mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-18 16:01:58 +01:00
*Removed ntfs/fat source and added them as custom libs (makes them easier to update later)
*Added sources of the custom libs to the branches *Fixed crash when switching from list layout to grid/carousel layout *Removed 1:1 copy option because its meaningless and almost the same as installing all partitions *Fixed install partition selection. This option needs a reset. Go to settings and reselect your option for this. *Fixed schinese and tchinese language modes (filename bugs. has to be schinese.lang and tchinese.lang like on SVN) *Fixed bug in sound buffer circle *Fixed incorrect behaviour of x-flip when selecting system like (thx Cyan for the patch) *Accept ios revision 65535 for Waninkokos IOSes (thx to PPSainity for pointing it out) *Merged the new theming style branch into trunk. Just as a reminder: ALL old themes will not work until the themers did port it to the new style! *Removed old theme style completely Theme example: The example file of the theme is the Default.them file. It can be found in the SVN trunk. Change in loading of themes: When selecting a theme now a list of all .them files in a folder is displayed. The image folder of that theme has to be in the same folder as the .them file. The image path is defined in the head of the .them file in the line with "Image-Folder: Example\n".
This commit is contained in:
parent
d62e41d601
commit
0f17471b27
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
|
9
libcustomext2fs/CREDITS
Normal file
9
libcustomext2fs/CREDITS
Normal file
@ -0,0 +1,9 @@
|
||||
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
|
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.
|
31
libcustomext2fs/Makefile
Normal file
31
libcustomext2fs/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
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
|
||||
|
||||
run: install
|
||||
$(MAKE) -C example
|
||||
$(MAKE) -C example run
|
||||
|
99
libcustomext2fs/include/ext2.h
Normal file
99
libcustomext2fs/include/ext2.h
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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 */
|
||||
#define CACHE_DEFAULT_PAGE_COUNT 8 /* The default number of pages in the cache */
|
||||
#define CACHE_DEFAULT_PAGE_SIZE 128 /* 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_DEFAULT (EXT2_FLAG_RW | EXT2_FLAG_64BITS | EXT2_FLAG_JOURNAL_DEV_OK)
|
||||
|
||||
/**
|
||||
* 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
|
132
libcustomext2fs/source/Makefile
Normal file
132
libcustomext2fs/source/Makefile
Normal file
@ -0,0 +1,132 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 = -O3 -Wall $(MACHDEP) $(INCLUDE) -DGEKKO \
|
||||
-DHAVE_UNISTD_H -DHAVE_SYS_STAT_H -DHAVE_SYS_TYPES_H -DHAVE_UTIME_H -DWORDS_BIGENDIAN \
|
||||
-DHAVE_ERRNO_H -DHAVE_STRDUP -DHAVE_SYS_RESOURCE_H
|
||||
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
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
308
libcustomext2fs/source/alloc.c
Normal file
308
libcustomext2fs/source/alloc.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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 <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++) {
|
||||
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);
|
||||
else
|
||||
ext2fs_fast_unmark_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;
|
||||
|
||||
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;
|
||||
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++;
|
||||
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;
|
||||
|
||||
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;
|
||||
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++;
|
||||
} 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;
|
||||
}
|
86
libcustomext2fs/source/alloc_sb.c
Normal file
86
libcustomext2fs/source/alloc_sb.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 <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 (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);
|
||||
|
||||
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;
|
||||
|
||||
num_blocks -= 2 + fs->inode_blocks_per_group + used_blks;
|
||||
|
||||
return num_blocks ;
|
||||
}
|
106
libcustomext2fs/source/alloc_stats.c
Normal file
106
libcustomext2fs/source/alloc_stats.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 <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_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;
|
||||
}
|
239
libcustomext2fs/source/alloc_tables.c
Normal file
239
libcustomext2fs/source/alloc_tables.c
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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 <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 offset, int size,
|
||||
int elem_size)
|
||||
{
|
||||
int flexbg, flexbg_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;
|
||||
|
||||
if (size > (int) (fs->super->s_blocks_per_group / 8))
|
||||
size = (int) fs->super->s_blocks_per_group / 8;
|
||||
|
||||
if (offset)
|
||||
offset -= 1;
|
||||
|
||||
/*
|
||||
* Don't do a long search if the previous block
|
||||
* search is still valid.
|
||||
*/
|
||||
if (start_blk && group % flexbg_size) {
|
||||
if (ext2fs_test_block_bitmap_range2(bmap, start_blk + elem_size,
|
||||
size))
|
||||
return start_blk + elem_size;
|
||||
}
|
||||
|
||||
start_blk = ext2fs_group_first_block2(fs, flexbg_size * flexbg);
|
||||
last_grp = group | (flexbg_size - 1);
|
||||
if (last_grp > fs->group_desc_count)
|
||||
last_grp = fs->group_desc_count;
|
||||
last_blk = ext2fs_group_last_block2(fs, last_grp);
|
||||
|
||||
/* Find the first available block */
|
||||
if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, 1, bmap,
|
||||
&first_free))
|
||||
return first_free;
|
||||
|
||||
if (ext2fs_get_free_blocks2(fs, first_free + offset, last_blk, size,
|
||||
bmap, &first_free))
|
||||
return first_free;
|
||||
|
||||
return first_free;
|
||||
}
|
||||
|
||||
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
|
||||
ext2fs_block_bitmap bmap)
|
||||
{
|
||||
errcode_t retval;
|
||||
blk64_t group_blk, start_blk, last_blk, new_blk, blk;
|
||||
dgrp_t last_grp = 0;
|
||||
int j, 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);
|
||||
rem_grps = last_grp - group;
|
||||
if (last_grp > fs->group_desc_count)
|
||||
last_grp = fs->group_desc_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 && ext2fs_block_bitmap_loc(fs, group - 1))
|
||||
prev_block = ext2fs_block_bitmap_loc(fs, group - 1);
|
||||
start_blk = flexbg_offset(fs, group, prev_block, bmap,
|
||||
0, 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 && ext2fs_inode_bitmap_loc(fs, group - 1))
|
||||
prev_block = ext2fs_inode_bitmap_loc(fs, group - 1);
|
||||
start_blk = flexbg_offset(fs, group, prev_block, bmap,
|
||||
flexbg_size, 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 && ext2fs_inode_table_loc(fs, group - 1))
|
||||
prev_block = ext2fs_inode_table_loc(fs, group - 1);
|
||||
if (last_grp == fs->group_desc_count)
|
||||
rem_grps = last_grp - group;
|
||||
group_blk = flexbg_offset(fs, group, prev_block, bmap,
|
||||
flexbg_size * 2,
|
||||
fs->inode_blocks_per_group *
|
||||
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;
|
||||
}
|
||||
|
327
libcustomext2fs/source/badblocks.c
Normal file
327
libcustomext2fs/source/badblocks.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* 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 <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 = (low+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;
|
||||
}
|
63
libcustomext2fs/source/bb_compat.c
Normal file
63
libcustomext2fs/source/bb_compat.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 <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 <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;
|
||||
|
||||
rec.bad_block_count = 0;
|
||||
rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
|
||||
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
|
256
libcustomext2fs/source/bitmaps.c
Normal file
256
libcustomext2fs/source/bitmaps.c
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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 <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"
|
||||
|
||||
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 = 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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
117
libcustomext2fs/source/bitops.c
Normal file
117
libcustomext2fs/source/bitops.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 <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);
|
||||
}
|
||||
|
638
libcustomext2fs/source/bitops.h
Normal file
638
libcustomext2fs/source/bitops.h
Normal file
@ -0,0 +1,638 @@
|
||||
/*
|
||||
* 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_
|
||||
|
||||
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_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_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
|
327
libcustomext2fs/source/blkmap64_ba.c
Normal file
327
libcustomext2fs/source/blkmap64_ba.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* 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 <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,
|
||||
};
|
477
libcustomext2fs/source/blknum.c
Normal file
477
libcustomext2fs/source/blknum.c
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* 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 "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 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
|
||||
*
|
||||
* XXX Ignoring 64-bit file system flag - most places where this is
|
||||
* called don't have access to the fs struct, and the high bits should
|
||||
* be 0 in the non-64-bit case anyway.
|
||||
*/
|
||||
blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode)
|
||||
{
|
||||
return (inode->i_file_acl |
|
||||
(__u64) inode->osd2.linux2.l_i_file_acl_high << 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the acl block of a file
|
||||
*/
|
||||
void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk)
|
||||
{
|
||||
inode->i_file_acl = blk;
|
||||
inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
|
||||
}
|
||||
|
622
libcustomext2fs/source/block.c
Normal file
622
libcustomext2fs/source/block.c
Normal file
@ -0,0 +1,622 @@
|
||||
/*
|
||||
* 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 <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)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
335
libcustomext2fs/source/bmap.c
Normal file
335
libcustomext2fs/source/bmap.c
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
}
|
||||
|
||||
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 (inode->i_flags & EXT4_EXTENTS_FL) {
|
||||
struct ext2fs_extent extent;
|
||||
unsigned int offset;
|
||||
|
||||
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
|
||||
if (retval)
|
||||
goto done;
|
||||
if (bmap_flags & BMAP_SET) {
|
||||
retval = ext2fs_extent_set_bmap(handle, block,
|
||||
*phys_blk, 0);
|
||||
goto done;
|
||||
}
|
||||
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;
|
||||
goto done;
|
||||
}
|
||||
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
|
||||
if (retval)
|
||||
goto done;
|
||||
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)) {
|
||||
retval = ext2fs_alloc_block(fs, b, block_buf, &b);
|
||||
if (retval)
|
||||
goto done;
|
||||
retval = ext2fs_extent_set_bmap(handle, block,
|
||||
(blk64_t) b, 0);
|
||||
if (retval)
|
||||
goto done;
|
||||
/* Update inode after setting extent */
|
||||
retval = ext2fs_read_inode(fs, ino, inode);
|
||||
if (retval)
|
||||
return retval;
|
||||
blocks_alloc++;
|
||||
*phys_blk = b;
|
||||
}
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!block_buf) {
|
||||
retval = ext2fs_get_array(2, fs->blocksize, &buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
block_buf = buf;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
61
libcustomext2fs/source/bmap64.h
Normal file
61
libcustomext2fs/source/bmap64.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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;
|
||||
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;
|
166
libcustomext2fs/source/bmove.c
Normal file
166
libcustomext2fs/source/bmove.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 <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_blocks(&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)))
|
||||
|
198
libcustomext2fs/source/brel_ma.c
Normal file
198
libcustomext2fs/source/brel_ma.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
}
|
103
libcustomext2fs/source/check_desc.c
Normal file
103
libcustomext2fs/source/check_desc.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
int j;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
retval = ext2fs_allocate_block_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);
|
||||
if (i == (fs->group_desc_count - 1))
|
||||
last_block = ext2fs_blocks_count(fs->super)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
461
libcustomext2fs/source/closefs.c
Normal file
461
libcustomext2fs/source/closefs.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
* 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 <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 (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);
|
||||
|
||||
if (group == fs->group_desc_count-1) {
|
||||
numblocks = (ext2fs_blocks_count(fs->super) -
|
||||
(blk64_t) fs->super->s_first_data_block) %
|
||||
(blk64_t) fs->super->s_blocks_per_group;
|
||||
if (!numblocks)
|
||||
numblocks = fs->super->s_blocks_per_group;
|
||||
} else
|
||||
numblocks = fs->super->s_blocks_per_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)
|
||||
{
|
||||
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
|
||||
|
||||
retval = io_channel_flush(fs->io);
|
||||
retval = write_primary_superblock(fs, super_shadow);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
fs->flags &= ~EXT2_FLAG_DIRTY;
|
||||
|
||||
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)
|
||||
{
|
||||
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_flush(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__)*/
|
10
libcustomext2fs/source/config.h
Normal file
10
libcustomext2fs/source/config.h
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UTIME_H 1
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#define HAVE_ERRNO_H 1
|
||||
#define EXT2_FLAT_INCLUDES 1
|
||||
#define HAVE_STRDUP 1
|
||||
#define HAVE_SYS_RESOURCE_H 1
|
73
libcustomext2fs/source/crc16.c
Normal file
73
libcustomext2fs/source/crc16.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* crc16.c
|
||||
*
|
||||
* This source code is licensed under the GNU General Public License,
|
||||
* Version 2. See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#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 */
|
286
libcustomext2fs/source/csum.c
Normal file
286
libcustomext2fs/source/csum.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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%
|
||||
*/
|
||||
|
||||
#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) {
|
||||
int 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++) {
|
||||
unsigned int old_csum = ext2fs_bg_checksum(fs, i);
|
||||
int old_unused = ext2fs_bg_itable_unused(fs, i);
|
||||
unsigned int old_flags = ext2fs_bg_flags(fs, i);
|
||||
int 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
|
||||
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 %016Lx%016Lx(%04x), grp %u(%04x): %04x=%04x\n",
|
||||
msg, *(long long *)&sb->s_uuid, *(long long *)&sb->s_uuid[8],
|
||||
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
|
414
libcustomext2fs/source/dblist.c
Normal file
414
libcustomext2fs/source/dblist.c
Normal file
@ -0,0 +1,414 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
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)
|
||||
return retval;
|
||||
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 -= 100;
|
||||
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;
|
||||
}
|
||||
|
79
libcustomext2fs/source/dblist_dir.c
Normal file
79
libcustomext2fs/source/dblist_dir.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
}
|
268
libcustomext2fs/source/dir_iterate.c
Normal file
268
libcustomext2fs/source/dir_iterate.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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 <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 (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;
|
||||
}
|
||||
|
126
libcustomext2fs/source/dirblock.c
Normal file
126
libcustomext2fs/source/dirblock.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 <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);
|
||||
}
|
||||
|
257
libcustomext2fs/source/dirhash.c
Normal file
257
libcustomext2fs/source/dirhash.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 <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++;
|
||||
case EXT2_HASH_LEGACY:
|
||||
hash = dx_hack_hash(name, len, unsigned_flag);
|
||||
break;
|
||||
case EXT2_HASH_HALF_MD4_UNSIGNED:
|
||||
unsigned_flag++;
|
||||
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++;
|
||||
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 < 4) {
|
||||
numberOfPages = 4;
|
||||
}
|
||||
|
||||
if (sectorsPerPage < 32) {
|
||||
sectorsPerPage = 32;
|
||||
}
|
||||
|
||||
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
|
||||
|
96
libcustomext2fs/source/dupfs.c
Normal file
96
libcustomext2fs/source/dupfs.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
|
||||
}
|
||||
|
51
libcustomext2fs/source/e2image.h
Normal file
51
libcustomext2fs/source/e2image.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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%
|
||||
*/
|
||||
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
74
libcustomext2fs/source/e2p/e2p.h
Normal file
74
libcustomext2fs/source/e2p/e2p.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* e2p.h --- header file for the e2p library
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* Needed by dirent.h on netbsd */
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "../ext2_fs.h"
|
||||
|
||||
#define E2P_FEATURE_COMPAT 0
|
||||
#define E2P_FEATURE_INCOMPAT 1
|
||||
#define E2P_FEATURE_RO_INCOMPAT 2
|
||||
#define E2P_FEATURE_TYPE_MASK 0x03
|
||||
|
||||
#define E2P_FEATURE_NEGATE_FLAG 0x80
|
||||
|
||||
#define E2P_FS_FEATURE 0
|
||||
#define E2P_JOURNAL_FEATURE 1
|
||||
|
||||
/* `options' for print_flags() */
|
||||
|
||||
#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
|
||||
|
||||
|
||||
int fgetflags (const char * name, unsigned long * flags);
|
||||
int fgetversion (const char * name, unsigned long * version);
|
||||
int fsetflags (const char * name, unsigned long flags);
|
||||
int fsetversion (const char * name, unsigned long version);
|
||||
int getflags (int fd, unsigned long * flags);
|
||||
int getversion (int fd, unsigned long * version);
|
||||
int iterate_on_dir (const char * dir_name,
|
||||
int (*func) (const char *, struct dirent *, void *),
|
||||
void * private);
|
||||
void list_super(struct ext2_super_block * s);
|
||||
void list_super2(struct ext2_super_block * s, FILE *f);
|
||||
void print_fs_errors (FILE * f, unsigned short errors);
|
||||
void print_flags (FILE * f, unsigned long flags, unsigned options);
|
||||
void print_fs_state (FILE * f, unsigned short state);
|
||||
int setflags (int fd, unsigned long flags);
|
||||
int setversion (int fd, unsigned long version);
|
||||
|
||||
const char *e2p_feature2string(int compat, unsigned int mask);
|
||||
const char *e2p_jrnl_feature2string(int compat, unsigned int mask);
|
||||
int e2p_string2feature(char *string, int *compat, unsigned int *mask);
|
||||
int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask);
|
||||
int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
|
||||
int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
|
||||
__u32 *clear_ok_array, int *type_err,
|
||||
unsigned int *mask_err);
|
||||
|
||||
int e2p_is_null_uuid(void *uu);
|
||||
void e2p_uuid_to_str(void *uu, char *out);
|
||||
const char *e2p_uuid2str(void *uu);
|
||||
|
||||
const char *e2p_hash2string(int num);
|
||||
int e2p_string2hash(char *string);
|
||||
|
||||
const char *e2p_mntopt2string(unsigned int mask);
|
||||
int e2p_string2mntopt(char *string, unsigned int *mask);
|
||||
int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
|
||||
|
||||
unsigned long parse_num_blocks(const char *arg, int log_block_size);
|
||||
unsigned long long parse_num_blocks2(const char *arg, int log_block_size);
|
||||
|
||||
char *e2p_os2string(int os_type);
|
||||
int e2p_string2os(char *str);
|
||||
|
||||
unsigned int e2p_percent(int percent, unsigned int base);
|
385
libcustomext2fs/source/e2p/feature.c
Normal file
385
libcustomext2fs/source/e2p/feature.c
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* feature.c --- convert between features and strings
|
||||
*
|
||||
* Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
#include <ext2fs/ext2fs.h>
|
||||
#include <ext2fs/jfs_user.h>
|
||||
|
||||
struct feature {
|
||||
int compat;
|
||||
unsigned int mask;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static struct feature feature_list[] = {
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
|
||||
"dir_prealloc" },
|
||||
{ E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
|
||||
"has_journal" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
|
||||
"imagic_inodes" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
|
||||
"ext_attr" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
|
||||
"dir_index" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
|
||||
"resize_inode" },
|
||||
{ E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG,
|
||||
"lazy_bg" },
|
||||
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
|
||||
"sparse_super" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
|
||||
"large_file" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE,
|
||||
"huge_file" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
|
||||
"uninit_bg" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
|
||||
"uninit_groups" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK,
|
||||
"dir_nlink" },
|
||||
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE,
|
||||
"extra_isize" },
|
||||
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
|
||||
"compression" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
|
||||
"filetype" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
|
||||
"needs_recovery" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
|
||||
"journal_dev" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
|
||||
"extent" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
|
||||
"extents" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
|
||||
"meta_bg" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT,
|
||||
"64bit" },
|
||||
{ E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG,
|
||||
"flex_bg"},
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct feature jrnl_feature_list[] = {
|
||||
{ E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM,
|
||||
"journal_checksum" },
|
||||
|
||||
{ E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE,
|
||||
"journal_incompat_revoke" },
|
||||
{ E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT,
|
||||
"journal_async_commit" },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_feature2string(int compat, unsigned int mask)
|
||||
{
|
||||
struct feature *f;
|
||||
static char buf[20];
|
||||
char fchar;
|
||||
int fnum;
|
||||
|
||||
for (f = feature_list; f->string; f++) {
|
||||
if ((compat == f->compat) &&
|
||||
(mask == f->mask))
|
||||
return f->string;
|
||||
}
|
||||
switch (compat) {
|
||||
case E2P_FEATURE_COMPAT:
|
||||
fchar = 'C';
|
||||
break;
|
||||
case E2P_FEATURE_INCOMPAT:
|
||||
fchar = 'I';
|
||||
break;
|
||||
case E2P_FEATURE_RO_INCOMPAT:
|
||||
fchar = 'R';
|
||||
break;
|
||||
default:
|
||||
fchar = '?';
|
||||
break;
|
||||
}
|
||||
for (fnum = 0; mask >>= 1; fnum++);
|
||||
sprintf(buf, "FEATURE_%c%d", fchar, fnum);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
|
||||
{
|
||||
struct feature *f;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (f = feature_list; f->string; f++) {
|
||||
if (!strcasecmp(string, f->string)) {
|
||||
*compat_type = f->compat;
|
||||
*mask = f->mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "FEATURE_", 8))
|
||||
return 1;
|
||||
|
||||
switch (string[8]) {
|
||||
case 'c':
|
||||
case 'C':
|
||||
*compat_type = E2P_FEATURE_COMPAT;
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
*compat_type = E2P_FEATURE_INCOMPAT;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
*compat_type = E2P_FEATURE_RO_INCOMPAT;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
if (string[9] == 0)
|
||||
return 1;
|
||||
num = strtol(string+9, &eptr, 10);
|
||||
if (num > 32 || num < 0)
|
||||
return 1;
|
||||
if (*eptr)
|
||||
return 1;
|
||||
*mask = 1 << num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *e2p_jrnl_feature2string(int compat, unsigned int mask)
|
||||
{
|
||||
struct feature *f;
|
||||
static char buf[20];
|
||||
char fchar;
|
||||
int fnum;
|
||||
|
||||
for (f = jrnl_feature_list; f->string; f++) {
|
||||
if ((compat == f->compat) &&
|
||||
(mask == f->mask))
|
||||
return f->string;
|
||||
}
|
||||
switch (compat) {
|
||||
case E2P_FEATURE_COMPAT:
|
||||
fchar = 'C';
|
||||
break;
|
||||
case E2P_FEATURE_INCOMPAT:
|
||||
fchar = 'I';
|
||||
break;
|
||||
case E2P_FEATURE_RO_INCOMPAT:
|
||||
fchar = 'R';
|
||||
break;
|
||||
default:
|
||||
fchar = '?';
|
||||
break;
|
||||
}
|
||||
for (fnum = 0; mask >>= 1; fnum++);
|
||||
sprintf(buf, "FEATURE_%c%d", fchar, fnum);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask)
|
||||
{
|
||||
struct feature *f;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (f = jrnl_feature_list; f->string; f++) {
|
||||
if (!strcasecmp(string, f->string)) {
|
||||
*compat_type = f->compat;
|
||||
*mask = f->mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "FEATURE_", 8))
|
||||
return 1;
|
||||
|
||||
switch (string[8]) {
|
||||
case 'c':
|
||||
case 'C':
|
||||
*compat_type = E2P_FEATURE_COMPAT;
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
*compat_type = E2P_FEATURE_INCOMPAT;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
*compat_type = E2P_FEATURE_RO_INCOMPAT;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
if (string[9] == 0)
|
||||
return 1;
|
||||
num = strtol(string+9, &eptr, 10);
|
||||
if (num > 32 || num < 0)
|
||||
return 1;
|
||||
if (*eptr)
|
||||
return 1;
|
||||
*mask = 1 << num;
|
||||
return 0;
|
||||
}
|
||||
static char *skip_over_blanks(char *cp)
|
||||
{
|
||||
while (*cp && isspace((int)*cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *skip_over_word(char *cp)
|
||||
{
|
||||
while (*cp && !isspace((int)*cp) && *cp != ',')
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a feature set array as requested by the user. The ok_array,
|
||||
* if set, allows the application to limit what features the user is
|
||||
* allowed to set or clear using this function. If clear_ok_array is set,
|
||||
* then use it tell whether or not it is OK to clear a filesystem feature.
|
||||
*/
|
||||
int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
|
||||
__u32 *clear_ok_array, int *type_err,
|
||||
unsigned int *mask_err)
|
||||
{
|
||||
char *cp, *buf, *next;
|
||||
int neg;
|
||||
unsigned int mask;
|
||||
int compat_type;
|
||||
int rc = 0;
|
||||
|
||||
if (!clear_ok_array)
|
||||
clear_ok_array = ok_array;
|
||||
|
||||
if (type_err)
|
||||
*type_err = 0;
|
||||
if (mask_err)
|
||||
*mask_err = 0;
|
||||
|
||||
buf = malloc(strlen(str)+1);
|
||||
if (!buf)
|
||||
return 1;
|
||||
strcpy(buf, str);
|
||||
for (cp = buf; cp && *cp; cp = next ? next+1 : 0) {
|
||||
neg = 0;
|
||||
cp = skip_over_blanks(cp);
|
||||
next = skip_over_word(cp);
|
||||
|
||||
if (*next == 0)
|
||||
next = 0;
|
||||
else
|
||||
*next = 0;
|
||||
|
||||
if ((strcasecmp(cp, "none") == 0) ||
|
||||
(strcasecmp(cp, "clear") == 0)) {
|
||||
compat_array[0] = 0;
|
||||
compat_array[1] = 0;
|
||||
compat_array[2] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*cp) {
|
||||
case '-':
|
||||
case '^':
|
||||
neg++;
|
||||
case '+':
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (e2p_string2feature(cp, &compat_type, &mask)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
if (neg) {
|
||||
if (clear_ok_array &&
|
||||
!(clear_ok_array[compat_type] & mask)) {
|
||||
rc = 1;
|
||||
if (type_err)
|
||||
*type_err = (compat_type |
|
||||
E2P_FEATURE_NEGATE_FLAG);
|
||||
if (mask_err)
|
||||
*mask_err = mask;
|
||||
break;
|
||||
}
|
||||
compat_array[compat_type] &= ~mask;
|
||||
} else {
|
||||
if (ok_array && !(ok_array[compat_type] & mask)) {
|
||||
rc = 1;
|
||||
if (type_err)
|
||||
*type_err = compat_type;
|
||||
if (mask_err)
|
||||
*mask_err = mask;
|
||||
break;
|
||||
}
|
||||
compat_array[compat_type] |= mask;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
|
||||
{
|
||||
return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int compat, compat2, i;
|
||||
unsigned int mask, mask2;
|
||||
const char *str;
|
||||
struct feature *f;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (i == 0) {
|
||||
f = feature_list;
|
||||
printf("Feature list:\n");
|
||||
} else {
|
||||
printf("\nJournal feature list:\n");
|
||||
f = jrnl_feature_list;
|
||||
}
|
||||
for (; f->string; f++) {
|
||||
if (i == 0) {
|
||||
e2p_string2feature((char *)f->string, &compat,
|
||||
&mask);
|
||||
str = e2p_feature2string(compat, mask);
|
||||
} else {
|
||||
e2p_jrnl_string2feature((char *)f->string,
|
||||
&compat, &mask);
|
||||
str = e2p_jrnl_feature2string(compat, mask);
|
||||
}
|
||||
|
||||
printf("\tCompat = %d, Mask = %u, %s\n",
|
||||
compat, mask, f->string);
|
||||
if (strcmp(f->string, str)) {
|
||||
if (e2p_string2feature((char *) str, &compat2,
|
||||
&mask2) ||
|
||||
(compat2 != compat) ||
|
||||
(mask2 != mask)) {
|
||||
fprintf(stderr, "Failure!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
95
libcustomext2fs/source/e2p/fgetflags.c
Normal file
95
libcustomext2fs/source/e2p/fgetflags.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* fgetflags.c - Get a file flags on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
int fgetflags (const char * name, unsigned long * flags)
|
||||
{
|
||||
#if HAVE_STAT_FLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
|
||||
struct stat buf;
|
||||
if (stat (name, &buf) == -1)
|
||||
return -1;
|
||||
|
||||
*flags = 0;
|
||||
#ifdef UF_IMMUTABLE
|
||||
if (buf.st_flags & UF_IMMUTABLE)
|
||||
*flags |= EXT2_IMMUTABLE_FL;
|
||||
#endif
|
||||
#ifdef UF_APPEND
|
||||
if (buf.st_flags & UF_APPEND)
|
||||
*flags |= EXT2_APPEND_FL;
|
||||
#endif
|
||||
#ifdef UF_NODUMP
|
||||
if (buf.st_flags & UF_NODUMP)
|
||||
*flags |= EXT2_NODUMP_FL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
int fd, r, f, save_errno = 0;
|
||||
|
||||
if (!lstat(name, &buf) &&
|
||||
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
|
||||
goto notsupp;
|
||||
}
|
||||
#if !APPLE_DARWIN
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
*flags = f;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return r;
|
||||
#else
|
||||
f = -1;
|
||||
save_errno = syscall(SYS_fsctl, name, EXT2_IOC_GETFLAGS, &f, 0);
|
||||
*flags = f;
|
||||
return (save_errno);
|
||||
#endif
|
||||
#endif /* HAVE_EXT2_IOCTLS */
|
||||
#endif
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
69
libcustomext2fs/source/e2p/fgetversion.c
Normal file
69
libcustomext2fs/source/e2p/fgetversion.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* fgetversion.c - Get a file version on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
int fgetversion (const char * name, unsigned long * version)
|
||||
{
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#if !APPLE_DARWIN
|
||||
int fd, r, ver, save_errno = 0;
|
||||
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
*version = ver;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return r;
|
||||
#else
|
||||
int ver=-1, err;
|
||||
err = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0);
|
||||
*version = ver;
|
||||
return(err);
|
||||
#endif
|
||||
#else /* ! HAVE_EXT2_IOCTLS */
|
||||
extern int errno;
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
#endif /* ! HAVE_EXT2_IOCTLS */
|
||||
}
|
100
libcustomext2fs/source/e2p/fsetflags.c
Normal file
100
libcustomext2fs/source/e2p/fsetflags.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* fsetflags.c - Set a file flags on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
/*
|
||||
* Deal with lame glibc's that define this function without actually
|
||||
* implementing it. Can you say "attractive nuisance", boys and girls?
|
||||
* I knew you could!
|
||||
*/
|
||||
#ifdef __linux__
|
||||
#undef HAVE_CHFLAGS
|
||||
#endif
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
int fsetflags (const char * name, unsigned long flags)
|
||||
{
|
||||
#if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
|
||||
struct stat buf;
|
||||
unsigned long bsd_flags = 0;
|
||||
|
||||
#ifdef UF_IMMUTABLE
|
||||
if (flags & EXT2_IMMUTABLE_FL)
|
||||
bsd_flags |= UF_IMMUTABLE;
|
||||
#endif
|
||||
#ifdef UF_APPEND
|
||||
if (flags & EXT2_APPEND_FL)
|
||||
bsd_flags |= UF_APPEND;
|
||||
#endif
|
||||
#ifdef UF_NODUMP
|
||||
if (flags & EXT2_NODUMP_FL)
|
||||
bsd_flags |= UF_NODUMP;
|
||||
#endif
|
||||
|
||||
return chflags (name, bsd_flags);
|
||||
#else
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
int fd, r, f, save_errno = 0;
|
||||
|
||||
if (!lstat(name, &buf) &&
|
||||
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
|
||||
goto notsupp;
|
||||
}
|
||||
#if !APPLE_DARWIN
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
f = (int) flags;
|
||||
r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
#else
|
||||
f = (int) flags;
|
||||
return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0);
|
||||
#endif
|
||||
return r;
|
||||
#endif /* HAVE_EXT2_IOCTLS */
|
||||
#endif
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
67
libcustomext2fs/source/e2p/fsetversion.c
Normal file
67
libcustomext2fs/source/e2p/fsetversion.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* fsetversion.c - Set a file version on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
|
||||
#else
|
||||
#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
int fsetversion (const char * name, unsigned long version)
|
||||
{
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#if !APPLE_DARWIN
|
||||
int fd, r, ver, save_errno = 0;
|
||||
|
||||
fd = open (name, OPEN_FLAGS);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
ver = (int) version;
|
||||
r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
|
||||
if (r == -1)
|
||||
save_errno = errno;
|
||||
close (fd);
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return r;
|
||||
#else
|
||||
int ver = (int)version;
|
||||
return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0);
|
||||
#endif
|
||||
#else /* ! HAVE_EXT2_IOCTLS */
|
||||
extern int errno;
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
#endif /* ! HAVE_EXT2_IOCTLS */
|
||||
}
|
66
libcustomext2fs/source/e2p/getflags.c
Normal file
66
libcustomext2fs/source/e2p/getflags.c
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* getflags.c - Get a file flags on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
int getflags (int fd, unsigned long * flags)
|
||||
{
|
||||
#if HAVE_STAT_FLAGS
|
||||
struct stat buf;
|
||||
if (fstat (fd, &buf) == -1)
|
||||
return -1;
|
||||
|
||||
*flags = 0;
|
||||
#ifdef UF_IMMUTABLE
|
||||
if (buf.st_flags & UF_IMMUTABLE)
|
||||
*flags |= EXT2_IMMUTABLE_FL;
|
||||
#endif
|
||||
#ifdef UF_APPEND
|
||||
if (buf.st_flags & UF_APPEND)
|
||||
*flags |= EXT2_APPEND_FL;
|
||||
#endif
|
||||
#ifdef UF_NODUMP
|
||||
if (buf.st_flags & UF_NODUMP)
|
||||
*flags |= EXT2_NODUMP_FL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
int r, f;
|
||||
|
||||
if (!fstat(fd, &buf) &&
|
||||
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode))
|
||||
goto notsupp;
|
||||
r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
|
||||
*flags = f;
|
||||
return r;
|
||||
#endif /* HAVE_EXT2_IOCTLS */
|
||||
#endif
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
41
libcustomext2fs/source/e2p/getversion.c
Normal file
41
libcustomext2fs/source/e2p/getversion.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* getversion.c - Get a file version on an ext2 file system
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
int getversion (int fd, unsigned long * version)
|
||||
{
|
||||
#if HAVE_EXT2_IOCTLS
|
||||
int r, ver;
|
||||
|
||||
r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
|
||||
*version = ver;
|
||||
return 0;
|
||||
#else /* ! HAVE_EXT2_IOCTLS */
|
||||
extern int errno;
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
#endif /* ! HAVE_EXT2_IOCTLS */
|
||||
}
|
71
libcustomext2fs/source/e2p/hashstr.c
Normal file
71
libcustomext2fs/source/e2p/hashstr.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* feature.c --- convert between features and strings
|
||||
*
|
||||
* Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct hash {
|
||||
int num;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static struct hash hash_list[] = {
|
||||
{ EXT2_HASH_LEGACY, "legacy" },
|
||||
{ EXT2_HASH_HALF_MD4, "half_md4" },
|
||||
{ EXT2_HASH_TEA, "tea" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_hash2string(int num)
|
||||
{
|
||||
struct hash *p;
|
||||
static char buf[20];
|
||||
|
||||
for (p = hash_list; p->string; p++) {
|
||||
if (num == p->num)
|
||||
return p->string;
|
||||
}
|
||||
sprintf(buf, "HASHALG_%d", num);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the hash algorithm, or -1 on error
|
||||
*/
|
||||
int e2p_string2hash(char *string)
|
||||
{
|
||||
struct hash *p;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (p = hash_list; p->string; p++) {
|
||||
if (!strcasecmp(string, p->string)) {
|
||||
return p->num;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "HASHALG_", 8))
|
||||
return -1;
|
||||
|
||||
if (string[8] == 0)
|
||||
return -1;
|
||||
num = strtol(string+8, &eptr, 10);
|
||||
if (num > 255 || num < 0)
|
||||
return -1;
|
||||
if (*eptr)
|
||||
return -1;
|
||||
return num;
|
||||
}
|
||||
|
75
libcustomext2fs/source/e2p/iod.c
Normal file
75
libcustomext2fs/source/e2p/iod.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* iod.c - Iterate a function on each entry of a directory
|
||||
*
|
||||
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
/*
|
||||
* History:
|
||||
* 93/10/30 - Creation
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int iterate_on_dir (const char * dir_name,
|
||||
int (*func) (const char *, struct dirent *, void *),
|
||||
void * private)
|
||||
{
|
||||
DIR * dir;
|
||||
struct dirent *de, *dep;
|
||||
int max_len = -1, len, ret = 0;
|
||||
|
||||
#if HAVE_PATHCONF && defined(_PC_NAME_MAX)
|
||||
max_len = pathconf(dir_name, _PC_NAME_MAX);
|
||||
#endif
|
||||
if (max_len == -1) {
|
||||
#ifdef _POSIX_NAME_MAX
|
||||
max_len = _POSIX_NAME_MAX;
|
||||
#else
|
||||
#ifdef NAME_MAX
|
||||
max_len = NAME_MAX;
|
||||
#else
|
||||
max_len = 256;
|
||||
#endif /* NAME_MAX */
|
||||
#endif /* _POSIX_NAME_MAX */
|
||||
}
|
||||
max_len += sizeof(struct dirent);
|
||||
|
||||
de = malloc(max_len+1);
|
||||
if (!de)
|
||||
return -1;
|
||||
memset(de, 0, max_len+1);
|
||||
|
||||
dir = opendir (dir_name);
|
||||
if (dir == NULL) {
|
||||
free(de);
|
||||
return -1;
|
||||
}
|
||||
while ((dep = readdir (dir))) {
|
||||
#ifdef HAVE_RECLEN_DIRENT
|
||||
len = dep->d_reclen;
|
||||
if (len > max_len)
|
||||
len = max_len;
|
||||
#else
|
||||
len = sizeof(struct dirent);
|
||||
#endif
|
||||
memcpy(de, dep, len);
|
||||
if ((*func)(dir_name, de, private))
|
||||
ret++;
|
||||
}
|
||||
free(de);
|
||||
closedir(dir);
|
||||
return ret;
|
||||
}
|
403
libcustomext2fs/source/e2p/ls.c
Normal file
403
libcustomext2fs/source/e2p/ls.c
Normal file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
* ls.c - List the contents of an ext2fs superblock
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
|
||||
* Laboratoire MASI, Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
static void print_user (unsigned short uid, FILE *f)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
fprintf(f, "%u ", uid);
|
||||
pw = getpwuid (uid);
|
||||
if (pw == NULL)
|
||||
fprintf(f, "(user unknown)\n");
|
||||
else
|
||||
fprintf(f, "(user %s)\n", pw->pw_name);
|
||||
}
|
||||
|
||||
static void print_group (unsigned short gid, FILE *f)
|
||||
{
|
||||
struct group *gr;
|
||||
|
||||
fprintf(f, "%u ", gid);
|
||||
gr = getgrgid (gid);
|
||||
if (gr == NULL)
|
||||
fprintf(f, "(group unknown)\n");
|
||||
else
|
||||
fprintf(f, "(group %s)\n", gr->gr_name);
|
||||
}
|
||||
|
||||
#define MONTH_INT (86400 * 30)
|
||||
#define WEEK_INT (86400 * 7)
|
||||
#define DAY_INT (86400)
|
||||
#define HOUR_INT (60 * 60)
|
||||
#define MINUTE_INT (60)
|
||||
|
||||
static const char *interval_string(unsigned int secs)
|
||||
{
|
||||
static char buf[256], tmp[80];
|
||||
int hr, min, num;
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
if (secs == 0)
|
||||
return "<none>";
|
||||
|
||||
if (secs >= MONTH_INT) {
|
||||
num = secs / MONTH_INT;
|
||||
secs -= num*MONTH_INT;
|
||||
sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
|
||||
}
|
||||
if (secs >= WEEK_INT) {
|
||||
num = secs / WEEK_INT;
|
||||
secs -= num*WEEK_INT;
|
||||
sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
|
||||
num, (num>1) ? "s" : "");
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
if (secs >= DAY_INT) {
|
||||
num = secs / DAY_INT;
|
||||
secs -= num*DAY_INT;
|
||||
sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
|
||||
num, (num>1) ? "s" : "");
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
if (secs > 0) {
|
||||
hr = secs / HOUR_INT;
|
||||
secs -= hr*HOUR_INT;
|
||||
min = secs / MINUTE_INT;
|
||||
secs -= min*MINUTE_INT;
|
||||
sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
|
||||
hr, min, secs);
|
||||
strcat(buf, tmp);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void print_features(struct ext2_super_block * s, FILE *f)
|
||||
{
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
int i, j, printed=0;
|
||||
__u32 *mask = &s->s_feature_compat, m;
|
||||
|
||||
fprintf(f, "Filesystem features: ");
|
||||
for (i=0; i <3; i++,mask++) {
|
||||
for (j=0,m=1; j < 32; j++, m<<=1) {
|
||||
if (*mask & m) {
|
||||
fprintf(f, " %s", e2p_feature2string(i, m));
|
||||
printed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (printed == 0)
|
||||
fprintf(f, " (none)");
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_mntopts(struct ext2_super_block * s, FILE *f)
|
||||
{
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
int i, printed=0;
|
||||
__u32 mask = s->s_default_mount_opts, m;
|
||||
|
||||
fprintf(f, "Default mount options: ");
|
||||
if (mask & EXT3_DEFM_JMODE) {
|
||||
fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
|
||||
printed++;
|
||||
}
|
||||
for (i=0,m=1; i < 32; i++, m<<=1) {
|
||||
if (m & EXT3_DEFM_JMODE)
|
||||
continue;
|
||||
if (mask & m) {
|
||||
fprintf(f, " %s", e2p_mntopt2string(m));
|
||||
printed++;
|
||||
}
|
||||
}
|
||||
if (printed == 0)
|
||||
fprintf(f, " (none)");
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_super_flags(struct ext2_super_block * s, FILE *f)
|
||||
{
|
||||
int flags_found = 0;
|
||||
|
||||
if (s->s_flags == 0)
|
||||
return;
|
||||
|
||||
fputs("Filesystem flags: ", f);
|
||||
if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) {
|
||||
fputs("signed_directory_hash ", f);
|
||||
flags_found++;
|
||||
}
|
||||
if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) {
|
||||
fputs("unsigned_directory_hash ", f);
|
||||
flags_found++;
|
||||
}
|
||||
if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) {
|
||||
fputs("test_filesystem ", f);
|
||||
flags_found++;
|
||||
}
|
||||
if (flags_found)
|
||||
fputs("\n", f);
|
||||
else
|
||||
fputs("(none)\n", f);
|
||||
}
|
||||
|
||||
static __u64 e2p_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);
|
||||
}
|
||||
|
||||
static __u64 e2p_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);
|
||||
}
|
||||
|
||||
static __u64 e2p_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);
|
||||
}
|
||||
|
||||
#ifndef EXT2_INODE_SIZE
|
||||
#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
|
||||
#endif
|
||||
|
||||
#ifndef EXT2_GOOD_OLD_REV
|
||||
#define EXT2_GOOD_OLD_REV 0
|
||||
#endif
|
||||
|
||||
void list_super2(struct ext2_super_block * sb, FILE *f)
|
||||
{
|
||||
int inode_blocks_per_group;
|
||||
char buf[80], *str;
|
||||
time_t tm;
|
||||
|
||||
inode_blocks_per_group = (((sb->s_inodes_per_group *
|
||||
EXT2_INODE_SIZE(sb)) +
|
||||
EXT2_BLOCK_SIZE(sb) - 1) /
|
||||
EXT2_BLOCK_SIZE(sb));
|
||||
if (sb->s_volume_name[0]) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
||||
} else
|
||||
strcpy(buf, "<none>");
|
||||
fprintf(f, "Filesystem volume name: %s\n", buf);
|
||||
if (sb->s_last_mounted[0]) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
|
||||
} else
|
||||
strcpy(buf, "<not available>");
|
||||
fprintf(f, "Last mounted on: %s\n", buf);
|
||||
fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid));
|
||||
fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic);
|
||||
fprintf(f, "Filesystem revision #: %d", sb->s_rev_level);
|
||||
if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
|
||||
fprintf(f, " (original)\n");
|
||||
#ifdef EXT2_DYNAMIC_REV
|
||||
} else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
|
||||
fprintf(f, " (dynamic)\n");
|
||||
#endif
|
||||
} else
|
||||
fprintf(f, " (unknown)\n");
|
||||
print_features(sb, f);
|
||||
print_super_flags(sb, f);
|
||||
print_mntopts(sb, f);
|
||||
if (sb->s_mount_opts[0])
|
||||
fprintf(f, "Mount options: %s\n", sb->s_mount_opts);
|
||||
fprintf(f, "Filesystem state: ");
|
||||
print_fs_state (f, sb->s_state);
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, "Errors behavior: ");
|
||||
print_fs_errors(f, sb->s_errors);
|
||||
fprintf(f, "\n");
|
||||
str = e2p_os2string(sb->s_creator_os);
|
||||
fprintf(f, "Filesystem OS type: %s\n", str);
|
||||
free(str);
|
||||
fprintf(f, "Inode count: %u\n", sb->s_inodes_count);
|
||||
fprintf(f, "Block count: %llu\n", e2p_blocks_count(sb));
|
||||
fprintf(f, "Reserved block count: %llu\n", e2p_r_blocks_count(sb));
|
||||
fprintf(f, "Free blocks: %llu\n", e2p_free_blocks_count(sb));
|
||||
fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count);
|
||||
fprintf(f, "First block: %u\n", sb->s_first_data_block);
|
||||
fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb));
|
||||
fprintf(f, "Fragment size: %u\n", EXT2_FRAG_SIZE(sb));
|
||||
if (sb->s_reserved_gdt_blocks)
|
||||
fprintf(f, "Reserved GDT blocks: %u\n",
|
||||
sb->s_reserved_gdt_blocks);
|
||||
fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group);
|
||||
fprintf(f, "Fragments per group: %u\n", sb->s_frags_per_group);
|
||||
fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group);
|
||||
fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group);
|
||||
if (sb->s_raid_stride)
|
||||
fprintf(f, "RAID stride: %u\n",
|
||||
sb->s_raid_stride);
|
||||
if (sb->s_raid_stripe_width)
|
||||
fprintf(f, "RAID stripe width: %u\n",
|
||||
sb->s_raid_stripe_width);
|
||||
if (sb->s_first_meta_bg)
|
||||
fprintf(f, "First meta block group: %u\n",
|
||||
sb->s_first_meta_bg);
|
||||
if (sb->s_log_groups_per_flex)
|
||||
fprintf(f, "Flex block group size: %u\n",
|
||||
1 << sb->s_log_groups_per_flex);
|
||||
if (sb->s_mkfs_time) {
|
||||
tm = sb->s_mkfs_time;
|
||||
fprintf(f, "Filesystem created: %s", ctime(&tm));
|
||||
}
|
||||
tm = sb->s_mtime;
|
||||
fprintf(f, "Last mount time: %s",
|
||||
sb->s_mtime ? ctime(&tm) : "n/a\n");
|
||||
tm = sb->s_wtime;
|
||||
fprintf(f, "Last write time: %s", ctime(&tm));
|
||||
fprintf(f, "Mount count: %u\n", sb->s_mnt_count);
|
||||
fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count);
|
||||
tm = sb->s_lastcheck;
|
||||
fprintf(f, "Last checked: %s", ctime(&tm));
|
||||
fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval,
|
||||
interval_string(sb->s_checkinterval));
|
||||
if (sb->s_checkinterval)
|
||||
{
|
||||
time_t next;
|
||||
|
||||
next = sb->s_lastcheck + sb->s_checkinterval;
|
||||
fprintf(f, "Next check after: %s", ctime(&next));
|
||||
}
|
||||
#define POW2(x) ((__u64) 1 << (x))
|
||||
if (sb->s_kbytes_written) {
|
||||
fprintf(f, "Lifetime writes: ");
|
||||
if (sb->s_kbytes_written < POW2(13))
|
||||
fprintf(f, "%llu kB\n", sb->s_kbytes_written);
|
||||
else if (sb->s_kbytes_written < POW2(23))
|
||||
fprintf(f, "%llu MB\n",
|
||||
(sb->s_kbytes_written + POW2(9)) >> 10);
|
||||
else if (sb->s_kbytes_written < POW2(33))
|
||||
fprintf(f, "%llu GB\n",
|
||||
(sb->s_kbytes_written + POW2(19)) >> 20);
|
||||
else if (sb->s_kbytes_written < POW2(43))
|
||||
fprintf(f, "%llu TB\n",
|
||||
(sb->s_kbytes_written + POW2(29)) >> 30);
|
||||
else
|
||||
fprintf(f, "%llu PB\n",
|
||||
(sb->s_kbytes_written + POW2(39)) >> 40);
|
||||
}
|
||||
fprintf(f, "Reserved blocks uid: ");
|
||||
print_user(sb->s_def_resuid, f);
|
||||
fprintf(f, "Reserved blocks gid: ");
|
||||
print_group(sb->s_def_resgid, f);
|
||||
if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
|
||||
fprintf(f, "First inode: %d\n", sb->s_first_ino);
|
||||
fprintf(f, "Inode size: %d\n", sb->s_inode_size);
|
||||
if (sb->s_min_extra_isize)
|
||||
fprintf(f, "Required extra isize: %d\n",
|
||||
sb->s_min_extra_isize);
|
||||
if (sb->s_want_extra_isize)
|
||||
fprintf(f, "Desired extra isize: %d\n",
|
||||
sb->s_want_extra_isize);
|
||||
}
|
||||
if (!e2p_is_null_uuid(sb->s_journal_uuid))
|
||||
fprintf(f, "Journal UUID: %s\n",
|
||||
e2p_uuid2str(sb->s_journal_uuid));
|
||||
if (sb->s_journal_inum)
|
||||
fprintf(f, "Journal inode: %u\n",
|
||||
sb->s_journal_inum);
|
||||
if (sb->s_journal_dev)
|
||||
fprintf(f, "Journal device: 0x%04x\n",
|
||||
sb->s_journal_dev);
|
||||
if (sb->s_last_orphan)
|
||||
fprintf(f, "First orphan inode: %u\n",
|
||||
sb->s_last_orphan);
|
||||
if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
|
||||
sb->s_def_hash_version)
|
||||
fprintf(f, "Default directory hash: %s\n",
|
||||
e2p_hash2string(sb->s_def_hash_version));
|
||||
if (!e2p_is_null_uuid(sb->s_hash_seed))
|
||||
fprintf(f, "Directory Hash Seed: %s\n",
|
||||
e2p_uuid2str(sb->s_hash_seed));
|
||||
if (sb->s_jnl_backup_type) {
|
||||
fprintf(f, "Journal backup: ");
|
||||
switch (sb->s_jnl_backup_type) {
|
||||
case 1:
|
||||
fprintf(f, "inode blocks\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(f, "type %u\n", sb->s_jnl_backup_type);
|
||||
}
|
||||
}
|
||||
if (sb->s_snapshot_inum) {
|
||||
fprintf(f, "Snapshot inode: %u\n",
|
||||
sb->s_snapshot_inum);
|
||||
fprintf(f, "Snapshot ID: %u\n",
|
||||
sb->s_snapshot_id);
|
||||
fprintf(f, "Snapshot reserved blocks: %llu\n",
|
||||
sb->s_snapshot_r_blocks_count);
|
||||
}
|
||||
if (sb->s_snapshot_list)
|
||||
fprintf(f, "Snapshot list head: %u\n",
|
||||
sb->s_snapshot_list);
|
||||
if (sb->s_error_count)
|
||||
fprintf(f, "FS Error count: %u\n",
|
||||
sb->s_error_count);
|
||||
if (sb->s_first_error_time) {
|
||||
tm = sb->s_first_error_time;
|
||||
fprintf(f, "First error time: %s", ctime(&tm));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, (char *)sb->s_first_error_func,
|
||||
sizeof(sb->s_first_error_func));
|
||||
fprintf(f, "First error function: %s\n", buf);
|
||||
fprintf(f, "First error line #: %u\n",
|
||||
sb->s_first_error_line);
|
||||
fprintf(f, "First error inode #: %u\n",
|
||||
sb->s_first_error_ino);
|
||||
fprintf(f, "First error block #: %llu\n",
|
||||
sb->s_first_error_block);
|
||||
}
|
||||
if (sb->s_last_error_time) {
|
||||
tm = sb->s_last_error_time;
|
||||
fprintf(f, "Last error time: %s", ctime(&tm));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, (char *) sb->s_last_error_func,
|
||||
sizeof(sb->s_last_error_func));
|
||||
fprintf(f, "Last error function: %s\n", buf);
|
||||
fprintf(f, "Last error line #: %u\n",
|
||||
sb->s_last_error_line);
|
||||
fprintf(f, "Last error inode #: %u\n",
|
||||
sb->s_last_error_ino);
|
||||
fprintf(f, "Last error block #: %llu\n",
|
||||
sb->s_last_error_block);
|
||||
}
|
||||
}
|
||||
|
||||
void list_super (struct ext2_super_block * s)
|
||||
{
|
||||
list_super2(s, stdout);
|
||||
}
|
||||
|
147
libcustomext2fs/source/e2p/mntopts.c
Normal file
147
libcustomext2fs/source/e2p/mntopts.c
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* mountopts.c --- convert between default mount options and strings
|
||||
*
|
||||
* Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
struct mntopt {
|
||||
unsigned int mask;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
static struct mntopt mntopt_list[] = {
|
||||
{ EXT2_DEFM_DEBUG, "debug" },
|
||||
{ EXT2_DEFM_BSDGROUPS, "bsdgroups" },
|
||||
{ EXT2_DEFM_XATTR_USER, "user_xattr" },
|
||||
{ EXT2_DEFM_ACL, "acl" },
|
||||
{ EXT2_DEFM_UID16, "uid16" },
|
||||
{ EXT3_DEFM_JMODE_DATA, "journal_data" },
|
||||
{ EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
|
||||
{ EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
|
||||
{ EXT4_DEFM_NOBARRIER, "nobarrier" },
|
||||
{ EXT4_DEFM_BLOCK_VALIDITY, "block_validity" },
|
||||
{ EXT4_DEFM_DISCARD, "discard"},
|
||||
{ EXT4_DEFM_NODELALLOC, "nodelalloc"},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const char *e2p_mntopt2string(unsigned int mask)
|
||||
{
|
||||
struct mntopt *f;
|
||||
static char buf[20];
|
||||
int fnum;
|
||||
|
||||
for (f = mntopt_list; f->string; f++) {
|
||||
if (mask == f->mask)
|
||||
return f->string;
|
||||
}
|
||||
for (fnum = 0; mask >>= 1; fnum++);
|
||||
sprintf(buf, "MNTOPT_%d", fnum);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int e2p_string2mntopt(char *string, unsigned int *mask)
|
||||
{
|
||||
struct mntopt *f;
|
||||
char *eptr;
|
||||
int num;
|
||||
|
||||
for (f = mntopt_list; f->string; f++) {
|
||||
if (!strcasecmp(string, f->string)) {
|
||||
*mask = f->mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strncasecmp(string, "MNTOPT_", 8))
|
||||
return 1;
|
||||
|
||||
if (string[8] == 0)
|
||||
return 1;
|
||||
num = strtol(string+8, &eptr, 10);
|
||||
if (num > 32 || num < 0)
|
||||
return 1;
|
||||
if (*eptr)
|
||||
return 1;
|
||||
*mask = 1 << num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *skip_over_blanks(char *cp)
|
||||
{
|
||||
while (*cp && isspace((int) *cp))
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static char *skip_over_word(char *cp)
|
||||
{
|
||||
while (*cp && !isspace((int) *cp) && *cp != ',')
|
||||
cp++;
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a mntopt set array as requested by the user. The ok
|
||||
* parameter, if non-zero, allows the application to limit what
|
||||
* mntopts the user is allowed to set or clear using this function.
|
||||
*/
|
||||
int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
|
||||
{
|
||||
char *cp, *buf, *next;
|
||||
int neg;
|
||||
unsigned int mask;
|
||||
int rc = 0;
|
||||
|
||||
buf = malloc(strlen(str)+1);
|
||||
if (!buf)
|
||||
return 1;
|
||||
strcpy(buf, str);
|
||||
cp = buf;
|
||||
while (cp && *cp) {
|
||||
neg = 0;
|
||||
cp = skip_over_blanks(cp);
|
||||
next = skip_over_word(cp);
|
||||
if (*next == 0)
|
||||
next = 0;
|
||||
else
|
||||
*next = 0;
|
||||
switch (*cp) {
|
||||
case '-':
|
||||
case '^':
|
||||
neg++;
|
||||
case '+':
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (e2p_string2mntopt(cp, &mask)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
if (ok && !(ok & mask)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
if (mask & EXT3_DEFM_JMODE)
|
||||
*mntopts &= ~EXT3_DEFM_JMODE;
|
||||
if (neg)
|
||||
*mntopts &= ~mask;
|
||||
else
|
||||
*mntopts |= mask;
|
||||
cp = next ? next+1 : 0;
|
||||
}
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
77
libcustomext2fs/source/e2p/ostype.c
Normal file
77
libcustomext2fs/source/e2p/ostype.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* getostype.c - Get the Filesystem OS type
|
||||
*
|
||||
* Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char *os_tab[] =
|
||||
{ "Linux",
|
||||
"Hurd",
|
||||
"Masix",
|
||||
"FreeBSD",
|
||||
"Lites",
|
||||
0 };
|
||||
|
||||
/*
|
||||
* Convert an os_type to a string
|
||||
*/
|
||||
char *e2p_os2string(int os_type)
|
||||
{
|
||||
const char *os;
|
||||
char *ret;
|
||||
|
||||
if (os_type <= EXT2_OS_LITES)
|
||||
os = os_tab[os_type];
|
||||
else
|
||||
os = "(unknown os)";
|
||||
|
||||
ret = malloc(strlen(os)+1);
|
||||
if (ret)
|
||||
strcpy(ret, os);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an os_type to a string
|
||||
*/
|
||||
int e2p_string2os(char *str)
|
||||
{
|
||||
const char **cpp;
|
||||
int i = 0;
|
||||
|
||||
for (cpp = os_tab; *cpp; cpp++, i++) {
|
||||
if (!strcasecmp(str, *cpp))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TEST_PROGRAM
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *s;
|
||||
int i, os;
|
||||
|
||||
for (i=0; i <= EXT2_OS_LITES; i++) {
|
||||
s = e2p_os2string(i);
|
||||
os = e2p_string2os(s);
|
||||
printf("%d: %s (%d)\n", i, s, os);
|
||||
if (i != os) {
|
||||
fprintf(stderr, "Failure!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
71
libcustomext2fs/source/e2p/parse_num.c
Normal file
71
libcustomext2fs/source/e2p/parse_num.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* parse_num.c - Parse the number of blocks
|
||||
*
|
||||
* Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Library
|
||||
* General Public License, version 2.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include "e2p.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned long long parse_num_blocks2(const char *arg, int log_block_size)
|
||||
{
|
||||
char *p;
|
||||
unsigned long long num;
|
||||
|
||||
num = strtoull(arg, &p, 0);
|
||||
|
||||
if (p[0] && p[1])
|
||||
return 0;
|
||||
|
||||
switch (*p) { /* Using fall-through logic */
|
||||
case 'T': case 't':
|
||||
num <<= 10;
|
||||
case 'G': case 'g':
|
||||
num <<= 10;
|
||||
case 'M': case 'm':
|
||||
num <<= 10;
|
||||
case 'K': case 'k':
|
||||
num >>= log_block_size;
|
||||
break;
|
||||
case 's':
|
||||
num >>= (1+log_block_size);
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
unsigned long parse_num_blocks(const char *arg, int log_block_size)
|
||||
{
|
||||
return parse_num_blocks2(arg, log_block_size);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
unsigned long num;
|
||||
int log_block_size = 0;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s arg\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
num = parse_num_blocks(argv[1], log_block_size);
|
||||
|
||||
printf("Parsed number: %lu\n", num);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user