am 0c9dc552: am aecb7f84: Merge "Revert "Revert "sound trigger: several data structure updates"""
* commit '0c9dc552921bf50d62c8b81084a703ac07e48cd6':
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0254bd2..e78fc88 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -53,3 +53,4 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/reboot)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/lmkd_intermediates/import_includes)
diff --git a/adb/sockets.c b/adb/sockets.c
index de14a22..faa9564 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -23,6 +23,10 @@
#include "sysdeps.h"
+#if !ADB_HOST
+#include <cutils/properties.h>
+#endif
+
#define TRACE_TAG TRACE_SOCKETS
#include "adb.h"
@@ -428,6 +432,9 @@
{
asocket *s;
int fd;
+#if !ADB_HOST
+ char debug[PROPERTY_VALUE_MAX];
+#endif
#if !ADB_HOST
if (!strcmp(name,"jdwp")) {
@@ -444,7 +451,11 @@
D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
#if !ADB_HOST
- if ((!strncmp(name, "root:", 5) && getuid() != 0)
+ if (!strncmp(name, "root:", 5))
+ property_get("ro.debuggable", debug, "");
+
+ if ((!strncmp(name, "root:", 5) && getuid() != 0
+ && strcmp(debug, "1") == 0)
|| !strncmp(name, "usb:", 4)
|| !strncmp(name, "tcpip:", 6)) {
D("LS(%d): enabling exit_on_close\n", s->id);
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index e4d7ecc..c33b263 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -22,13 +22,6 @@
-Wunused \
-Werror \
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP
-endif # ARCH_ARM_HAVE_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-
LOCAL_SHARED_LIBRARIES := \
libbacktrace \
libcutils \
@@ -45,6 +38,8 @@
include $(BUILD_EXECUTABLE)
+
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := crasher.c
LOCAL_SRC_FILES_arm := arm/crashglue.S
@@ -59,36 +54,14 @@
#LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+# The arm emulator has VFP but not VFPv3-D32.
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_ASFLAGS_arm += -DHAS_VFP_D32
+endif
+
LOCAL_MODULE := crasher
LOCAL_MODULE_STEM_32 := crasher
LOCAL_MODULE_STEM_64 := crasher64
LOCAL_MULTILIB := both
include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_MODULE_TARGET_ARCH += arm
-LOCAL_SRC_FILES_arm := arm/vfp.S
-LOCAL_CFLAGS_arm += -DWITH_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-endif # ARCH_ARM_HAVE_VFP == true
-LOCAL_CFLAGS += -Werror
-
-LOCAL_SRC_FILES_arm64 := arm64/vfp.S
-LOCAL_MODULE_TARGET_ARCH += arm64
-
-LOCAL_SRC_FILES := vfp-crasher.c
-LOCAL_MODULE := vfp-crasher
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-
-LOCAL_MODULE_STEM_32 := vfp-crasher
-LOCAL_MODULE_STEM_64 := vfp-crasher64
-LOCAL_MULTILIB := both
-
-include $(BUILD_EXECUTABLE)
diff --git a/debuggerd/arm/crashglue.S b/debuggerd/arm/crashglue.S
index eb9d0e3..4fbfd6e 100644
--- a/debuggerd/arm/crashglue.S
+++ b/debuggerd/arm/crashglue.S
@@ -1,8 +1,5 @@
.globl crash1
.type crash1, %function
-.globl crashnostack
-.type crashnostack, %function
-
crash1:
ldr r0, =0xa5a50000
ldr r1, =0xa5a50001
@@ -18,11 +15,48 @@
ldr r11, =0xa5a50011
ldr r12, =0xa5a50012
+
+ fconstd d0, #0
+ fconstd d1, #1
+ fconstd d2, #2
+ fconstd d3, #3
+ fconstd d4, #4
+ fconstd d5, #5
+ fconstd d6, #6
+ fconstd d7, #7
+ fconstd d8, #8
+ fconstd d9, #9
+ fconstd d10, #10
+ fconstd d11, #11
+ fconstd d12, #12
+ fconstd d13, #13
+ fconstd d14, #14
+ fconstd d15, #15
+#if defined(HAS_VFP_D32)
+ fconstd d16, #16
+ fconstd d17, #17
+ fconstd d18, #18
+ fconstd d19, #19
+ fconstd d20, #20
+ fconstd d21, #21
+ fconstd d22, #22
+ fconstd d23, #23
+ fconstd d24, #24
+ fconstd d25, #25
+ fconstd d26, #26
+ fconstd d27, #27
+ fconstd d28, #28
+ fconstd d29, #29
+ fconstd d30, #30
+ fconstd d31, #31
+#endif
+
mov lr, #0
ldr lr, [lr]
b .
-
+.globl crashnostack
+.type crashnostack, %function
crashnostack:
mov sp, #0
mov r0, #0
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index 839d47a..8270066 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -27,21 +27,8 @@
#include "../utility.h"
#include "../machine.h"
-// enable to dump memory pointed to by every register
-#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
-
-#ifdef WITH_VFP
-#ifdef WITH_VFP_D32
-#define NUM_VFP_REGS 32
-#else
-#define NUM_VFP_REGS 16
-#endif
-#endif
-
-// If configured to do so, dump memory around *all* registers
-// for the crashing thread.
void dump_memory_and_code(log_t* log, pid_t tid) {
- struct pt_regs regs;
+ pt_regs regs;
if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) {
return;
}
@@ -73,7 +60,7 @@
}
void dump_registers(log_t* log, pid_t tid) {
- struct pt_regs r;
+ pt_regs r;
if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
_LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno));
return;
@@ -93,19 +80,15 @@
static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
static_cast<uint32_t>(r.ARM_cpsr));
-#ifdef WITH_VFP
- struct user_vfp vfp_regs;
- int i;
-
+ user_vfp vfp_regs;
if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
_LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno));
return;
}
- for (i = 0; i < NUM_VFP_REGS; i += 2) {
+ for (size_t i = 0; i < 32; i += 2) {
_LOG(log, logtype::REGISTERS, " d%-2d %016llx d%-2d %016llx\n",
i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
}
_LOG(log, logtype::REGISTERS, " scr %08lx\n", vfp_regs.fpscr);
-#endif
}
diff --git a/debuggerd/arm/vfp.S b/debuggerd/arm/vfp.S
deleted file mode 100644
index 9744f6f..0000000
--- a/debuggerd/arm/vfp.S
+++ /dev/null
@@ -1,43 +0,0 @@
- .text
- .align 2
- .global crash
- .type crash, %function
-crash:
- fconstd d0, #0
- fconstd d1, #1
- fconstd d2, #2
- fconstd d3, #3
- fconstd d4, #4
- fconstd d5, #5
- fconstd d6, #6
- fconstd d7, #7
- fconstd d8, #8
- fconstd d9, #9
- fconstd d10, #10
- fconstd d11, #11
- fconstd d12, #12
- fconstd d13, #13
- fconstd d14, #14
- fconstd d15, #15
-#ifdef WITH_VFP_D32
- fconstd d16, #16
- fconstd d17, #17
- fconstd d18, #18
- fconstd d19, #19
- fconstd d20, #20
- fconstd d21, #21
- fconstd d22, #22
- fconstd d23, #23
- fconstd d24, #24
- fconstd d25, #25
- fconstd d26, #26
- fconstd d27, #27
- fconstd d28, #28
- fconstd d29, #29
- fconstd d30, #30
- fconstd d31, #31
-#endif
- mov r0, #0
- str r0, [r0]
- bx lr
-
diff --git a/debuggerd/arm64/crashglue.S b/debuggerd/arm64/crashglue.S
index b06b67c..e58b542 100644
--- a/debuggerd/arm64/crashglue.S
+++ b/debuggerd/arm64/crashglue.S
@@ -1,8 +1,5 @@
.globl crash1
.type crash1, %function
-.globl crashnostack
-.type crashnostack, %function
-
crash1:
ldr x0, =0xa5a50000
ldr x1, =0xa5a50001
@@ -35,11 +32,46 @@
ldr x28, =0xa5a50028
ldr x29, =0xa5a50029
+ fmov d0, -1.0 // -1 is more convincing than 0.
+ fmov d1, 1.0
+ fmov d2, 2.0
+ fmov d3, 3.0
+ fmov d4, 4.0
+ fmov d5, 5.0
+ fmov d6, 6.0
+ fmov d7, 7.0
+ fmov d8, 8.0
+ fmov d9, 9.0
+ fmov d10, 10.0
+ fmov d11, 11.0
+ fmov d12, 12.0
+ fmov d13, 13.0
+ fmov d14, 14.0
+ fmov d15, 15.0
+ fmov d16, 16.0
+ fmov d17, 17.0
+ fmov d18, 18.0
+ fmov d19, 19.0
+ fmov d20, 20.0
+ fmov d21, 21.0
+ fmov d22, 22.0
+ fmov d23, 23.0
+ fmov d24, 24.0
+ fmov d25, 25.0
+ fmov d26, 26.0
+ fmov d27, 27.0
+ fmov d28, 28.0
+ fmov d29, 29.0
+ fmov d30, 30.0
+ fmov d31, 31.0
+
mov x30, xzr
ldr x30, [x30]
b .
+.globl crashnostack
+.type crashnostack, %function
crashnostack:
mov x0, xzr
add sp, x0, xzr
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
index 48308c3..ec664bd 100644
--- a/debuggerd/arm64/machine.cpp
+++ b/debuggerd/arm64/machine.cpp
@@ -30,13 +30,6 @@
#include "../utility.h"
#include "../machine.h"
-/* enable to dump memory pointed to by every register */
-#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
-
-/*
- * If configured to do so, dump memory around *all* registers
- * for the crashing thread.
- */
void dump_memory_and_code(log_t* log, pid_t tid) {
struct user_pt_regs regs;
struct iovec io;
diff --git a/debuggerd/arm64/vfp.S b/debuggerd/arm64/vfp.S
deleted file mode 100644
index bf12c22..0000000
--- a/debuggerd/arm64/vfp.S
+++ /dev/null
@@ -1,42 +0,0 @@
- .text
- .align 2
- .global crash
- .type crash, %function
-crash:
- fmov d0, XZR
- fmov d1, 1.0
- fmov d2, 2.0
- fmov d3, 3.0
- fmov d4, 4.0
- fmov d5, 5.0
- fmov d6, 6.0
- fmov d7, 7.0
- fmov d8, 8.0
- fmov d9, 9.0
- fmov d10, 10.0
- fmov d11, 11.0
- fmov d12, 12.0
- fmov d13, 13.0
- fmov d14, 14.0
- fmov d15, 15.0
- fmov d16, 16.0
- fmov d17, 17.0
- fmov d18, 18.0
- fmov d19, 19.0
- fmov d20, 20.0
- fmov d21, 21.0
- fmov d22, 22.0
- fmov d23, 23.0
- fmov d24, 24.0
- fmov d25, 25.0
- fmov d26, 26.0
- fmov d27, 27.0
- fmov d28, 28.0
- fmov d29, 29.0
- fmov d30, 30.0
- fmov d31, 31.0
-
- mov x0, xzr
- str x0, [x0]
- br x30
-
diff --git a/debuggerd/vfp-crasher.c b/debuggerd/vfp-crasher.c
deleted file mode 100644
index 7a19cdd..0000000
--- a/debuggerd/vfp-crasher.c
+++ /dev/null
@@ -1,7 +0,0 @@
-int main()
-{
- extern void crash(void);
-
- crash();
- return 0;
-}
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 8388629..8444081 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -1,5 +1,5 @@
#ifndef _FS_H_
-#define _FH_H_
+#define _FS_H_
#include <stdint.h>
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 1ee33a1..4a6b702 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -35,6 +35,8 @@
#define POWER_SUPPLY_SUBSYSTEM "power_supply"
#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
+#define FAKE_BATTERY_CAPACITY 42
+#define FAKE_BATTERY_TEMPERATURE 424
namespace android {
@@ -530,11 +532,11 @@
KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
}
- if (property_get("persist.sys.battery.capacity", pval, NULL) > 0)
- mBatteryFixedCapacity = (int) strtol(pval, NULL, 10);
-
- if (property_get("persist.sys.battery.temperature", pval, NULL) > 0)
- mBatteryFixedTemperature = (int) strtol(pval, NULL, 10);
+ if (property_get("ro.boot.fake_battery", pval, NULL) > 0
+ && strtol(pval, NULL, 10) != 0) {
+ mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
+ mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+ }
}
}; // namespace android
diff --git a/include/system/audio.h b/include/system/audio.h
index c7cd109..f42c640 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -52,7 +52,9 @@
AUDIO_STREAM_ALARM = 4,
AUDIO_STREAM_NOTIFICATION = 5,
AUDIO_STREAM_BLUETOOTH_SCO = 6,
- AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
+ AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
+ * and must be routed to speaker
+ */
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
@@ -200,7 +202,16 @@
/* AAC sub format field definition: specify profile or bitrate for recording... */
typedef enum {
- AUDIO_FORMAT_AAC_SUB_NONE = 0x0,
+ AUDIO_FORMAT_AAC_SUB_MAIN = 0x1,
+ AUDIO_FORMAT_AAC_SUB_LC = 0x2,
+ AUDIO_FORMAT_AAC_SUB_SSR = 0x4,
+ AUDIO_FORMAT_AAC_SUB_LTP = 0x8,
+ AUDIO_FORMAT_AAC_SUB_HE_V1 = 0x10,
+ AUDIO_FORMAT_AAC_SUB_SCALABLE = 0x20,
+ AUDIO_FORMAT_AAC_SUB_ERLC = 0x40,
+ AUDIO_FORMAT_AAC_SUB_LD = 0x80,
+ AUDIO_FORMAT_AAC_SUB_HE_V2 = 0x100,
+ AUDIO_FORMAT_AAC_SUB_ELD = 0x200,
} audio_format_aac_sub_fmt_t;
/* VORBIS sub format field definition: specify quality for recording... */
@@ -225,8 +236,8 @@
AUDIO_FORMAT_AMR_NB = 0x02000000UL,
AUDIO_FORMAT_AMR_WB = 0x03000000UL,
AUDIO_FORMAT_AAC = 0x04000000UL,
- AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL,
- AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL,
+ AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/
+ AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/
AUDIO_FORMAT_VORBIS = 0x07000000UL,
AUDIO_FORMAT_OPUS = 0x08000000UL,
AUDIO_FORMAT_AC3 = 0x09000000UL,
@@ -249,10 +260,41 @@
AUDIO_FORMAT_PCM_SUB_FLOAT),
AUDIO_FORMAT_PCM_24_BIT_PACKED = (AUDIO_FORMAT_PCM |
AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
+ AUDIO_FORMAT_AAC_MAIN = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_MAIN),
+ AUDIO_FORMAT_AAC_LC = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LC),
+ AUDIO_FORMAT_AAC_SSR = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_SSR),
+ AUDIO_FORMAT_AAC_LTP = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LTP),
+ AUDIO_FORMAT_AAC_HE_V1 = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_HE_V1),
+ AUDIO_FORMAT_AAC_SCALABLE = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_SCALABLE),
+ AUDIO_FORMAT_AAC_ERLC = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_ERLC),
+ AUDIO_FORMAT_AAC_LD = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LD),
+ AUDIO_FORMAT_AAC_HE_V2 = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_HE_V2),
+ AUDIO_FORMAT_AAC_ELD = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_ELD),
} audio_format_t;
+/* For the channel mask for position assignment representation */
enum {
+
+/* These can be a complete audio_channel_mask_t. */
+
AUDIO_CHANNEL_NONE = 0x0,
+ AUDIO_CHANNEL_INVALID = 0xC0000000,
+
+/* These can be the bits portion of an audio_channel_mask_t
+ * with representation AUDIO_CHANNEL_REPRESENTATION_POSITION.
+ * Using these bits as a complete audio_channel_mask_t is deprecated.
+ */
+
/* output channels */
AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1,
AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2,
@@ -273,6 +315,8 @@
AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000,
AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000,
+/* TODO: should these be considered complete channel masks, or only bits? */
+
AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT,
AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
AUDIO_CHANNEL_OUT_FRONT_RIGHT),
@@ -328,6 +372,8 @@
AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
+/* These are bits only, not complete values */
+
/* input channels */
AUDIO_CHANNEL_IN_LEFT = 0x4,
AUDIO_CHANNEL_IN_RIGHT = 0x8,
@@ -344,6 +390,8 @@
AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000,
AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000,
+/* TODO: should these be considered complete channel masks, or only bits, or deprecated? */
+
AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT,
AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK),
@@ -365,9 +413,95 @@
/* A channel mask per se only defines the presence or absence of a channel, not the order.
* But see AUDIO_INTERLEAVE_* below for the platform convention of order.
+ *
+ * audio_channel_mask_t is an opaque type and its internal layout should not
+ * be assumed as it may change in the future.
+ * Instead, always use the functions declared in this header to examine.
+ *
+ * These are the current representations:
+ *
+ * AUDIO_CHANNEL_REPRESENTATION_POSITION
+ * is a channel mask representation for position assignment.
+ * Each low-order bit corresponds to the spatial position of a transducer (output),
+ * or interpretation of channel (input).
+ * The user of a channel mask needs to know the context of whether it is for output or input.
+ * The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion.
+ * It is not permitted for no bits to be set.
+ *
+ * AUDIO_CHANNEL_REPRESENTATION_INDEX
+ * is a channel mask representation for index assignment.
+ * Each low-order bit corresponds to a selected channel.
+ * There is no platform interpretation of the various bits.
+ * There is no concept of output or input.
+ * It is not permitted for no bits to be set.
+ *
+ * All other representations are reserved for future use.
+ *
+ * Warning: current representation distinguishes between input and output, but this will not the be
+ * case in future revisions of the platform. Wherever there is an ambiguity between input and output
+ * that is currently resolved by checking the channel mask, the implementer should look for ways to
+ * fix it with additional information outside of the mask.
*/
typedef uint32_t audio_channel_mask_t;
+/* Maximum number of channels for all representations */
+#define AUDIO_CHANNEL_COUNT_MAX 30
+
+/* log(2) of maximum number of representations, not part of public API */
+#define AUDIO_CHANNEL_REPRESENTATION_LOG2 2
+
+/* Representations */
+typedef enum {
+ AUDIO_CHANNEL_REPRESENTATION_POSITION = 0, // must be zero for compatibility
+ // 1 is reserved for future use
+ AUDIO_CHANNEL_REPRESENTATION_INDEX = 2,
+ // 3 is reserved for future use
+} audio_channel_representation_t;
+
+/* The return value is undefined if the channel mask is invalid. */
+static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel)
+{
+ return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1);
+}
+
+/* The return value is undefined if the channel mask is invalid. */
+static inline audio_channel_representation_t audio_channel_mask_get_representation(
+ audio_channel_mask_t channel)
+{
+ // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits
+ return (audio_channel_representation_t)
+ ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1));
+}
+
+/* Returns true if the channel mask is valid,
+ * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values.
+ * This function is unable to determine whether a channel mask for position assignment
+ * is invalid because an output mask has an invalid output bit set,
+ * or because an input mask has an invalid input bit set.
+ * All other APIs that take a channel mask assume that it is valid.
+ */
+static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel)
+{
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ audio_channel_representation_t representation = audio_channel_mask_get_representation(channel);
+ switch (representation) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ break;
+ default:
+ bits = 0;
+ break;
+ }
+ return bits != 0;
+}
+
+/* Not part of public API */
+static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits(
+ audio_channel_representation_t representation, uint32_t bits)
+{
+ return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits);
+}
+
/* Expresses the convention when stereo audio samples are stored interleaved
* in an array. This should improve readability by allowing code to use
* symbolic indices instead of hard-coded [0] and [1].
@@ -499,6 +633,7 @@
/* S/PDIF in */
AUDIO_DEVICE_IN_SPDIF = AUDIO_DEVICE_BIT_IN | 0x10000,
AUDIO_DEVICE_IN_BLUETOOTH_A2DP = AUDIO_DEVICE_BIT_IN | 0x20000,
+ AUDIO_DEVICE_IN_LOOPBACK = AUDIO_DEVICE_BIT_IN | 0x40000,
AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
@@ -519,6 +654,7 @@
AUDIO_DEVICE_IN_LINE |
AUDIO_DEVICE_IN_SPDIF |
AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
+ AUDIO_DEVICE_IN_LOOPBACK |
AUDIO_DEVICE_IN_DEFAULT),
AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
AUDIO_DEVICE_IN_ALL_USB = (AUDIO_DEVICE_IN_USB_ACCESSORY |
@@ -643,10 +779,10 @@
audio_gain_mode_t mode; /* mode requested for this command */
audio_channel_mask_t channel_mask; /* channels which gain value follows.
N/A in joint mode */
- int values[sizeof(audio_channel_mask_t)]; /* gain values in millibels for each
- channel ordered from LSb to MSb in channel mask.
- The number of values is 1 in joint mode or
- popcount(channel_mask) */
+ int values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels
+ for each channel ordered from LSb to MSb in
+ channel mask. The number of values is 1 in joint
+ mode or popcount(channel_mask) */
unsigned int ramp_duration_ms; /* ramp duration in ms */
};
@@ -911,81 +1047,182 @@
return false;
}
+/* Returns true if:
+ * representation is valid, and
+ * there is at least one channel bit set which _could_ correspond to an input channel, and
+ * there are no channel bits set which could _not_ correspond to an input channel.
+ * Otherwise returns false.
+ */
static inline bool audio_is_input_channel(audio_channel_mask_t channel)
{
- if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
- return channel != 0;
- else
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ if (bits & ~AUDIO_CHANNEL_IN_ALL) {
+ bits = 0;
+ }
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return bits != 0;
+ default:
return false;
+ }
}
+/* Returns true if:
+ * representation is valid, and
+ * there is at least one channel bit set which _could_ correspond to an output channel, and
+ * there are no channel bits set which could _not_ correspond to an output channel.
+ * Otherwise returns false.
+ */
static inline bool audio_is_output_channel(audio_channel_mask_t channel)
{
- if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0)
- return channel != 0;
- else
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ if (bits & ~AUDIO_CHANNEL_OUT_ALL) {
+ bits = 0;
+ }
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return bits != 0;
+ default:
return false;
+ }
}
/* Returns the number of channels from an input channel mask,
* used in the context of audio input or recording.
+ * If a channel bit is set which could _not_ correspond to an input channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
*/
static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel)
{
- return popcount(channel & AUDIO_CHANNEL_IN_ALL);
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ // TODO: We can now merge with from_out_mask and remove anding
+ bits &= AUDIO_CHANNEL_IN_ALL;
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return popcount(bits);
+ default:
+ return 0;
+ }
}
/* Returns the number of channels from an output channel mask,
* used in the context of audio output or playback.
+ * If a channel bit is set which could _not_ correspond to an output channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
*/
static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel)
{
- return popcount(channel & AUDIO_CHANNEL_OUT_ALL);
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ // TODO: We can now merge with from_in_mask and remove anding
+ bits &= AUDIO_CHANNEL_OUT_ALL;
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return popcount(bits);
+ default:
+ return 0;
+ }
}
-/* Derive an output channel mask from a channel count.
+/* Derive an output channel mask for position assignment from a channel count.
* This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
* cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
* and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
* for continuity with stereo.
- * Returns the matching channel mask, or 0 if the number of channels exceeds that of the
- * configurations for which a default channel mask is defined.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default output channel mask is defined.
*/
static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
{
+ uint32_t bits;
switch (channel_count) {
+ case 0:
+ return AUDIO_CHANNEL_NONE;
case 1:
- return AUDIO_CHANNEL_OUT_MONO;
+ bits = AUDIO_CHANNEL_OUT_MONO;
+ break;
case 2:
- return AUDIO_CHANNEL_OUT_STEREO;
+ bits = AUDIO_CHANNEL_OUT_STEREO;
+ break;
case 3:
- return (AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+ break;
case 4: // 4.0
- return AUDIO_CHANNEL_OUT_QUAD;
+ bits = AUDIO_CHANNEL_OUT_QUAD;
+ break;
case 5: // 5.0
- return (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+ break;
case 6: // 5.1
- return AUDIO_CHANNEL_OUT_5POINT1;
+ bits = AUDIO_CHANNEL_OUT_5POINT1;
+ break;
case 7: // 6.1
- return (AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER;
+ break;
case 8:
- return AUDIO_CHANNEL_OUT_7POINT1;
+ bits = AUDIO_CHANNEL_OUT_7POINT1;
+ break;
default:
- return 0;
+ return AUDIO_CHANNEL_INVALID;
}
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
}
-/* Similar to above, but for input. Currently handles only mono and stereo. */
+/* Derive an input channel mask for position assignment from a channel count.
+ * Currently handles only mono and stereo.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default input channel mask is defined.
+ */
static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
{
+ uint32_t bits;
switch (channel_count) {
+ case 0:
+ return AUDIO_CHANNEL_NONE;
case 1:
- return AUDIO_CHANNEL_IN_MONO;
+ bits = AUDIO_CHANNEL_IN_MONO;
+ break;
case 2:
- return AUDIO_CHANNEL_IN_STEREO;
+ bits = AUDIO_CHANNEL_IN_STEREO;
+ break;
default:
- return 0;
+ return AUDIO_CHANNEL_INVALID;
}
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
+}
+
+/* Derive a channel mask for index assignment from a channel count.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX.
+ */
+static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count(
+ uint32_t channel_count)
+{
+ if (channel_count == 0) {
+ return AUDIO_CHANNEL_NONE;
+ }
+ if (channel_count > AUDIO_CHANNEL_COUNT_MAX) {
+ return AUDIO_CHANNEL_INVALID;
+ }
+ uint32_t bits = (1 << channel_count) - 1;
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
}
static inline bool audio_is_valid_format(audio_format_t format)
diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h
index 3085830..a6554de 100644
--- a/include/system/audio_policy.h
+++ b/include/system/audio_policy.h
@@ -44,9 +44,6 @@
AUDIO_POLICY_FORCE_DIGITAL_DOCK,
AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_HDMI_ARC,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_SPDIF,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_LINE,
AUDIO_POLICY_FORCE_CFG_CNT,
AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
diff --git a/init/builtins.c b/init/builtins.c
index f7bd8a9..6032184 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -48,7 +48,7 @@
#include <private/android_filesystem_config.h>
-void add_environment(const char *name, const char *value);
+int add_environment(const char *name, const char *value);
extern int init_module(void *, unsigned long, const char *);
@@ -261,8 +261,7 @@
int do_export(int nargs, char **args)
{
- add_environment(args[1], args[2]);
- return 0;
+ return add_environment(args[1], args[2]);
}
int do_hostname(int nargs, char **args)
diff --git a/init/init.c b/init/init.c
index e4ac1cf..74c0308 100644
--- a/init/init.c
+++ b/init/init.c
@@ -96,11 +96,24 @@
/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
- int n;
+ size_t n;
+ size_t key_len = strlen(key);
- for (n = 0; n < 31; n++) {
- if (!ENV[n]) {
- size_t len = strlen(key) + strlen(val) + 2;
+ /* The last environment entry is reserved to terminate the list */
+ for (n = 0; n < (ARRAY_SIZE(ENV) - 1); n++) {
+
+ /* Delete any existing entry for this key */
+ if (ENV[n] != NULL) {
+ size_t entry_key_len = strcspn(ENV[n], "=");
+ if ((entry_key_len == key_len) && (strncmp(ENV[n], key, entry_key_len) == 0)) {
+ free((char*)ENV[n]);
+ ENV[n] = NULL;
+ }
+ }
+
+ /* Add entry if a free slot is available */
+ if (ENV[n] == NULL) {
+ size_t len = key_len + strlen(val) + 2;
char *entry = malloc(len);
snprintf(entry, len, "%s=%s", key, val);
ENV[n] = entry;
@@ -108,7 +121,9 @@
}
}
- return 1;
+ ERROR("No env. room to store: '%s':'%s'\n", key, val);
+
+ return -1;
}
static void zap_stdio(void)
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index fa0792f..f8ffb1d 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -39,17 +39,9 @@
#if defined(HAVE_ANDROID_OS) && defined(HAVE_SCHED_H) && defined(HAVE_PTHREADS)
-#include <linux/prctl.h>
-#include <sched.h>
#include <pthread.h>
-
-#ifndef SCHED_NORMAL
- #define SCHED_NORMAL 0
-#endif
-
-#ifndef SCHED_BATCH
- #define SCHED_BATCH 3
-#endif
+#include <sched.h>
+#include <sys/prctl.h>
#define POLICY_DEBUG 0
diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk
new file mode 100644
index 0000000..501321f
--- /dev/null
+++ b/libprocessgroup/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := processgroup.cpp
+LOCAL_MODULE := libprocessgroup
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_REQUIRED_MODULE := processgroup_cleanup
+include external/libcxx/libcxx.mk
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := cleanup.cpp
+LOCAL_MODULE := processgroup_cleanup
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_STATIC_LIBRARIES := libc libcutils
+include $(BUILD_EXECUTABLE)
diff --git a/libprocessgroup/cleanup.cpp b/libprocessgroup/cleanup.cpp
new file mode 100644
index 0000000..cca8dc4
--- /dev/null
+++ b/libprocessgroup/cleanup.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <unistd.h>
+#include <sys/syslimits.h>
+
+#include "processgroup_priv.h"
+
+int main(int argc, char **argv)
+{
+ char buf[PATH_MAX];
+ if (argc != 2)
+ return -1;
+
+ memcpy(buf, PROCESSGROUP_CGROUP_PATH, sizeof(PROCESSGROUP_CGROUP_PATH));
+ strlcat(buf, argv[1], sizeof(buf));
+ return rmdir(buf);
+}
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
new file mode 100644
index 0000000..11bd8cc
--- /dev/null
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _PROCESSGROUP_H_
+#define _PROCESSGROUP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+int killProcessGroup(uid_t uid, int initialPid, int signal);
+
+int createProcessGroup(uid_t uid, int initialPid);
+
+void removeAllProcessGroups(void);
+
+__END_DECLS
+
+#endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
new file mode 100644
index 0000000..c32e741
--- /dev/null
+++ b/libprocessgroup/processgroup.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "libprocessgroup"
+
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <processgroup/processgroup.h>
+#include "processgroup_priv.h"
+
+struct ctx {
+ bool initialized;
+ int fd;
+ char buf[128];
+ char *buf_ptr;
+ size_t buf_len;
+};
+
+static int convertUidToPath(char *path, size_t size, uid_t uid)
+{
+ return snprintf(path, size, "%s/%s%d",
+ PROCESSGROUP_CGROUP_PATH,
+ PROCESSGROUP_UID_PREFIX,
+ uid);
+}
+
+static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid)
+{
+ return snprintf(path, size, "%s/%s%d/%s%d",
+ PROCESSGROUP_CGROUP_PATH,
+ PROCESSGROUP_UID_PREFIX,
+ uid,
+ PROCESSGROUP_PID_PREFIX,
+ pid);
+}
+
+static int initCtx(uid_t uid, int pid, struct ctx *ctx)
+{
+ int ret;
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+ convertUidPidToPath(path, sizeof(path), uid, pid);
+ strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
+
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ret = -errno;
+ SLOGV("failed to open %s: %s", path, strerror(errno));
+ return ret;
+ }
+
+ ctx->fd = fd;
+ ctx->buf_ptr = ctx->buf;
+ ctx->buf_len = 0;
+ ctx->initialized = true;
+
+ return 0;
+}
+
+static int refillBuffer(struct ctx *ctx)
+{
+ memmove(ctx->buf, ctx->buf_ptr, ctx->buf_len);
+ ctx->buf_ptr = ctx->buf;
+
+ ssize_t ret = read(ctx->fd, ctx->buf_ptr + ctx->buf_len,
+ sizeof(ctx->buf) - ctx->buf_len);
+ if (ret < 0) {
+ return -errno;
+ } else if (ret == 0) {
+ return 0;
+ }
+
+ ctx->buf_len += ret;
+ assert(ctx->buf_len <= sizeof(ctx->buf));
+
+ return ret;
+}
+
+static pid_t getOneAppProcess(uid_t uid, int appProcessPid, struct ctx *ctx)
+{
+ if (!ctx->initialized) {
+ int ret = initCtx(uid, appProcessPid, ctx);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ char *eptr;
+ while ((eptr = (char *)memchr(ctx->buf_ptr, '\n', ctx->buf_len)) == NULL) {
+ int ret = refillBuffer(ctx);
+ if (ret == 0) {
+ return -ERANGE;
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ *eptr = '\0';
+ char *pid_eptr = NULL;
+ errno = 0;
+ long pid = strtol(ctx->buf_ptr, &pid_eptr, 10);
+ if (errno != 0) {
+ return -errno;
+ }
+ if (pid_eptr != eptr) {
+ return -EINVAL;
+ }
+
+ ctx->buf_ptr = eptr + 1;
+
+ return (pid_t)pid;
+}
+
+static int removeProcessGroup(uid_t uid, int pid)
+{
+ int ret;
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+
+ convertUidPidToPath(path, sizeof(path), uid, pid);
+ ret = rmdir(path);
+
+ convertUidToPath(path, sizeof(path), uid);
+ rmdir(path);
+
+ return ret;
+}
+
+static void removeUidProcessGroups(const char *uid_path)
+{
+ DIR *uid = opendir(uid_path);
+ if (uid != NULL) {
+ struct dirent cur;
+ struct dirent *dir;
+ while ((readdir_r(uid, &cur, &dir) == 0) && dir) {
+ char path[PROCESSGROUP_MAX_PATH_LEN];
+
+ if (dir->d_type != DT_DIR) {
+ continue;
+ }
+
+ if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) {
+ continue;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name);
+ SLOGV("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+
+void removeAllProcessGroups()
+{
+ SLOGV("removeAllProcessGroups()");
+ DIR *root = opendir(PROCESSGROUP_CGROUP_PATH);
+ if (root == NULL) {
+ SLOGE("failed to open %s: %s", PROCESSGROUP_CGROUP_PATH, strerror(errno));
+ }
+ if (root != NULL) {
+ struct dirent cur;
+ struct dirent *dir;
+ while ((readdir_r(root, &cur, &dir) == 0) && dir) {
+ char path[PROCESSGROUP_MAX_PATH_LEN];
+
+ if (dir->d_type != DT_DIR) {
+ continue;
+ }
+ if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) {
+ continue;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", PROCESSGROUP_CGROUP_PATH, dir->d_name);
+ removeUidProcessGroups(path);
+ SLOGV("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+
+static int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
+{
+ int processes = 0;
+ struct ctx ctx;
+ pid_t pid;
+
+ ctx.initialized = false;
+
+ while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0) {
+ processes++;
+ SLOGV("sending processgroup kill to pid %d\n", pid);
+ int ret = kill(pid, signal);
+ if (ret == -1) {
+ SLOGV("failed to kill pid %d: %s", pid, strerror(errno));
+ }
+ }
+
+ if (ctx.initialized) {
+ close(ctx.fd);
+ }
+
+ return processes;
+}
+
+int killProcessGroup(uid_t uid, int initialPid, int signal)
+{
+ int processes;
+ int sleep_us = 100;
+
+ while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
+ SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
+ if (sleep_us < 128000) {
+ usleep(sleep_us);
+ sleep_us *= 2;
+ } else {
+ SLOGE("failed to kill %d processes for processgroup %d\n",
+ processes, initialPid);
+ break;
+ }
+ }
+
+ if (processes == 0) {
+ return removeProcessGroup(uid, initialPid);
+ } else {
+ return -1;
+ }
+}
+
+static int mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ int ret;
+
+ ret = mkdir(path, 0750);
+ if (ret < 0 && errno != EEXIST) {
+ return -errno;
+ }
+
+ ret = chown(path, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ ret = -errno;
+ rmdir(path);
+ return ret;
+ }
+
+ return 0;
+}
+
+int createProcessGroup(uid_t uid, int initialPid)
+{
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+ int ret;
+
+ convertUidToPath(path, sizeof(path), uid);
+
+ ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
+ return ret;
+ }
+
+ convertUidPidToPath(path, sizeof(path), uid, initialPid);
+
+ ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
+ return ret;
+ }
+
+ strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
+
+ int fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ ret = -errno;
+ SLOGE("failed to open %s: %s", path, strerror(errno));
+ return ret;
+ }
+
+ char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
+ int len = snprintf(pid, sizeof(pid), "%d", initialPid);
+
+ ret = write(fd, pid, len);
+ if (ret < 0) {
+ ret = -errno;
+ SLOGE("failed to write '%s' to %s: %s", pid, path, strerror(errno));
+ } else {
+ ret = 0;
+ }
+
+ close(fd);
+ return ret;
+}
+
diff --git a/libprocessgroup/processgroup_priv.h b/libprocessgroup/processgroup_priv.h
new file mode 100644
index 0000000..1895bf9
--- /dev/null
+++ b/libprocessgroup/processgroup_priv.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _PROCESSGROUP_PRIV_H_
+#define _PROCESSGROUP_PRIV_H_
+
+#define PROCESSGROUP_CGROUP_PATH "/acct"
+#define PROCESSGROUP_UID_PREFIX "uid_"
+#define PROCESSGROUP_PID_PREFIX "pid_"
+#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
+#define PROCESSGROUP_MAX_UID_LEN 11
+#define PROCESSGROUP_MAX_PID_LEN 11
+#define PROCESSGROUP_MAX_PATH_LEN \
+ (sizeof(PROCESSGROUP_CGROUP_PATH) + \
+ sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \
+ PROCESSGROUP_MAX_UID_LEN + \
+ sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \
+ PROCESSGROUP_MAX_PID_LEN + \
+ sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \
+ 1)
+
+#endif
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 2dd8af2..043a085 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := lmkd.c
-LOCAL_SHARED_LIBRARIES := libcutils liblog libm libc
+LOCAL_SHARED_LIBRARIES := libcutils liblog libm libc libprocessgroup
LOCAL_CFLAGS := -Werror
LOCAL_MODULE := lmkd
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 5caf77d..1aeb182 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -32,6 +32,7 @@
#include <cutils/sockets.h>
#include <log/log.h>
+#include <processgroup/processgroup.h>
#ifndef __unused
#define __unused __attribute__((__unused__))
@@ -104,6 +105,7 @@
struct proc {
struct adjslot_list asl;
int pid;
+ uid_t uid;
int oomadj;
struct proc *pidhash_next;
};
@@ -227,7 +229,7 @@
close(fd);
}
-static void cmd_procprio(int pid, int oomadj) {
+static void cmd_procprio(int pid, int uid, int oomadj) {
struct proc *procp;
char path[80];
char val[20];
@@ -253,6 +255,7 @@
}
procp->pid = pid;
+ procp->uid = uid;
procp->oomadj = oomadj;
proc_insert(procp);
} else {
@@ -356,9 +359,9 @@
cmd_target(targets, &ibuf[1]);
break;
case LMK_PROCPRIO:
- if (nargs != 2)
+ if (nargs != 3)
goto wronglen;
- cmd_procprio(ntohl(ibuf[1]), ntohl(ibuf[2]));
+ cmd_procprio(ntohl(ibuf[1]), ntohl(ibuf[2]), ntohl(ibuf[3]));
break;
case LMK_PROCREMOVE:
if (nargs != 1)
@@ -565,6 +568,7 @@
if (procp) {
int pid = procp->pid;
+ uid_t uid = procp->uid;
char *taskname;
int tasksize;
int r;
@@ -581,13 +585,14 @@
goto retry;
}
- ALOGI("Killing '%s' (%d), adj %d\n"
+ ALOGI("Killing '%s' (%d), uid %d, adj %d\n"
" to free %ldkB because cache %ldkB is below limit %ldkB for oom_adj %d\n"
" Free memory is %ldkB %s reserved",
- taskname, pid, procp->oomadj, tasksize * page_k,
+ taskname, pid, uid, procp->oomadj, tasksize * page_k,
other_file * page_k, minfree * page_k, min_score_adj,
other_free * page_k, other_free >= 0 ? "above" : "below");
r = kill(pid, SIGKILL);
+ killProcessGroup(uid, pid, SIGKILL);
pid_remove(pid);
if (r) {
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 957fdb5..4bea4be 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -503,13 +503,11 @@
(user_logger_content) ? yes : no,
(kernel_logger_available) ? yes : no,
(kernel_logger_content) ? yes : no,
- (user_logger_available && kernel_logger_available) ? "WARNING" : "ok",
+ (user_logger_available && kernel_logger_available) ? "ERROR" : "ok",
(user_logger_content && kernel_logger_content) ? "ERROR" : "ok");
- if (user_logger_available && kernel_logger_available) {
- printf("WARNING: kernel & user logger; both consuming resources!!!\n");
- }
-
+ EXPECT_EQ(0, user_logger_available && kernel_logger_available);
+ EXPECT_EQ(0, !user_logger_available && !kernel_logger_available);
EXPECT_EQ(0, user_logger_content && kernel_logger_content);
EXPECT_EQ(0, !user_logger_content && !kernel_logger_content);
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1bbc7ab..68eae67 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -193,13 +193,11 @@
chown system cache /cache
chmod 0770 /cache
# We restorecon /cache in case the cache partition has been reset.
- restorecon /cache
+ restorecon_recursive /cache
# This may have been created by the recovery system with odd permissions
chown system cache /cache/recovery
chmod 0770 /cache/recovery
- # This may have been created by the recovery system with the wrong context.
- restorecon /cache/recovery
#change permissions on vmallocinfo so we can grab it from bugreports
chown root log /proc/vmallocinfo
@@ -613,6 +611,7 @@
service flash_recovery /system/bin/install-recovery.sh
class main
+ seclabel u:r:install_recovery:s0
oneshot
service racoon /system/bin/racoon
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 3a164ed..d3afcb1 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "sdcard"
+
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@@ -35,6 +37,7 @@
#include <cutils/fs.h>
#include <cutils/hashmap.h>
+#include <cutils/log.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
@@ -90,12 +93,12 @@
#define FUSE_TRACE 0
#if FUSE_TRACE
-#define TRACE(x...) fprintf(stderr,x)
+#define TRACE(x...) ALOGD(x)
#else
#define TRACE(x...) do {} while (0)
#endif
-#define ERROR(x...) fprintf(stderr,x)
+#define ERROR(x...) ALOGE(x)
#define FUSE_UNKNOWN_INO 0xffffffff
@@ -1313,14 +1316,23 @@
static int handle_fsync(struct fuse* fuse, struct fuse_handler* handler,
const struct fuse_in_header* hdr, const struct fuse_fsync_in* req)
{
- int is_data_sync = req->fsync_flags & 1;
- struct handle *h = id_to_ptr(req->fh);
- int res;
+ bool is_dir = (hdr->opcode == FUSE_FSYNCDIR);
+ bool is_data_sync = req->fsync_flags & 1;
- TRACE("[%d] FSYNC %p(%d) is_data_sync=%d\n", handler->token,
- h, h->fd, is_data_sync);
- res = is_data_sync ? fdatasync(h->fd) : fsync(h->fd);
- if (res < 0) {
+ int fd = -1;
+ if (is_dir) {
+ struct dirhandle *dh = id_to_ptr(req->fh);
+ fd = dirfd(dh->d);
+ } else {
+ struct handle *h = id_to_ptr(req->fh);
+ fd = h->fd;
+ }
+
+ TRACE("[%d] %s %p(%d) is_data_sync=%d\n", handler->token,
+ is_dir ? "FSYNCDIR" : "FSYNC",
+ id_to_ptr(req->fh), fd, is_data_sync);
+ int res = is_data_sync ? fdatasync(fd) : fsync(fd);
+ if (res == -1) {
return -errno;
}
return 0;
diff --git a/toolbox/bsd-compatibility.h b/toolbox/bsd-compatibility.h
index a304631..abc3064 100644
--- a/toolbox/bsd-compatibility.h
+++ b/toolbox/bsd-compatibility.h
@@ -31,6 +31,9 @@
/* We want chown to support user.group as well as user:group. */
#define SUPPORT_DOT
+/* We don't localize /system/bin! */
+#define WITHOUT_NLS
+
__BEGIN_DECLS
extern int uid_from_user(const char* name, uid_t* uid);
diff --git a/toolbox/grep/grep.c b/toolbox/grep/grep.c
index 7b2c487..7314e13 100644
--- a/toolbox/grep/grep.c
+++ b/toolbox/grep/grep.c
@@ -159,7 +159,6 @@
{
fprintf(stderr, getstr(4), __progname);
fprintf(stderr, "%s", getstr(5));
- fprintf(stderr, "%s", getstr(5));
fprintf(stderr, "%s", getstr(6));
fprintf(stderr, "%s", getstr(7));
exit(2);
@@ -403,7 +402,7 @@
Aflag = 0;
else if (Aflag > LLONG_MAX / 10) {
errno = ERANGE;
- err(2, "%llu", Aflag);
+ err(2, NULL);
}
Aflag = Bflag = (Aflag * 10) + (c - '0');
break;
@@ -420,10 +419,10 @@
l = strtoull(optarg, &ep, 10);
if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
((errno == EINVAL) && (l == 0)))
- err(2, "strtoull");
+ err(2, NULL);
else if (ep[0] != '\0') {
errno = EINVAL;
- err(2, "empty");
+ err(2, NULL);
}
if (c == 'A')
Aflag = l;
@@ -509,10 +508,10 @@
mcount = strtoull(optarg, &ep, 10);
if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
((errno == EINVAL) && (mcount == 0)))
- err(2, "strtoull");
+ err(2, NULL);
else if (ep[0] != '\0') {
errno = EINVAL;
- err(2, "empty");
+ err(2, NULL);
}
break;
case 'n':
diff --git a/toolbox/grep/grep.h b/toolbox/grep/grep.h
index 6454f93..eafb00e 100644
--- a/toolbox/grep/grep.h
+++ b/toolbox/grep/grep.h
@@ -29,10 +29,6 @@
* SUCH DAMAGE.
*/
-#ifdef ANDROID
-#define WITHOUT_NLS
-#endif
-
#ifndef ANDROID
#include <bzlib.h>
#endif
diff --git a/toolbox/grep/util.c b/toolbox/grep/util.c
index 5712fee..ecd948d 100644
--- a/toolbox/grep/util.c
+++ b/toolbox/grep/util.c
@@ -1,4 +1,4 @@
-/* $NetBSD: util.c,v 1.16 2012/05/06 22:32:05 joerg Exp $ */
+/* $NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $ */
/* $FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $ */
/* $OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $ */
@@ -34,7 +34,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.16 2012/05/06 22:32:05 joerg Exp $");
+__RCSID("$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $");
#include <sys/stat.h>
#include <sys/types.h>
@@ -74,9 +74,10 @@
for (i = 0; i < fpatterns; ++i) {
if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
fnmatch(fpattern[i].pat, fname_base, 0) == 0) {
- if (fpattern[i].mode == EXCL_PAT)
+ if (fpattern[i].mode == EXCL_PAT) {
+ free(fname_copy);
return (false);
- else
+ } else
ret = true;
}
}
@@ -128,7 +129,7 @@
break;
default:
fts_flags = FTS_LOGICAL;
-
+
}
fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
@@ -273,7 +274,7 @@
return (c);
}
-#define iswword(x) (iswalnum((wint_t)(x)) || (x) == L'_')
+#define iswword(x) (iswalnum((x)) || (x) == L'_')
/*
* Processes a line comparing it with the specified patterns. Each pattern
@@ -474,13 +475,13 @@
if (!oflag)
fwrite(line->dat + a, matches[i].rm_so - a, 1,
stdout);
- if (color)
+ if (color)
fprintf(stdout, "\33[%sm\33[K", color);
- fwrite(line->dat + matches[i].rm_so,
+ fwrite(line->dat + matches[i].rm_so,
matches[i].rm_eo - matches[i].rm_so, 1,
stdout);
- if (color)
+ if (color)
fprintf(stdout, "\33[m\33[K");
a = matches[i].rm_eo;
if (oflag)
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 30b9f77..5fbca8d 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -27,20 +27,20 @@
#ifndef lint
static const char rcsid[] =
- "$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.33 2009/04/11 14:56:29 ed Exp $";
+ "$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.33 2009/04/11 14:56:29 ed Exp $";
#endif /* not lint */
#include <sys/param.h>
#ifndef ANDROID
- #include <sys/fdcio.h>
- #include <sys/disk.h>
- #include <sys/disklabel.h>
- #include <sys/mount.h>
+#include <sys/fdcio.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/mount.h>
#else
- #include <stdarg.h>
- #include <linux/fs.h>
- #include <linux/hdreg.h>
+#include <stdarg.h>
+#include <linux/fs.h>
+#include <linux/hdreg.h>
#endif
#include <sys/stat.h>
@@ -58,44 +58,44 @@
#include <time.h>
#include <unistd.h>
-#define MAXU16 0xffff /* maximum unsigned 16-bit quantity */
-#define BPN 4 /* bits per nibble */
-#define NPB 2 /* nibbles per byte */
+#define MAXU16 0xffff /* maximum unsigned 16-bit quantity */
+#define BPN 4 /* bits per nibble */
+#define NPB 2 /* nibbles per byte */
-#define DOSMAGIC 0xaa55 /* DOS magic number */
-#define MINBPS 512 /* minimum bytes per sector */
-#define MAXSPC 128 /* maximum sectors per cluster */
-#define MAXNFT 16 /* maximum number of FATs */
-#define DEFBLK 4096 /* default block size */
-#define DEFBLK16 2048 /* default block size FAT16 */
-#define DEFRDE 512 /* default root directory entries */
-#define RESFTE 2 /* reserved FAT entries */
-#define MINCLS12 1 /* minimum FAT12 clusters */
-#define MINCLS16 0x1000 /* minimum FAT16 clusters */
-#define MINCLS32 2 /* minimum FAT32 clusters */
-#define MAXCLS12 0xfed /* maximum FAT12 clusters */
-#define MAXCLS16 0xfff5 /* maximum FAT16 clusters */
-#define MAXCLS32 0xffffff5 /* maximum FAT32 clusters */
+#define DOSMAGIC 0xaa55 /* DOS magic number */
+#define MINBPS 512 /* minimum bytes per sector */
+#define MAXSPC 128 /* maximum sectors per cluster */
+#define MAXNFT 16 /* maximum number of FATs */
+#define DEFBLK 4096 /* default block size */
+#define DEFBLK16 2048 /* default block size FAT16 */
+#define DEFRDE 512 /* default root directory entries */
+#define RESFTE 2 /* reserved FAT entries */
+#define MINCLS12 1 /* minimum FAT12 clusters */
+#define MINCLS16 0x1000 /* minimum FAT16 clusters */
+#define MINCLS32 2 /* minimum FAT32 clusters */
+#define MAXCLS12 0xfed /* maximum FAT12 clusters */
+#define MAXCLS16 0xfff5 /* maximum FAT16 clusters */
+#define MAXCLS32 0xffffff5 /* maximum FAT32 clusters */
-#define mincls(fat) ((fat) == 12 ? MINCLS12 : \
- (fat) == 16 ? MINCLS16 : \
- MINCLS32)
+#define mincls(fat) ((fat) == 12 ? MINCLS12 : \
+ (fat) == 16 ? MINCLS16 : \
+ MINCLS32)
-#define maxcls(fat) ((fat) == 12 ? MAXCLS12 : \
- (fat) == 16 ? MAXCLS16 : \
- MAXCLS32)
+#define maxcls(fat) ((fat) == 12 ? MAXCLS12 : \
+ (fat) == 16 ? MAXCLS16 : \
+ MAXCLS32)
-#define mk1(p, x) \
+#define mk1(p, x) \
(p) = (u_int8_t)(x)
-#define mk2(p, x) \
- (p)[0] = (u_int8_t)(x), \
+#define mk2(p, x) \
+ (p)[0] = (u_int8_t)(x), \
(p)[1] = (u_int8_t)((x) >> 010)
-#define mk4(p, x) \
- (p)[0] = (u_int8_t)(x), \
- (p)[1] = (u_int8_t)((x) >> 010), \
- (p)[2] = (u_int8_t)((x) >> 020), \
+#define mk4(p, x) \
+ (p)[0] = (u_int8_t)(x), \
+ (p)[1] = (u_int8_t)((x) >> 010), \
+ (p)[2] = (u_int8_t)((x) >> 020), \
(p)[3] = (u_int8_t)((x) >> 030)
#define argto1(arg, lo, msg) argtou(arg, lo, 0xff, msg)
@@ -104,71 +104,71 @@
#define argtox(arg, lo, msg) argtou(arg, lo, UINT_MAX, msg)
struct bs {
- u_int8_t jmp[3]; /* bootstrap entry point */
- u_int8_t oem[8]; /* OEM name and version */
+ u_int8_t jmp[3]; /* bootstrap entry point */
+ u_int8_t oem[8]; /* OEM name and version */
};
struct bsbpb {
- u_int8_t bps[2]; /* bytes per sector */
- u_int8_t spc; /* sectors per cluster */
- u_int8_t res[2]; /* reserved sectors */
- u_int8_t nft; /* number of FATs */
- u_int8_t rde[2]; /* root directory entries */
- u_int8_t sec[2]; /* total sectors */
- u_int8_t mid; /* media descriptor */
- u_int8_t spf[2]; /* sectors per FAT */
- u_int8_t spt[2]; /* sectors per track */
- u_int8_t hds[2]; /* drive heads */
- u_int8_t hid[4]; /* hidden sectors */
- u_int8_t bsec[4]; /* big total sectors */
+ u_int8_t bps[2]; /* bytes per sector */
+ u_int8_t spc; /* sectors per cluster */
+ u_int8_t res[2]; /* reserved sectors */
+ u_int8_t nft; /* number of FATs */
+ u_int8_t rde[2]; /* root directory entries */
+ u_int8_t sec[2]; /* total sectors */
+ u_int8_t mid; /* media descriptor */
+ u_int8_t spf[2]; /* sectors per FAT */
+ u_int8_t spt[2]; /* sectors per track */
+ u_int8_t hds[2]; /* drive heads */
+ u_int8_t hid[4]; /* hidden sectors */
+ u_int8_t bsec[4]; /* big total sectors */
};
struct bsxbpb {
- u_int8_t bspf[4]; /* big sectors per FAT */
- u_int8_t xflg[2]; /* FAT control flags */
- u_int8_t vers[2]; /* file system version */
- u_int8_t rdcl[4]; /* root directory start cluster */
- u_int8_t infs[2]; /* file system info sector */
- u_int8_t bkbs[2]; /* backup boot sector */
- u_int8_t rsvd[12]; /* reserved */
+ u_int8_t bspf[4]; /* big sectors per FAT */
+ u_int8_t xflg[2]; /* FAT control flags */
+ u_int8_t vers[2]; /* file system version */
+ u_int8_t rdcl[4]; /* root directory start cluster */
+ u_int8_t infs[2]; /* file system info sector */
+ u_int8_t bkbs[2]; /* backup boot sector */
+ u_int8_t rsvd[12]; /* reserved */
};
struct bsx {
- u_int8_t drv; /* drive number */
- u_int8_t rsvd; /* reserved */
- u_int8_t sig; /* extended boot signature */
- u_int8_t volid[4]; /* volume ID number */
- u_int8_t label[11]; /* volume label */
- u_int8_t type[8]; /* file system type */
+ u_int8_t drv; /* drive number */
+ u_int8_t rsvd; /* reserved */
+ u_int8_t sig; /* extended boot signature */
+ u_int8_t volid[4]; /* volume ID number */
+ u_int8_t label[11]; /* volume label */
+ u_int8_t type[8]; /* file system type */
};
struct de {
- u_int8_t namext[11]; /* name and extension */
- u_int8_t attr; /* attributes */
- u_int8_t rsvd[10]; /* reserved */
- u_int8_t time[2]; /* creation time */
- u_int8_t date[2]; /* creation date */
- u_int8_t clus[2]; /* starting cluster */
- u_int8_t size[4]; /* size */
+ u_int8_t namext[11]; /* name and extension */
+ u_int8_t attr; /* attributes */
+ u_int8_t rsvd[10]; /* reserved */
+ u_int8_t time[2]; /* creation time */
+ u_int8_t date[2]; /* creation date */
+ u_int8_t clus[2]; /* starting cluster */
+ u_int8_t size[4]; /* size */
};
struct bpb {
- u_int bps; /* bytes per sector */
- u_int spc; /* sectors per cluster */
- u_int res; /* reserved sectors */
- u_int nft; /* number of FATs */
- u_int rde; /* root directory entries */
- u_int sec; /* total sectors */
- u_int mid; /* media descriptor */
- u_int spf; /* sectors per FAT */
- u_int spt; /* sectors per track */
- u_int hds; /* drive heads */
- u_int hid; /* hidden sectors */
- u_int bsec; /* big total sectors */
- u_int bspf; /* big sectors per FAT */
- u_int rdcl; /* root directory start cluster */
- u_int infs; /* file system info sector */
- u_int bkbs; /* backup boot sector */
+ u_int bps; /* bytes per sector */
+ u_int spc; /* sectors per cluster */
+ u_int res; /* reserved sectors */
+ u_int nft; /* number of FATs */
+ u_int rde; /* root directory entries */
+ u_int sec; /* total sectors */
+ u_int mid; /* media descriptor */
+ u_int spf; /* sectors per FAT */
+ u_int spt; /* sectors per track */
+ u_int hds; /* drive heads */
+ u_int hid; /* hidden sectors */
+ u_int bsec; /* big total sectors */
+ u_int bspf; /* big sectors per FAT */
+ u_int rdcl; /* root directory start cluster */
+ u_int infs; /* file system info sector */
+ u_int bkbs; /* backup boot sector */
};
#define BPBGAP 0, 0, 0, 0, 0, 0
@@ -181,35 +181,35 @@
{"180", {512, 1, 1, 2, 64, 360, 0xfc, 2, 9, 1, BPBGAP}},
{"320", {512, 2, 1, 2, 112, 640, 0xff, 1, 8, 2, BPBGAP}},
{"360", {512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2, BPBGAP}},
- {"640", {512, 2, 1, 2, 112, 1280, 0xfb, 2, 8, 2, BPBGAP}},
+ {"640", {512, 2, 1, 2, 112, 1280, 0xfb, 2, 8, 2, BPBGAP}},
{"720", {512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, BPBGAP}},
{"1200", {512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, BPBGAP}},
- {"1232", {1024,1, 1, 2, 192, 1232, 0xfe, 2, 8, 2, BPBGAP}},
+ {"1232", {1024,1, 1, 2, 192, 1232, 0xfe, 2, 8, 2, BPBGAP}},
{"1440", {512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2, BPBGAP}},
{"2880", {512, 2, 1, 2, 240, 5760, 0xf0, 9, 36, 2, BPBGAP}}
};
static const u_int8_t bootcode[] = {
- 0xfa, /* cli */
- 0x31, 0xc0, /* xor ax,ax */
- 0x8e, 0xd0, /* mov ss,ax */
- 0xbc, 0x00, 0x7c, /* mov sp,7c00h */
- 0xfb, /* sti */
- 0x8e, 0xd8, /* mov ds,ax */
- 0xe8, 0x00, 0x00, /* call $ + 3 */
- 0x5e, /* pop si */
- 0x83, 0xc6, 0x19, /* add si,+19h */
- 0xbb, 0x07, 0x00, /* mov bx,0007h */
- 0xfc, /* cld */
- 0xac, /* lodsb */
- 0x84, 0xc0, /* test al,al */
- 0x74, 0x06, /* jz $ + 8 */
- 0xb4, 0x0e, /* mov ah,0eh */
- 0xcd, 0x10, /* int 10h */
- 0xeb, 0xf5, /* jmp $ - 9 */
- 0x30, 0xe4, /* xor ah,ah */
- 0xcd, 0x16, /* int 16h */
- 0xcd, 0x19, /* int 19h */
+ 0xfa, /* cli */
+ 0x31, 0xc0, /* xor ax,ax */
+ 0x8e, 0xd0, /* mov ss,ax */
+ 0xbc, 0x00, 0x7c, /* mov sp,7c00h */
+ 0xfb, /* sti */
+ 0x8e, 0xd8, /* mov ds,ax */
+ 0xe8, 0x00, 0x00, /* call $ + 3 */
+ 0x5e, /* pop si */
+ 0x83, 0xc6, 0x19, /* add si,+19h */
+ 0xbb, 0x07, 0x00, /* mov bx,0007h */
+ 0xfc, /* cld */
+ 0xac, /* lodsb */
+ 0x84, 0xc0, /* test al,al */
+ 0x74, 0x06, /* jz $ + 8 */
+ 0xb4, 0x0e, /* mov ah,0eh */
+ 0xcd, 0x10, /* int 10h */
+ 0xeb, 0xf5, /* jmp $ - 9 */
+ 0x30, 0xe4, /* xor ah,ah */
+ 0xcd, 0x16, /* int 16h */
+ 0xcd, 0x19, /* int 19h */
0x0d, 0x0a,
'N', 'o', 'n', '-', 's', 'y', 's', 't',
'e', 'm', ' ', 'd', 'i', 's', 'k',
@@ -223,8 +223,7 @@
static void check_mounted(const char *, mode_t);
static void getstdfmt(const char *, struct bpb *);
-static void getdiskinfo(int, const char *, const char *, int,
- struct bpb *);
+static void getdiskinfo(int, const char *, const char *, int, struct bpb *);
static void print_bpb(struct bpb *);
static u_int ckgeom(const char *, u_int, const char *);
static u_int argtou(const char *, u_int, u_int, const char *);
@@ -237,8 +236,7 @@
/*
* Construct a FAT12, FAT16, or FAT32 file system.
*/
-int
-newfs_msdos_main(int argc, char *argv[])
+int newfs_msdos_main(int argc, char *argv[])
{
static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
const char *opt_B = NULL, *opt_L = NULL, *opt_O = NULL, *opt_f = NULL;
@@ -266,458 +264,444 @@
off_t opt_create = 0, opt_ofs = 0;
while ((ch = getopt(argc, argv, opts)) != -1)
- switch (ch) {
- case '@':
- opt_ofs = argtooff(optarg, "offset");
- break;
- case 'N':
- opt_N = 1;
- break;
- case 'B':
- opt_B = optarg;
- break;
- case 'C':
- opt_create = argtooff(optarg, "create size");
- break;
- case 'F':
- if (strcmp(optarg, "12") &&
- strcmp(optarg, "16") &&
- strcmp(optarg, "32"))
- errx(1, "%s: bad FAT type", optarg);
- opt_F = atoi(optarg);
- break;
- case 'I':
- opt_I = argto4(optarg, 0, "volume ID");
- Iflag = 1;
- break;
- case 'L':
- if (!oklabel(optarg))
- errx(1, "%s: bad volume label", optarg);
- opt_L = optarg;
- break;
- case 'O':
- if (strlen(optarg) > 8)
- errx(1, "%s: bad OEM string", optarg);
- opt_O = optarg;
- break;
- case 'S':
- opt_S = argto2(optarg, 1, "bytes/sector");
- break;
- case 'a':
- opt_a = argto4(optarg, 1, "sectors/FAT");
- break;
- case 'b':
- opt_b = argtox(optarg, 1, "block size");
- opt_c = 0;
- break;
- case 'c':
- opt_c = argto1(optarg, 1, "sectors/cluster");
- opt_b = 0;
- break;
- case 'e':
- opt_e = argto2(optarg, 1, "directory entries");
- break;
- case 'f':
- opt_f = optarg;
- break;
- case 'h':
- opt_h = argto2(optarg, 1, "drive heads");
- break;
- case 'i':
- opt_i = argto2(optarg, 1, "info sector");
- break;
- case 'k':
- opt_k = argto2(optarg, 1, "backup sector");
- break;
- case 'm':
- opt_m = argto1(optarg, 0, "media descriptor");
- mflag = 1;
- break;
- case 'n':
- opt_n = argto1(optarg, 1, "number of FATs");
- break;
- case 'o':
- opt_o = argto4(optarg, 0, "hidden sectors");
- oflag = 1;
- break;
- case 'r':
- opt_r = argto2(optarg, 1, "reserved sectors");
- break;
- case 's':
- opt_s = argto4(optarg, 1, "file system size");
- break;
- case 'u':
- opt_u = argto2(optarg, 1, "sectors/track");
- break;
- default:
- usage();
- }
+ switch (ch) {
+ case '@':
+ opt_ofs = argtooff(optarg, "offset");
+ break;
+ case 'N':
+ opt_N = 1;
+ break;
+ case 'B':
+ opt_B = optarg;
+ break;
+ case 'C':
+ opt_create = argtooff(optarg, "create size");
+ break;
+ case 'F':
+ if (strcmp(optarg, "12") && strcmp(optarg, "16") && strcmp(optarg, "32"))
+ errx(1, "%s: bad FAT type", optarg);
+ opt_F = atoi(optarg);
+ break;
+ case 'I':
+ opt_I = argto4(optarg, 0, "volume ID");
+ Iflag = 1;
+ break;
+ case 'L':
+ if (!oklabel(optarg))
+ errx(1, "%s: bad volume label", optarg);
+ opt_L = optarg;
+ break;
+ case 'O':
+ if (strlen(optarg) > 8)
+ errx(1, "%s: bad OEM string", optarg);
+ opt_O = optarg;
+ break;
+ case 'S':
+ opt_S = argto2(optarg, 1, "bytes/sector");
+ break;
+ case 'a':
+ opt_a = argto4(optarg, 1, "sectors/FAT");
+ break;
+ case 'b':
+ opt_b = argtox(optarg, 1, "block size");
+ opt_c = 0;
+ break;
+ case 'c':
+ opt_c = argto1(optarg, 1, "sectors/cluster");
+ opt_b = 0;
+ break;
+ case 'e':
+ opt_e = argto2(optarg, 1, "directory entries");
+ break;
+ case 'f':
+ opt_f = optarg;
+ break;
+ case 'h':
+ opt_h = argto2(optarg, 1, "drive heads");
+ break;
+ case 'i':
+ opt_i = argto2(optarg, 1, "info sector");
+ break;
+ case 'k':
+ opt_k = argto2(optarg, 1, "backup sector");
+ break;
+ case 'm':
+ opt_m = argto1(optarg, 0, "media descriptor");
+ mflag = 1;
+ break;
+ case 'n':
+ opt_n = argto1(optarg, 1, "number of FATs");
+ break;
+ case 'o':
+ opt_o = argto4(optarg, 0, "hidden sectors");
+ oflag = 1;
+ break;
+ case 'r':
+ opt_r = argto2(optarg, 1, "reserved sectors");
+ break;
+ case 's':
+ opt_s = argto4(optarg, 1, "file system size");
+ break;
+ case 'u':
+ opt_u = argto2(optarg, 1, "sectors/track");
+ break;
+ default:
+ usage();
+ }
argc -= optind;
argv += optind;
if (argc < 1 || argc > 2)
- usage();
+ usage();
fname = *argv++;
if (!opt_create && !strchr(fname, '/')) {
- snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
- if (!(fname = strdup(buf)))
- err(1, "%s", buf);
+ snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
+ if (!(fname = strdup(buf)))
+ err(1, "%s", buf);
}
dtype = *argv;
if (opt_create) {
- if (opt_N)
- errx(1, "create (-C) is incompatible with -N");
- fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
- if (fd == -1)
- errx(1, "failed to create %s", fname);
- if (ftruncate(fd, opt_create))
- errx(1, "failed to initialize %jd bytes", (intmax_t)opt_create);
+ if (opt_N)
+ errx(1, "create (-C) is incompatible with -N");
+ fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1)
+ errx(1, "failed to create %s", fname);
+ if (ftruncate(fd, opt_create))
+ errx(1, "failed to initialize %jd bytes", (intmax_t)opt_create);
} else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1)
- err(1, "%s", fname);
+ err(1, "%s", fname);
if (fstat(fd, &sb))
- err(1, "%s", fname);
+ err(1, "%s", fname);
if (opt_create) {
- if (!S_ISREG(sb.st_mode))
- warnx("warning, %s is not a regular file", fname);
+ if (!S_ISREG(sb.st_mode))
+ warnx("warning, %s is not a regular file", fname);
} else {
- if (!S_ISCHR(sb.st_mode))
- warnx("warning, %s is not a character device", fname);
+ if (!S_ISCHR(sb.st_mode))
+ warnx("warning, %s is not a character device", fname);
}
if (!opt_N)
- check_mounted(fname, sb.st_mode);
+ check_mounted(fname, sb.st_mode);
if (opt_ofs && opt_ofs != lseek(fd, opt_ofs, SEEK_SET))
- errx(1, "cannot seek to %jd", (intmax_t)opt_ofs);
+ errx(1, "cannot seek to %jd", (intmax_t)opt_ofs);
memset(&bpb, 0, sizeof(bpb));
if (opt_f) {
- getstdfmt(opt_f, &bpb);
- bpb.bsec = bpb.sec;
- bpb.sec = 0;
- bpb.bspf = bpb.spf;
- bpb.spf = 0;
+ getstdfmt(opt_f, &bpb);
+ bpb.bsec = bpb.sec;
+ bpb.sec = 0;
+ bpb.bspf = bpb.spf;
+ bpb.spf = 0;
}
if (opt_h)
- bpb.hds = opt_h;
+ bpb.hds = opt_h;
if (opt_u)
- bpb.spt = opt_u;
+ bpb.spt = opt_u;
if (opt_S)
- bpb.bps = opt_S;
+ bpb.bps = opt_S;
if (opt_s)
- bpb.bsec = opt_s;
+ bpb.bsec = opt_s;
if (oflag)
- bpb.hid = opt_o;
+ bpb.hid = opt_o;
if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
- off_t delta;
- getdiskinfo(fd, fname, dtype, oflag, &bpb);
+ off_t delta;
+ getdiskinfo(fd, fname, dtype, oflag, &bpb);
if (opt_s) {
bpb.bsec = opt_s;
}
- bpb.bsec -= (opt_ofs / bpb.bps);
- delta = bpb.bsec % bpb.spt;
- if (delta != 0) {
- warnx("trim %d sectors from %d to adjust to a multiple of %d",
- (int)delta, bpb.bsec, bpb.spt);
- bpb.bsec -= delta;
- }
- if (bpb.spc == 0) { /* set defaults */
- if (bpb.bsec <= 6000) /* about 3MB -> 512 bytes */
- bpb.spc = 1;
- else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
- bpb.spc = 8;
- else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
- bpb.spc = 16;
- else if (bpb.bsec <= (1<<22)) /* 2G -> 16k, some versions of windows
- require a minimum of 65527 clusters */
- bpb.spc = 32;
- else
- bpb.spc = 64; /* otherwise 32k */
- }
+ bpb.bsec -= (opt_ofs / bpb.bps);
+ delta = bpb.bsec % bpb.spt;
+ if (delta != 0) {
+ warnx("trim %d sectors from %d to adjust to a multiple of %d",
+ (int)delta, bpb.bsec, bpb.spt);
+ bpb.bsec -= delta;
+ }
+ if (bpb.spc == 0) { /* set defaults */
+ if (bpb.bsec <= 6000) /* about 3MB -> 512 bytes */
+ bpb.spc = 1;
+ else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
+ bpb.spc = 8;
+ else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
+ bpb.spc = 16;
+ else if (bpb.bsec <= (1<<22)) /* 2G -> 16k, some versions of windows
+ require a minimum of 65527 clusters */
+ bpb.spc = 32;
+ else
+ bpb.spc = 64; /* otherwise 32k */
+ }
}
if (!powerof2(bpb.bps))
- errx(1, "bytes/sector (%u) is not a power of 2", bpb.bps);
+ errx(1, "bytes/sector (%u) is not a power of 2", bpb.bps);
if (bpb.bps < MINBPS)
- errx(1, "bytes/sector (%u) is too small; minimum is %u",
- bpb.bps, MINBPS);
+ errx(1, "bytes/sector (%u) is too small; minimum is %u",
+ bpb.bps, MINBPS);
if (!(fat = opt_F)) {
- if (opt_f)
- fat = 12;
- else if (!opt_e && (opt_i || opt_k))
- fat = 32;
+ if (opt_f)
+ fat = 12;
+ else if (!opt_e && (opt_i || opt_k))
+ fat = 32;
}
if ((fat == 32 && opt_e) || (fat != 32 && (opt_i || opt_k)))
- errx(1, "-%c is not a legal FAT%s option",
- fat == 32 ? 'e' : opt_i ? 'i' : 'k',
- fat == 32 ? "32" : "12/16");
+ errx(1, "-%c is not a legal FAT%s option",
+ fat == 32 ? 'e' : opt_i ? 'i' : 'k',
+ fat == 32 ? "32" : "12/16");
if (opt_f && fat == 32)
- bpb.rde = 0;
+ bpb.rde = 0;
if (opt_b) {
- if (!powerof2(opt_b))
- errx(1, "block size (%u) is not a power of 2", opt_b);
- if (opt_b < bpb.bps)
- errx(1, "block size (%u) is too small; minimum is %u",
- opt_b, bpb.bps);
- if (opt_b > bpb.bps * MAXSPC)
- errx(1, "block size (%u) is too large; maximum is %u",
- opt_b, bpb.bps * MAXSPC);
- bpb.spc = opt_b / bpb.bps;
+ if (!powerof2(opt_b))
+ errx(1, "block size (%u) is not a power of 2", opt_b);
+ if (opt_b < bpb.bps)
+ errx(1, "block size (%u) is too small; minimum is %u",
+ opt_b, bpb.bps);
+ if (opt_b > bpb.bps * MAXSPC)
+ errx(1, "block size (%u) is too large; maximum is %u", opt_b, bpb.bps * MAXSPC);
+ bpb.spc = opt_b / bpb.bps;
}
if (opt_c) {
- if (!powerof2(opt_c))
- errx(1, "sectors/cluster (%u) is not a power of 2", opt_c);
- bpb.spc = opt_c;
+ if (!powerof2(opt_c))
+ errx(1, "sectors/cluster (%u) is not a power of 2", opt_c);
+ bpb.spc = opt_c;
}
if (opt_r)
- bpb.res = opt_r;
+ bpb.res = opt_r;
if (opt_n) {
- if (opt_n > MAXNFT)
- errx(1, "number of FATs (%u) is too large; maximum is %u",
- opt_n, MAXNFT);
- bpb.nft = opt_n;
+ if (opt_n > MAXNFT)
+ errx(1, "number of FATs (%u) is too large; maximum is %u", opt_n, MAXNFT);
+ bpb.nft = opt_n;
}
if (opt_e)
- bpb.rde = opt_e;
+ bpb.rde = opt_e;
if (mflag) {
- if (opt_m < 0xf0)
- errx(1, "illegal media descriptor (%#x)", opt_m);
- bpb.mid = opt_m;
+ if (opt_m < 0xf0)
+ errx(1, "illegal media descriptor (%#x)", opt_m);
+ bpb.mid = opt_m;
}
if (opt_a)
- bpb.bspf = opt_a;
+ bpb.bspf = opt_a;
if (opt_i)
- bpb.infs = opt_i;
+ bpb.infs = opt_i;
if (opt_k)
- bpb.bkbs = opt_k;
+ bpb.bkbs = opt_k;
bss = 1;
bname = NULL;
fd1 = -1;
if (opt_B) {
- bname = opt_B;
- if (!strchr(bname, '/')) {
- snprintf(buf, sizeof(buf), "/boot/%s", bname);
- if (!(bname = strdup(buf)))
- err(1, "%s", buf);
- }
- if ((fd1 = open(bname, O_RDONLY)) == -1 || fstat(fd1, &sb))
- err(1, "%s", bname);
- if (!S_ISREG(sb.st_mode) || sb.st_size % bpb.bps ||
- sb.st_size < bpb.bps || sb.st_size > bpb.bps * MAXU16)
- errx(1, "%s: inappropriate file type or format", bname);
- bss = sb.st_size / bpb.bps;
+ bname = opt_B;
+ if (!strchr(bname, '/')) {
+ snprintf(buf, sizeof(buf), "/boot/%s", bname);
+ if (!(bname = strdup(buf)))
+ err(1, "%s", buf);
+ }
+ if ((fd1 = open(bname, O_RDONLY)) == -1 || fstat(fd1, &sb))
+ err(1, "%s", bname);
+ if (!S_ISREG(sb.st_mode) || sb.st_size % bpb.bps ||
+ sb.st_size < bpb.bps || sb.st_size > bpb.bps * MAXU16)
+ errx(1, "%s: inappropriate file type or format", bname);
+ bss = sb.st_size / bpb.bps;
}
if (!bpb.nft)
- bpb.nft = 2;
+ bpb.nft = 2;
if (!fat) {
- if (bpb.bsec < (bpb.res ? bpb.res : bss) +
- howmany((RESFTE + (bpb.spc ? MINCLS16 : MAXCLS12 + 1)) *
- ((bpb.spc ? 16 : 12) / BPN), bpb.bps * NPB) *
- bpb.nft +
- howmany(bpb.rde ? bpb.rde : DEFRDE,
- bpb.bps / sizeof(struct de)) +
- (bpb.spc ? MINCLS16 : MAXCLS12 + 1) *
- (bpb.spc ? bpb.spc : howmany(DEFBLK, bpb.bps)))
- fat = 12;
- else if (bpb.rde || bpb.bsec <
- (bpb.res ? bpb.res : bss) +
- howmany((RESFTE + MAXCLS16) * 2, bpb.bps) * bpb.nft +
- howmany(DEFRDE, bpb.bps / sizeof(struct de)) +
- (MAXCLS16 + 1) *
- (bpb.spc ? bpb.spc : howmany(8192, bpb.bps)))
- fat = 16;
- else
- fat = 32;
+ if (bpb.bsec < (bpb.res ? bpb.res : bss) +
+ howmany((RESFTE + (bpb.spc ? MINCLS16 : MAXCLS12 + 1)) *
+ ((bpb.spc ? 16 : 12) / BPN), bpb.bps * NPB) *
+ bpb.nft +
+ howmany(bpb.rde ? bpb.rde : DEFRDE,
+ bpb.bps / sizeof(struct de)) +
+ (bpb.spc ? MINCLS16 : MAXCLS12 + 1) *
+ (bpb.spc ? bpb.spc : howmany(DEFBLK, bpb.bps)))
+ fat = 12;
+ else if (bpb.rde || bpb.bsec <
+ (bpb.res ? bpb.res : bss) +
+ howmany((RESFTE + MAXCLS16) * 2, bpb.bps) * bpb.nft +
+ howmany(DEFRDE, bpb.bps / sizeof(struct de)) +
+ (MAXCLS16 + 1) *
+ (bpb.spc ? bpb.spc : howmany(8192, bpb.bps)))
+ fat = 16;
+ else
+ fat = 32;
}
x = bss;
if (fat == 32) {
- if (!bpb.infs) {
- if (x == MAXU16 || x == bpb.bkbs)
- errx(1, "no room for info sector");
- bpb.infs = x;
- }
- if (bpb.infs != MAXU16 && x <= bpb.infs)
- x = bpb.infs + 1;
- if (!bpb.bkbs) {
- if (x == MAXU16)
- errx(1, "no room for backup sector");
- bpb.bkbs = x;
- } else if (bpb.bkbs != MAXU16 && bpb.bkbs == bpb.infs)
- errx(1, "backup sector would overwrite info sector");
- if (bpb.bkbs != MAXU16 && x <= bpb.bkbs)
- x = bpb.bkbs + 1;
+ if (!bpb.infs) {
+ if (x == MAXU16 || x == bpb.bkbs)
+ errx(1, "no room for info sector");
+ bpb.infs = x;
+ }
+ if (bpb.infs != MAXU16 && x <= bpb.infs)
+ x = bpb.infs + 1;
+ if (!bpb.bkbs) {
+ if (x == MAXU16)
+ errx(1, "no room for backup sector");
+ bpb.bkbs = x;
+ } else if (bpb.bkbs != MAXU16 && bpb.bkbs == bpb.infs)
+ errx(1, "backup sector would overwrite info sector");
+ if (bpb.bkbs != MAXU16 && x <= bpb.bkbs)
+ x = bpb.bkbs + 1;
}
if (!bpb.res)
- bpb.res = fat == 32 ? MAX(x, MAX(16384 / bpb.bps, 4)) : x;
+ bpb.res = fat == 32 ? MAX(x, MAX(16384 / bpb.bps, 4)) : x;
else if (bpb.res < x)
- errx(1, "too few reserved sectors");
+ errx(1, "too few reserved sectors");
if (fat != 32 && !bpb.rde)
- bpb.rde = DEFRDE;
+ bpb.rde = DEFRDE;
rds = howmany(bpb.rde, bpb.bps / sizeof(struct de));
if (!bpb.spc)
- for (bpb.spc = howmany(fat == 16 ? DEFBLK16 : DEFBLK, bpb.bps);
- bpb.spc < MAXSPC &&
- bpb.res +
- howmany((RESFTE + maxcls(fat)) * (fat / BPN),
- bpb.bps * NPB) * bpb.nft +
- rds +
- (u_int64_t)(maxcls(fat) + 1) * bpb.spc <= bpb.bsec;
- bpb.spc <<= 1);
+ for (bpb.spc = howmany(fat == 16 ? DEFBLK16 : DEFBLK, bpb.bps);
+ bpb.spc < MAXSPC &&
+ bpb.res +
+ howmany((RESFTE + maxcls(fat)) * (fat / BPN),
+ bpb.bps * NPB) * bpb.nft +
+ rds +
+ (u_int64_t)(maxcls(fat) + 1) * bpb.spc <= bpb.bsec;
+ bpb.spc <<= 1);
if (fat != 32 && bpb.bspf > MAXU16)
- errx(1, "too many sectors/FAT for FAT12/16");
+ errx(1, "too many sectors/FAT for FAT12/16");
x1 = bpb.res + rds;
x = bpb.bspf ? bpb.bspf : 1;
if (x1 + (u_int64_t)x * bpb.nft > bpb.bsec)
- errx(1, "meta data exceeds file system size");
+ errx(1, "meta data exceeds file system size");
x1 += x * bpb.nft;
x = (u_int64_t)(bpb.bsec - x1) * bpb.bps * NPB /
- (bpb.spc * bpb.bps * NPB + fat / BPN * bpb.nft);
- x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN),
- bpb.bps * NPB);
+ (bpb.spc * bpb.bps * NPB + fat / BPN * bpb.nft);
+ x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN), bpb.bps * NPB);
if (!bpb.bspf) {
- bpb.bspf = x2;
- x1 += (bpb.bspf - 1) * bpb.nft;
+ bpb.bspf = x2;
+ x1 += (bpb.bspf - 1) * bpb.nft;
}
cls = (bpb.bsec - x1) / bpb.spc;
x = (u_int64_t)bpb.bspf * bpb.bps * NPB / (fat / BPN) - RESFTE;
if (cls > x)
- cls = x;
+ cls = x;
if (bpb.bspf < x2)
- warnx("warning: sectors/FAT limits file system to %u clusters",
- cls);
+ warnx("warning: sectors/FAT limits file system to %u clusters", cls);
if (cls < mincls(fat))
- errx(1, "%u clusters too few clusters for FAT%u, need %u", cls, fat,
- mincls(fat));
+ errx(1, "%u clusters too few clusters for FAT%u, need %u", cls, fat, mincls(fat));
if (cls > maxcls(fat)) {
- cls = maxcls(fat);
- bpb.bsec = x1 + (cls + 1) * bpb.spc - 1;
- warnx("warning: FAT type limits file system to %u sectors",
- bpb.bsec);
+ cls = maxcls(fat);
+ bpb.bsec = x1 + (cls + 1) * bpb.spc - 1;
+ warnx("warning: FAT type limits file system to %u sectors", bpb.bsec);
}
- printf("%s: %u sector%s in %u FAT%u cluster%s "
- "(%u bytes/cluster)\n", fname, cls * bpb.spc,
- cls * bpb.spc == 1 ? "" : "s", cls, fat,
- cls == 1 ? "" : "s", bpb.bps * bpb.spc);
+ printf("%s: %u sector%s in %u FAT%u cluster%s (%u bytes/cluster)\n",
+ fname, cls * bpb.spc, cls * bpb.spc == 1 ? "" : "s", cls, fat,
+ cls == 1 ? "" : "s", bpb.bps * bpb.spc);
if (!bpb.mid)
- bpb.mid = !bpb.hid ? 0xf0 : 0xf8;
+ bpb.mid = !bpb.hid ? 0xf0 : 0xf8;
if (fat == 32)
- bpb.rdcl = RESFTE;
+ bpb.rdcl = RESFTE;
if (bpb.hid + bpb.bsec <= MAXU16) {
- bpb.sec = bpb.bsec;
- bpb.bsec = 0;
+ bpb.sec = bpb.bsec;
+ bpb.bsec = 0;
}
if (fat != 32) {
- bpb.spf = bpb.bspf;
- bpb.bspf = 0;
+ bpb.spf = bpb.bspf;
+ bpb.bspf = 0;
}
print_bpb(&bpb);
if (!opt_N) {
- gettimeofday(&tv, NULL);
- now = tv.tv_sec;
- tm = localtime(&now);
- if (!(img = malloc(bpb.bps)))
- err(1, "%u", bpb.bps);
- dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft;
- for (lsn = 0; lsn < dir + (fat == 32 ? bpb.spc : rds); lsn++) {
- x = lsn;
- if (opt_B &&
- fat == 32 && bpb.bkbs != MAXU16 &&
- bss <= bpb.bkbs && x >= bpb.bkbs) {
- x -= bpb.bkbs;
- if (!x && lseek(fd1, opt_ofs, SEEK_SET))
- err(1, "%s", bname);
- }
- if (opt_B && x < bss) {
- if ((n = read(fd1, img, bpb.bps)) == -1)
- err(1, "%s", bname);
- if ((unsigned)n != bpb.bps)
- errx(1, "%s: can't read sector %u", bname, x);
- } else
- memset(img, 0, bpb.bps);
- if (!lsn ||
- (fat == 32 && bpb.bkbs != MAXU16 && lsn == bpb.bkbs)) {
- x1 = sizeof(struct bs);
- bsbpb = (struct bsbpb *)(img + x1);
- mk2(bsbpb->bps, bpb.bps);
- mk1(bsbpb->spc, bpb.spc);
- mk2(bsbpb->res, bpb.res);
- mk1(bsbpb->nft, bpb.nft);
- mk2(bsbpb->rde, bpb.rde);
- mk2(bsbpb->sec, bpb.sec);
- mk1(bsbpb->mid, bpb.mid);
- mk2(bsbpb->spf, bpb.spf);
- mk2(bsbpb->spt, bpb.spt);
- mk2(bsbpb->hds, bpb.hds);
- mk4(bsbpb->hid, bpb.hid);
- mk4(bsbpb->bsec, bpb.bsec);
- x1 += sizeof(struct bsbpb);
- if (fat == 32) {
- bsxbpb = (struct bsxbpb *)(img + x1);
- mk4(bsxbpb->bspf, bpb.bspf);
- mk2(bsxbpb->xflg, 0);
- mk2(bsxbpb->vers, 0);
- mk4(bsxbpb->rdcl, bpb.rdcl);
- mk2(bsxbpb->infs, bpb.infs);
- mk2(bsxbpb->bkbs, bpb.bkbs);
- x1 += sizeof(struct bsxbpb);
- }
- bsx = (struct bsx *)(img + x1);
- mk1(bsx->sig, 0x29);
- if (Iflag)
- x = opt_I;
- else
- x = (((u_int)(1 + tm->tm_mon) << 8 |
- (u_int)tm->tm_mday) +
- ((u_int)tm->tm_sec << 8 |
- (u_int)(tv.tv_usec / 10))) << 16 |
- ((u_int)(1900 + tm->tm_year) +
- ((u_int)tm->tm_hour << 8 |
- (u_int)tm->tm_min));
- mk4(bsx->volid, x);
- mklabel(bsx->label, opt_L ? opt_L : "NO NAME");
- sprintf(buf, "FAT%u", fat);
- setstr(bsx->type, buf, sizeof(bsx->type));
- if (!opt_B) {
- x1 += sizeof(struct bsx);
- bs = (struct bs *)img;
- mk1(bs->jmp[0], 0xeb);
- mk1(bs->jmp[1], x1 - 2);
- mk1(bs->jmp[2], 0x90);
- setstr(bs->oem, opt_O ? opt_O : "BSD 4.4",
- sizeof(bs->oem));
- memcpy(img + x1, bootcode, sizeof(bootcode));
- mk2(img + MINBPS - 2, DOSMAGIC);
- }
- } else if (fat == 32 && bpb.infs != MAXU16 &&
- (lsn == bpb.infs ||
- (bpb.bkbs != MAXU16 &&
- lsn == bpb.bkbs + bpb.infs))) {
- mk4(img, 0x41615252);
- mk4(img + MINBPS - 28, 0x61417272);
- mk4(img + MINBPS - 24, 0xffffffff);
- mk4(img + MINBPS - 20, bpb.rdcl);
- mk2(img + MINBPS - 2, DOSMAGIC);
- } else if (lsn >= bpb.res && lsn < dir &&
- !((lsn - bpb.res) %
- (bpb.spf ? bpb.spf : bpb.bspf))) {
- mk1(img[0], bpb.mid);
- for (x = 1; x < fat * (fat == 32 ? 3 : 2) / 8; x++)
- mk1(img[x], fat == 32 && x % 4 == 3 ? 0x0f : 0xff);
- } else if (lsn == dir && opt_L) {
- de = (struct de *)img;
- mklabel(de->namext, opt_L);
- mk1(de->attr, 050);
- x = (u_int)tm->tm_hour << 11 |
- (u_int)tm->tm_min << 5 |
- (u_int)tm->tm_sec >> 1;
- mk2(de->time, x);
- x = (u_int)(tm->tm_year - 80) << 9 |
- (u_int)(tm->tm_mon + 1) << 5 |
- (u_int)tm->tm_mday;
- mk2(de->date, x);
- }
- if ((n = write(fd, img, bpb.bps)) == -1)
- err(1, "%s", fname);
- if ((unsigned)n != bpb.bps) {
- errx(1, "%s: can't write sector %u", fname, lsn);
+ gettimeofday(&tv, NULL);
+ now = tv.tv_sec;
+ tm = localtime(&now);
+ if (!(img = malloc(bpb.bps)))
+ err(1, "%u", bpb.bps);
+ dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft;
+ for (lsn = 0; lsn < dir + (fat == 32 ? bpb.spc : rds); lsn++) {
+ x = lsn;
+ if (opt_B && fat == 32 && bpb.bkbs != MAXU16 && bss <= bpb.bkbs && x >= bpb.bkbs) {
+ x -= bpb.bkbs;
+ if (!x && lseek(fd1, opt_ofs, SEEK_SET))
+ err(1, "%s", bname);
+ }
+ if (opt_B && x < bss) {
+ if ((n = read(fd1, img, bpb.bps)) == -1)
+ err(1, "%s", bname);
+ if ((unsigned)n != bpb.bps)
+ errx(1, "%s: can't read sector %u", bname, x);
+ } else
+ memset(img, 0, bpb.bps);
+ if (!lsn || (fat == 32 && bpb.bkbs != MAXU16 && lsn == bpb.bkbs)) {
+ x1 = sizeof(struct bs);
+ bsbpb = (struct bsbpb *)(img + x1);
+ mk2(bsbpb->bps, bpb.bps);
+ mk1(bsbpb->spc, bpb.spc);
+ mk2(bsbpb->res, bpb.res);
+ mk1(bsbpb->nft, bpb.nft);
+ mk2(bsbpb->rde, bpb.rde);
+ mk2(bsbpb->sec, bpb.sec);
+ mk1(bsbpb->mid, bpb.mid);
+ mk2(bsbpb->spf, bpb.spf);
+ mk2(bsbpb->spt, bpb.spt);
+ mk2(bsbpb->hds, bpb.hds);
+ mk4(bsbpb->hid, bpb.hid);
+ mk4(bsbpb->bsec, bpb.bsec);
+ x1 += sizeof(struct bsbpb);
+ if (fat == 32) {
+ bsxbpb = (struct bsxbpb *)(img + x1);
+ mk4(bsxbpb->bspf, bpb.bspf);
+ mk2(bsxbpb->xflg, 0);
+ mk2(bsxbpb->vers, 0);
+ mk4(bsxbpb->rdcl, bpb.rdcl);
+ mk2(bsxbpb->infs, bpb.infs);
+ mk2(bsxbpb->bkbs, bpb.bkbs);
+ x1 += sizeof(struct bsxbpb);
+ }
+ bsx = (struct bsx *)(img + x1);
+ mk1(bsx->sig, 0x29);
+ if (Iflag)
+ x = opt_I;
+ else
+ x = (((u_int)(1 + tm->tm_mon) << 8 |
+ (u_int)tm->tm_mday) +
+ ((u_int)tm->tm_sec << 8 |
+ (u_int)(tv.tv_usec / 10))) << 16 |
+ ((u_int)(1900 + tm->tm_year) +
+ ((u_int)tm->tm_hour << 8 |
+ (u_int)tm->tm_min));
+ mk4(bsx->volid, x);
+ mklabel(bsx->label, opt_L ? opt_L : "NO NAME");
+ sprintf(buf, "FAT%u", fat);
+ setstr(bsx->type, buf, sizeof(bsx->type));
+ if (!opt_B) {
+ x1 += sizeof(struct bsx);
+ bs = (struct bs *)img;
+ mk1(bs->jmp[0], 0xeb);
+ mk1(bs->jmp[1], x1 - 2);
+ mk1(bs->jmp[2], 0x90);
+ setstr(bs->oem, opt_O ? opt_O : "BSD 4.4",
+ sizeof(bs->oem));
+ memcpy(img + x1, bootcode, sizeof(bootcode));
+ mk2(img + MINBPS - 2, DOSMAGIC);
+ }
+ } else if (fat == 32 && bpb.infs != MAXU16 &&
+ (lsn == bpb.infs || (bpb.bkbs != MAXU16 &&
+ lsn == bpb.bkbs + bpb.infs))) {
+ mk4(img, 0x41615252);
+ mk4(img + MINBPS - 28, 0x61417272);
+ mk4(img + MINBPS - 24, 0xffffffff);
+ mk4(img + MINBPS - 20, bpb.rdcl);
+ mk2(img + MINBPS - 2, DOSMAGIC);
+ } else if (lsn >= bpb.res && lsn < dir &&
+ !((lsn - bpb.res) % (bpb.spf ? bpb.spf : bpb.bspf))) {
+ mk1(img[0], bpb.mid);
+ for (x = 1; x < fat * (fat == 32 ? 3 : 2) / 8; x++)
+ mk1(img[x], fat == 32 && x % 4 == 3 ? 0x0f : 0xff);
+ } else if (lsn == dir && opt_L) {
+ de = (struct de *)img;
+ mklabel(de->namext, opt_L);
+ mk1(de->attr, 050);
+ x = (u_int)tm->tm_hour << 11 |
+ (u_int)tm->tm_min << 5 |
+ (u_int)tm->tm_sec >> 1;
+ mk2(de->time, x);
+ x = (u_int)(tm->tm_year - 80) << 9 |
+ (u_int)(tm->tm_mon + 1) << 5 |
+ (u_int)tm->tm_mday;
+ mk2(de->date, x);
+ }
+ if ((n = write(fd, img, bpb.bps)) == -1)
+ err(1, "%s", fname);
+ if ((unsigned)n != bpb.bps) {
+ errx(1, "%s: can't write sector %u", fname, lsn);
exit(1);
}
- }
+ }
}
return 0;
}
@@ -725,8 +709,7 @@
/*
* Exit with error if file system is mounted.
*/
-static void
-check_mounted(const char *fname, mode_t mode)
+static void check_mounted(const char *fname, mode_t mode)
{
#ifdef ANDROID
warnx("Skipping mount checks");
@@ -737,19 +720,18 @@
int n, r;
if (!(n = getmntinfo(&mp, MNT_NOWAIT)))
- err(1, "getmntinfo");
+ err(1, "getmntinfo");
len = strlen(_PATH_DEV);
s1 = fname;
if (!strncmp(s1, _PATH_DEV, len))
- s1 += len;
+ s1 += len;
r = S_ISCHR(mode) && s1 != fname && *s1 == 'r';
for (; n--; mp++) {
- s2 = mp->f_mntfromname;
- if (!strncmp(s2, _PATH_DEV, len))
- s2 += len;
- if ((r && s2 != mp->f_mntfromname && !strcmp(s1 + 1, s2)) ||
- !strcmp(s1, s2))
- errx(1, "%s is mounted on %s", fname, mp->f_mntonname);
+ s2 = mp->f_mntfromname;
+ if (!strncmp(s2, _PATH_DEV, len))
+ s2 += len;
+ if ((r && s2 != mp->f_mntfromname && !strcmp(s1 + 1, s2)) || !strcmp(s1, s2))
+ errx(1, "%s is mounted on %s", fname, mp->f_mntonname);
}
#endif
}
@@ -757,15 +739,14 @@
/*
* Get a standard format.
*/
-static void
-getstdfmt(const char *fmt, struct bpb *bpb)
+static void getstdfmt(const char *fmt, struct bpb *bpb)
{
u_int x, i;
x = sizeof(stdfmt) / sizeof(stdfmt[0]);
for (i = 0; i < x && strcmp(fmt, stdfmt[i].name); i++);
if (i == x)
- errx(1, "%s: unknown standard format", fmt);
+ errx(1, "%s: unknown standard format", fmt);
*bpb = stdfmt[i].bpb;
}
@@ -774,9 +755,8 @@
*/
#ifdef ANDROID
-static void
-getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
- struct bpb *bpb)
+static void getdiskinfo(int fd, const char *fname, const char *dtype,
+ __unused int oflag,struct bpb *bpb)
{
struct hd_geometry geom;
@@ -817,9 +797,8 @@
#else
-static void
-getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
- struct bpb *bpb)
+static void getdiskinfo(int fd, const char *fname, const char *dtype,
+ __unused int oflag, struct bpb *bpb)
{
struct disklabel *lp, dlp;
struct fd_type type;
@@ -829,97 +808,96 @@
/* If the user specified a disk type, try to use that */
if (dtype != NULL) {
- lp = getdiskbyname(dtype);
+ lp = getdiskbyname(dtype);
}
/* Maybe it's a floppy drive */
if (lp == NULL) {
- if (ioctl(fd, DIOCGMEDIASIZE, &ms) == -1) {
- struct stat st;
+ if (ioctl(fd, DIOCGMEDIASIZE, &ms) == -1) {
+ struct stat st;
- if (fstat(fd, &st))
- err(1, "Cannot get disk size");
- /* create a fake geometry for a file image */
- ms = st.st_size;
- dlp.d_secsize = 512;
- dlp.d_nsectors = 63;
- dlp.d_ntracks = 255;
- dlp.d_secperunit = ms / dlp.d_secsize;
- lp = &dlp;
- } else if (ioctl(fd, FD_GTYPE, &type) != -1) {
- dlp.d_secsize = 128 << type.secsize;
- dlp.d_nsectors = type.sectrac;
- dlp.d_ntracks = type.heads;
- dlp.d_secperunit = ms / dlp.d_secsize;
- lp = &dlp;
- }
+ if (fstat(fd, &st))
+ err(1, "Cannot get disk size");
+ /* create a fake geometry for a file image */
+ ms = st.st_size;
+ dlp.d_secsize = 512;
+ dlp.d_nsectors = 63;
+ dlp.d_ntracks = 255;
+ dlp.d_secperunit = ms / dlp.d_secsize;
+ lp = &dlp;
+ } else if (ioctl(fd, FD_GTYPE, &type) != -1) {
+ dlp.d_secsize = 128 << type.secsize;
+ dlp.d_nsectors = type.sectrac;
+ dlp.d_ntracks = type.heads;
+ dlp.d_secperunit = ms / dlp.d_secsize;
+ lp = &dlp;
+ }
}
/* Maybe it's a fixed drive */
if (lp == NULL) {
- if (ioctl(fd, DIOCGDINFO, &dlp) == -1) {
- if (bpb->bps == 0 && ioctl(fd, DIOCGSECTORSIZE, &dlp.d_secsize) == -1)
- errx(1, "Cannot get sector size, %s", strerror(errno));
+ if (ioctl(fd, DIOCGDINFO, &dlp) == -1) {
+ if (bpb->bps == 0 && ioctl(fd, DIOCGSECTORSIZE, &dlp.d_secsize) == -1)
+ errx(1, "Cannot get sector size, %s", strerror(errno));
- /* XXX Should we use bpb->bps if it's set? */
- dlp.d_secperunit = ms / dlp.d_secsize;
+ /* XXX Should we use bpb->bps if it's set? */
+ dlp.d_secperunit = ms / dlp.d_secsize;
- if (bpb->spt == 0 && ioctl(fd, DIOCGFWSECTORS, &dlp.d_nsectors) == -1) {
- warnx("Cannot get number of sectors per track, %s", strerror(errno));
- dlp.d_nsectors = 63;
- }
- if (bpb->hds == 0 && ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
- warnx("Cannot get number of heads, %s", strerror(errno));
- if (dlp.d_secperunit <= 63*1*1024)
- dlp.d_ntracks = 1;
- else if (dlp.d_secperunit <= 63*16*1024)
- dlp.d_ntracks = 16;
- else
- dlp.d_ntracks = 255;
- }
- }
+ if (bpb->spt == 0 && ioctl(fd, DIOCGFWSECTORS, &dlp.d_nsectors) == -1) {
+ warnx("Cannot get number of sectors per track, %s", strerror(errno));
+ dlp.d_nsectors = 63;
+ }
+ if (bpb->hds == 0 && ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
+ warnx("Cannot get number of heads, %s", strerror(errno));
+ if (dlp.d_secperunit <= 63*1*1024)
+ dlp.d_ntracks = 1;
+ else if (dlp.d_secperunit <= 63*16*1024)
+ dlp.d_ntracks = 16;
+ else
+ dlp.d_ntracks = 255;
+ }
+ }
- hs = (ms / dlp.d_secsize) - dlp.d_secperunit;
- lp = &dlp;
+ hs = (ms / dlp.d_secsize) - dlp.d_secperunit;
+ lp = &dlp;
}
if (bpb->bps == 0)
- bpb->bps = ckgeom(fname, lp->d_secsize, "bytes/sector");
+ bpb->bps = ckgeom(fname, lp->d_secsize, "bytes/sector");
if (bpb->spt == 0)
- bpb->spt = ckgeom(fname, lp->d_nsectors, "sectors/track");
+ bpb->spt = ckgeom(fname, lp->d_nsectors, "sectors/track");
if (bpb->hds == 0)
- bpb->hds = ckgeom(fname, lp->d_ntracks, "drive heads");
+ bpb->hds = ckgeom(fname, lp->d_ntracks, "drive heads");
if (bpb->bsec == 0)
- bpb->bsec = lp->d_secperunit;
+ bpb->bsec = lp->d_secperunit;
if (bpb->hid == 0)
- bpb->hid = hs;
+ bpb->hid = hs;
}
#endif
/*
* Print out BPB values.
*/
-static void
-print_bpb(struct bpb *bpb)
+static void print_bpb(struct bpb *bpb)
{
printf("bps=%u spc=%u res=%u nft=%u", bpb->bps, bpb->spc, bpb->res,
- bpb->nft);
+ bpb->nft);
if (bpb->rde)
- printf(" rde=%u", bpb->rde);
+ printf(" rde=%u", bpb->rde);
if (bpb->sec)
- printf(" sec=%u", bpb->sec);
+ printf(" sec=%u", bpb->sec);
printf(" mid=%#x", bpb->mid);
if (bpb->spf)
- printf(" spf=%u", bpb->spf);
+ printf(" spf=%u", bpb->spf);
printf(" spt=%u hds=%u hid=%u", bpb->spt, bpb->hds, bpb->hid);
if (bpb->bsec)
- printf(" bsec=%u", bpb->bsec);
+ printf(" bsec=%u", bpb->bsec);
if (!bpb->spf) {
- printf(" bspf=%u rdcl=%u", bpb->bspf, bpb->rdcl);
- printf(" infs=");
- printf(bpb->infs == MAXU16 ? "%#x" : "%u", bpb->infs);
- printf(" bkbs=");
- printf(bpb->bkbs == MAXU16 ? "%#x" : "%u", bpb->bkbs);
+ printf(" bspf=%u rdcl=%u", bpb->bspf, bpb->rdcl);
+ printf(" infs=");
+ printf(bpb->infs == MAXU16 ? "%#x" : "%u", bpb->infs);
+ printf(" bkbs=");
+ printf(bpb->bkbs == MAXU16 ? "%#x" : "%u", bpb->bkbs);
}
printf("\n");
}
@@ -927,21 +905,19 @@
/*
* Check a disk geometry value.
*/
-static u_int
-ckgeom(const char *fname, u_int val, const char *msg)
+static u_int ckgeom(const char *fname, u_int val, const char *msg)
{
if (!val)
- errx(1, "%s: no default %s", fname, msg);
+ errx(1, "%s: no default %s", fname, msg);
if (val > MAXU16)
- errx(1, "%s: illegal %s %d", fname, msg, val);
+ errx(1, "%s: illegal %s %d", fname, msg, val);
return val;
}
/*
* Convert and check a numeric option argument.
*/
-static u_int
-argtou(const char *arg, u_int lo, u_int hi, const char *msg)
+static u_int argtou(const char *arg, u_int lo, u_int hi, const char *msg)
{
char *s;
u_long x;
@@ -949,15 +925,14 @@
errno = 0;
x = strtoul(arg, &s, 0);
if (errno || !*arg || *s || x < lo || x > hi)
- errx(1, "%s: bad %s", arg, msg);
+ errx(1, "%s: bad %s", arg, msg);
return x;
}
/*
* Same for off_t, with optional skmgpP suffix
*/
-static off_t
-argtooff(const char *arg, const char *msg)
+static off_t argtooff(const char *arg, const char *msg)
{
char *s;
off_t x;
@@ -965,40 +940,40 @@
x = strtoll(arg, &s, 0);
/* allow at most one extra char */
if (errno || x < 0 || (s[0] && s[1]) )
- errx(1, "%s: bad %s", arg, msg);
- if (*s) { /* the extra char is the multiplier */
- switch (*s) {
- default:
- errx(1, "%s: bad %s", arg, msg);
- /* notreached */
-
- case 's': /* sector */
- case 'S':
- x <<= 9; /* times 512 */
- break;
+ errx(1, "%s: bad %s", arg, msg);
+ if (*s) { /* the extra char is the multiplier */
+ switch (*s) {
+ default:
+ errx(1, "%s: bad %s", arg, msg);
+ /* notreached */
- case 'k': /* kilobyte */
- case 'K':
- x <<= 10; /* times 1024 */
- break;
+ case 's': /* sector */
+ case 'S':
+ x <<= 9; /* times 512 */
+ break;
- case 'm': /* megabyte */
- case 'M':
- x <<= 20; /* times 1024*1024 */
- break;
+ case 'k': /* kilobyte */
+ case 'K':
+ x <<= 10; /* times 1024 */
+ break;
- case 'g': /* gigabyte */
- case 'G':
- x <<= 30; /* times 1024*1024*1024 */
- break;
+ case 'm': /* megabyte */
+ case 'M':
+ x <<= 20; /* times 1024*1024 */
+ break;
- case 'p': /* partition start */
- case 'P': /* partition start */
- case 'l': /* partition length */
- case 'L': /* partition length */
- errx(1, "%s: not supported yet %s", arg, msg);
- /* notreached */
- }
+ case 'g': /* gigabyte */
+ case 'G':
+ x <<= 30; /* times 1024*1024*1024 */
+ break;
+
+ case 'p': /* partition start */
+ case 'P': /* partition start */
+ case 'l': /* partition length */
+ case 'L': /* partition length */
+ errx(1, "%s: not supported yet %s", arg, msg);
+ /* notreached */
+ }
}
return x;
}
@@ -1006,15 +981,14 @@
/*
* Check a volume label.
*/
-static int
-oklabel(const char *src)
+static int oklabel(const char *src)
{
int c, i;
for (i = 0; i <= 11; i++) {
- c = (u_char)*src++;
- if (c < ' ' + !i || strchr("\"*+,./:;<=>?[\\]|", c))
- break;
+ c = (u_char)*src++;
+ if (c < ' ' + !i || strchr("\"*+,./:;<=>?[\\]|", c))
+ break;
}
return i && !c;
}
@@ -1022,58 +996,55 @@
/*
* Make a volume label.
*/
-static void
-mklabel(u_int8_t *dest, const char *src)
+static void mklabel(u_int8_t *dest, const char *src)
{
int c, i;
for (i = 0; i < 11; i++) {
- c = *src ? toupper(*src++) : ' ';
- *dest++ = !i && c == '\xe5' ? 5 : c;
+ c = *src ? toupper(*src++) : ' ';
+ *dest++ = !i && c == '\xe5' ? 5 : c;
}
}
/*
* Copy string, padding with spaces.
*/
-static void
-setstr(u_int8_t *dest, const char *src, size_t len)
+static void setstr(u_int8_t *dest, const char *src, size_t len)
{
while (len--)
- *dest++ = *src ? *src++ : ' ';
+ *dest++ = *src ? *src++ : ' ';
}
/*
* Print usage message.
*/
-static void
-usage(void)
+static void usage(void)
{
- fprintf(stderr,
- "usage: newfs_msdos [ -options ] special [disktype]\n"
- "where the options are:\n"
- "\t-@ create file system at specified offset\n"
- "\t-B get bootstrap from file\n"
- "\t-C create image file with specified size\n"
- "\t-F FAT type (12, 16, or 32)\n"
- "\t-I volume ID\n"
- "\t-L volume label\n"
- "\t-N don't create file system: just print out parameters\n"
- "\t-O OEM string\n"
- "\t-S bytes/sector\n"
- "\t-a sectors/FAT\n"
- "\t-b block size\n"
- "\t-c sectors/cluster\n"
- "\t-e root directory entries\n"
- "\t-f standard format\n"
- "\t-h drive heads\n"
- "\t-i file system info sector\n"
- "\t-k backup boot sector\n"
- "\t-m media descriptor\n"
- "\t-n number of FATs\n"
- "\t-o hidden sectors\n"
- "\t-r reserved sectors\n"
- "\t-s file system size (sectors)\n"
- "\t-u sectors/track\n");
- exit(1);
+ fprintf(stderr,
+ "usage: newfs_msdos [ -options ] special [disktype]\n"
+ "where the options are:\n"
+ "\t-@ create file system at specified offset\n"
+ "\t-B get bootstrap from file\n"
+ "\t-C create image file with specified size\n"
+ "\t-F FAT type (12, 16, or 32)\n"
+ "\t-I volume ID\n"
+ "\t-L volume label\n"
+ "\t-N don't create file system: just print out parameters\n"
+ "\t-O OEM string\n"
+ "\t-S bytes/sector\n"
+ "\t-a sectors/FAT\n"
+ "\t-b block size\n"
+ "\t-c sectors/cluster\n"
+ "\t-e root directory entries\n"
+ "\t-f standard format\n"
+ "\t-h drive heads\n"
+ "\t-i file system info sector\n"
+ "\t-k backup boot sector\n"
+ "\t-m media descriptor\n"
+ "\t-n number of FATs\n"
+ "\t-o hidden sectors\n"
+ "\t-r reserved sectors\n"
+ "\t-s file system size (sectors)\n"
+ "\t-u sectors/track\n");
+ exit(1);
}