Files
lgcosta 293e6a7280
build / build (clang, ) (push) Failing after 12s
build / build (gcc, ) (push) Failing after 9s
build / build (gcc, --enable-io-failure-emulation) (push) Failing after 8s
build / build (gcc, --enable-warnings) (push) Failing after 6s
Fix real bugs and clean up the build with -Wall -Wextra
Build: add --enable-warnings (-Wall -Wextra); the tree is now warning-free
with it, so distributions can opt in without risking a surprise -Werror
breakage from a future compiler.

Real bugs fixed (each verified by a reproducer):

- lib/io.c: open_rollback_file() read 28 bytes into char[28] with no NUL
  and then strcmp()'d it against a 28-character magic, reading one byte
  past the array. The condition was also inverted, so a *valid* rollback
  file was rejected -- but only sometimes: the missing NUL made the result
  depend on stack garbage (verified: -O0 rejects, -O2 accepts). The whole
  --save-rollback/--rollback-changes path was unreliable. Now the buffer is
  sized for the terminator, zeroed, and the comparison is `!= 0`.
  Verified end to end: save -> reopen -> restore reports "2 blocks
  restored, 0 skipped"; a random file is rejected.

- reiserfscore/reiserfslib.c, reiserfscore/journal.c: asprintf() was
  called with &fs->fs_file_name / &fs->fs_j_file_name, but those fields
  are `char *`, not `char **`. Passing a `char **` where `char *` is
  expected wrote through the wrong pointer -- silent memory corruption on
  any allocation. Fixed by using the new checked helper.

- reiserfscore/node_formats.c: `code < 0` on an unsigned parameter was
  dead code; the guard never fired.

- resize_reiserfs: missing `break` after -j made -j fall into -f, so
  "-j dev" silently also forced the operation. Sign-compare on the
  count_blocks() ternary and on count + blocks.

- lib/misc.c: strncat with bound == strlen(src) (equivalent to strcat) into
  char[256] from a char[256] dirent name -- up to 261 bytes. Replaced with
  snprintf plus an explicit fit check.

- lib/misc.c: die() used vsprintf into a fixed 1024-byte buffer.

- strncpy with bound == destination size (mkreiserfs, tune, progbar) never
  terminated; replaced with snprintf.

Allocator: drop the homegrown magic-header allocator. It wrote "_mem_begin_"
/ "mem_end" through strcpy inside the allocation, kept the size in an
`int`, and its only safety check (checkmem) was never called -- every call
site is commented out. Replaced with a size_t header that is over-aligned
via max_align_t, so malloc alignment guarantees still hold. expandmem()
now takes the old size from the header instead of a caller-supplied value
that could disagree with it.

Warnings: annotate the deliberate fallthroughs (fsck pass cascade, unit
suffix parsing, percentage parsing), fix the remaining sign-compare and
missing-field-initializer sites, and compute addresses of packed members
via char* + offsetof instead of &member.

Portability: asm/types.h -> linux/types.h, malloc.h and sys/vfs.h dropped
from includes.h (nothing used them), sys/vfs.h -> sys/statfs.h for
statfs(2).

Version: reiserfsprogs.spec said 3.6.23 while configure.ac said 3.6.25.

Remove the dead `#if 0` main() from hashes.c.

Add .github/workflows/build.yml: gcc, clang, --enable-warnings and
--enable-io-failure-emulation, each followed by a format/check/inspect
smoke test on a real image.

Verified: ./autogen.sh && ./configure --enable-warnings && make is clean
from scratch (0 warnings, 51 compile/link steps). mkreiserfs, reiserfsck
--check, debugreiserfs -S, reiserfstune -l and a real resize_reiserfs
128M -> 256M all succeed, and fsck reports the resized image clean.
2026-11-11 22:02:38 -03:00

836 lines
21 KiB
C

/* * Copyright 1996-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
/* mkreiserfs is very simple. It skips first 64k of device, and then
writes the super block, the needed amount of bitmap blocks (this
amount is calculated based on file system size), and root block.
Bitmap policy is primitive: it assumes, that device does not have
unreadable blocks, and it occupies first blocks for super, bitmap
and root blocks. bitmap blocks are interleaved across the disk,
mainly to make resizing faster. */
#define _GNU_SOURCE
#ifndef HAVE_CONFIG_H
# include "config.h"
#endif
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
#include "../version.h"
#include <getopt.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/utsname.h>
#if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
# include <uuid/uuid.h>
#endif
static char *program_name;
static void message(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
static void message(const char *fmt, ...)
{
char *buf;
va_list args;
buf = NULL;
va_start(args, fmt);
vasprintf(&buf, fmt, args);
va_end(args);
if (buf) {
fprintf(stderr, "%s: %s\n", program_name, buf);
free(buf);
}
}
static void print_usage_and_exit(void)
{
fprintf(stderr, "Usage: %s [options] "
" device [block-count]\n"
"\n"
"Options:\n\n"
" -b | --block-size N size of file-system block, in bytes\n"
" -j | --journal-device FILE path to separate device to hold journal\n"
" -s | --journal-size N size of the journal in blocks\n"
" -o | --journal-offset N offset of the journal from the start of\n"
" the separate device, in blocks\n"
" -t | --transaction-max-size N maximal size of transaction, in blocks\n"
" -B | --badblocks file store all bad blocks given in file on the fs\n"
" -h | --hash rupasov|tea|r5 hash function to use by default\n"
" -u | --uuid UUID store UUID in the superblock\n"
" -l | --label LABEL store LABEL in the superblock\n"
" --format 3.5|3.6 old 3.5 format or newer 3.6\n"
" -f | --force specified once, make mkreiserfs the whole\n"
" disk, not block device or mounted partition;\n"
" specified twice, do not ask for confirmation\n"
" -q | --quiet quiet work without messages, progress and\n"
" questions. Useful if run in a script. For use\n"
" by end users only.\n"
" -d | --debug print debugging information during mkreiser\n"
" -V print version and exit\n",
program_name);
exit(1);
}
static int Create_default_journal = 1;
static int Block_size = 4096;
/* size of journal + 1 block for journal header */
static unsigned long Journal_size = 0;
static int Max_trans_size = 0; //JOURNAL_TRANS_MAX;
static int Hash = DEFAULT_HASH;
static int Offset = 0;
static char *Format;
static unsigned char UUID[16];
static char *LABEL = NULL;
static char *badblocks_file;
enum mkfs_mode {
DEBUG_MODE = 1 << 0,
QUIET_MODE = 1 << 1,
DO_NOTHING = 1 << 2
};
static int mode;
/* form super block (old one) */
static void make_super_block(reiserfs_filsys_t fs)
{
set_sb_umount_state(fs->fs_ondisk_sb, FS_CLEANLY_UMOUNTED);
set_sb_tree_height(fs->fs_ondisk_sb, 2);
set_sb_hash_code(fs->fs_ondisk_sb, Hash);
if (fs->fs_format == REISERFS_FORMAT_3_6) {
#if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
if (uuid_is_null(UUID))
uuid_generate(UUID);
memcpy(fs->fs_ondisk_sb->s_uuid, UUID, 16);
#endif
if (LABEL != NULL) {
if (strlen(LABEL) > 16)
reiserfs_warning(stderr,
"\nSpecified LABEL is longer then 16 "
"characters, will be truncated\n\n");
/* on-disk label is a fixed 16-byte field; keep it
NUL-terminated for the userspace readers below */
snprintf(fs->fs_ondisk_sb->s_label,
sizeof(fs->fs_ondisk_sb->s_label),
"%s", LABEL);
}
set_sb_v2_flag(fs->fs_ondisk_sb, reiserfs_attrs_cleared);
}
if (!is_reiserfs_jr_magic_string(fs->fs_ondisk_sb) ||
strcmp(fs->fs_file_name, fs->fs_j_file_name))
/* either standard journal (and we leave all new fields to be 0) or
journal is created on separate device so there is no space on data
device which can be used as a journal */
set_sb_reserved_for_journal(fs->fs_ondisk_sb, 0);
else
set_sb_reserved_for_journal(fs->fs_ondisk_sb,
get_jp_journal_size(sb_jp
(fs->
fs_ondisk_sb))
+ 1);
if (fs->fs_badblocks_bm)
set_sb_free_blocks(fs->fs_ondisk_sb,
get_sb_free_blocks(fs->fs_ondisk_sb) -
fs->fs_badblocks_bm->bm_set_bits);
}
/* wipe out first 64 k of a device and both possible reiserfs super block */
static void invalidate_other_formats(int dev)
{
struct buffer_head *bh;
bh = bread(dev, 0, 64 * 1024);
if (!bh) {
reiserfs_exit(1, "Unable to read first blocks of the device");
}
#if defined(__sparc__) || defined(__sparc_v9__)
memset(bh->b_data + 1024, 0, bh->b_size - 1024);
#else
memset(bh->b_data, 0, bh->b_size);
#endif
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh);
bwrite(bh);
brelse(bh);
}
static void zero_journal(reiserfs_filsys_t fs)
{
unsigned long start, len, done;
struct buffer_head *bh;
unsigned int i;
fprintf(stdout, "Initializing journal - ");
start = get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb));
len = get_jp_journal_size(sb_jp(fs->fs_ondisk_sb));
done = 0;
for (i = 0; i < len; i++) {
print_how_far(stdout, &done, len, 1, 1 /*be quiet */ );
bh = getblk(fs->fs_journal_dev, start + i, fs->fs_blocksize);
if (!bh) {
reiserfs_exit(1, "zero_journal: getblk failed");
}
memset(bh->b_data, 0, bh->b_size);
mark_buffer_dirty(bh);
mark_buffer_uptodate(bh, 1);
bwrite(bh);
brelse(bh);
}
fprintf(stdout, "\n");
fflush(stdout);
}
/* this only sets few first bits in bitmap block. Fills not initialized fields
of super block (root block and bitmap block numbers) */
static void make_bitmap(reiserfs_filsys_t fs)
{
struct reiserfs_super_block *sb = fs->fs_ondisk_sb;
unsigned int i;
unsigned long block;
int marked;
marked = 0;
/* mark skipped area and super block */
for (i = 0; i <= fs->fs_super_bh->b_blocknr; i++) {
reiserfs_bitmap_set_bit(fs->fs_bitmap2, i);
marked++;
}
if (fs->fs_badblocks_bm) {
for (i = 0; i < get_sb_block_count(sb); i++) {
if (reiserfs_bitmap_test_bit(fs->fs_badblocks_bm, i)) {
reiserfs_bitmap_set_bit(fs->fs_bitmap2, i);
marked++;
}
}
}
/* mark bitmaps as used */
block = fs->fs_super_bh->b_blocknr + 1;
for (i = 0; i < reiserfs_fs_bmap_nr(fs); i++) {
reiserfs_bitmap_set_bit(fs->fs_bitmap2, block);
marked++;
if (spread_bitmaps(fs))
block = (block / (fs->fs_blocksize * 8) + 1) *
(fs->fs_blocksize * 8);
else
block++;
}
if (!get_size_of_journal_or_reserved_area(fs->fs_ondisk_sb))
/* root block follows directly super block and first bitmap */
block = fs->fs_super_bh->b_blocknr + 1 + 1;
else {
/* makr journal blocks as used */
for (i = 0; i <= get_jp_journal_size(sb_jp(sb)); i++) {
reiserfs_bitmap_set_bit(fs->fs_bitmap2,
i +
get_jp_journal_1st_block(sb_jp
(sb)));
marked++;
}
block = get_jp_journal_1st_block(sb_jp(sb)) + i;
}
/*get correct block - not journal nor bitmap */
while (block_of_journal(fs, block) || block_of_bitmap(fs, block)) {
block++;
}
while ((block < get_sb_block_count(sb)) &&
reiserfs_bitmap_test_bit(fs->fs_bitmap2, block)) {
block++;
}
if (block >= get_sb_block_count(sb))
reiserfs_exit(1, "mkreiserfs: too many bad blocks");
reiserfs_bitmap_set_bit(fs->fs_bitmap2, block);
marked++;
set_sb_root_block(sb, block);
set_sb_free_blocks(sb, get_sb_block_count(sb) - marked);
}
static void set_root_dir_nlink(struct item_head *ih, void *sd)
{
__u32 nlink;
nlink = 3;
set_sd_nlink(ih, sd, &nlink);
}
/* form the root block of the tree (the block head, the item head, the
root directory) */
static void make_root_block(reiserfs_filsys_t fs)
{
struct reiserfs_super_block *sb;
struct buffer_head *bh;
sb = fs->fs_ondisk_sb;
/* get memory for root block */
bh = getblk(fs->fs_dev, get_sb_root_block(sb), get_sb_block_size(sb));
if (!bh) {
reiserfs_exit(1, "getblk failed");
}
mark_buffer_uptodate(bh, 1);
make_empty_leaf(bh);
make_sure_root_dir_exists(fs, set_root_dir_nlink, 0);
brelse(bh);
mark_objectid_used(fs, REISERFS_ROOT_PARENT_OBJECTID);
mark_objectid_used(fs, REISERFS_ROOT_OBJECTID);
}
static void report(reiserfs_filsys_t fs, char *j_filename)
{
// print_block (stdout, fs, fs->fs_super_bh);
struct reiserfs_super_block *sb =
(struct reiserfs_super_block *)(fs->fs_super_bh->b_data);
struct stat st;
dev_t rdev;
if (!is_any_reiserfs_magic_string(sb))
return;
if (fstat(fs->fs_super_bh->b_dev, &st) == -1) {
/*reiserfs_warning (stderr, "fstat failed: %s\n", strerror(errno)); */
rdev = 0;
} else
rdev = st.st_rdev;
if (mode & DEBUG_MODE) {
reiserfs_warning(stdout,
"Block %lu (0x%x) contains super block. ",
fs->fs_super_bh->b_blocknr, rdev);
}
switch (get_reiserfs_format(sb)) {
case REISERFS_FORMAT_3_5:
reiserfs_warning(stdout, " Format 3.5 with ");
break;
case REISERFS_FORMAT_3_6:
reiserfs_warning(stdout, "Format 3.6 with ");
break;
}
if (is_reiserfs_jr_magic_string(sb))
reiserfs_warning(stdout, "non-");
reiserfs_warning(stdout, "standard journal\n");
reiserfs_warning(stdout, "Count of blocks on the device: %u\n",
get_sb_block_count(sb));
reiserfs_warning(stdout, "Number of blocks consumed by mkreiserfs "
"formatting process: %u\n", get_sb_block_count(sb)
- get_sb_free_blocks(sb));
if (mode & DEBUG_MODE)
reiserfs_warning(stdout, "Free blocks: %u\n",
get_sb_free_blocks(sb));
reiserfs_warning(stdout, "Blocksize: %d\n", get_sb_block_size(sb));
reiserfs_warning(stdout, "Hash function used to sort names: %s\n",
code2name(get_sb_hash_code(sb)));
if (mode & DEBUG_MODE) {
reiserfs_warning(stdout, "Number of bitmaps: %u",
get_sb_bmap_nr(sb));
if (get_sb_bmap_nr(sb) != reiserfs_fs_bmap_nr(fs))
reiserfs_warning(stdout, " (really uses %u)",
reiserfs_fs_bmap_nr(fs));
reiserfs_warning(stdout, "\nRoot block: %u\n",
get_sb_root_block(sb));
reiserfs_warning(stdout, "Tree height: %d\n",
get_sb_tree_height(sb));
reiserfs_warning(stdout, "Objectid map size %d, max %d\n",
get_sb_oid_cursize(sb),
get_sb_oid_maxsize(sb));
reiserfs_warning(stdout, "Journal parameters:\n");
print_journal_params(stdout, sb_jp(sb));
} else {
if (j_filename && strcmp(j_filename, fs->fs_file_name))
reiserfs_warning(stdout, "Journal Device [0x%x]\n",
get_jp_journal_dev(sb_jp(sb)));
reiserfs_warning(stdout,
"Journal Size %u blocks (first block %u)\n",
get_jp_journal_size(sb_jp(sb)) + 1,
get_jp_journal_1st_block(sb_jp(sb)));
reiserfs_warning(stdout, "Journal Max transaction length %u\n",
get_jp_journal_max_trans_len(sb_jp(sb)));
}
if (j_filename && strcmp(j_filename, fs->fs_file_name)) {
reiserfs_warning(stdout,
"Space on this device reserved by journal: "
"%u\n", get_sb_reserved_for_journal(sb));
}
if (mode & DEBUG_MODE) {
reiserfs_warning(stdout, "Filesystem state 0x%x\n",
get_sb_fs_state(sb));
reiserfs_warning(stdout, "sb_version %u\n", get_sb_version(sb));
}
if (get_reiserfs_format(sb) == REISERFS_FORMAT_3_6) {
reiserfs_warning(stdout, "inode generation number: %u\n",
get_sb_v2_inode_generation(sb));
reiserfs_warning(stdout, "UUID: %U\n", sb->s_uuid);
if (strcmp(sb->s_label, ""))
reiserfs_warning(stdout, "LABEL: %s\n", sb->s_label);
}
return;
}
static void set_hash_function(char *str)
{
if (!strcmp(str, "tea"))
Hash = TEA_HASH;
else if (!strcmp(str, "rupasov"))
Hash = YURA_HASH;
else if (!strcmp(str, "r5"))
Hash = R5_HASH;
else
message("wrong hash type specified. Using default");
}
static void set_reiserfs_version(char *str)
{
if (!strcmp(str, "3.5"))
Format = "3.5";
else {
Format = "3.6";
if (strcmp(str, "3.6"))
message("wrong reiserfs version specified. "
"Using default 3.6 format");
}
}
static int str2int(char *str)
{
int val;
char *tmp;
val = (int)strtol(str, &tmp, 0);
if (*tmp) {
reiserfs_exit(1,
"%s: strtol is unable to make an integer of %s\n",
program_name, str);
}
return val;
}
static __u64 str2u64(char *str)
{
__u64 val;
char *tmp;
val = (__u64) strtoll(str, &tmp, 0);
if (*tmp) {
reiserfs_exit(1,
"%s: strtoll is unable to make an integer of %s\n",
program_name, str);
}
return val;
}
static void set_block_size(char *str, int *b_size)
{
*b_size = str2int(str);
if (!is_blocksize_correct(*b_size))
reiserfs_exit(1, "%s: wrong blocksize %s specified, "
"only power of 2 from 512-8192 interval "
"are supported", program_name, str);
}
static void set_transaction_max_size(char *str)
{
Max_trans_size = str2int(str);
}
/* reiserfs_create_journal will check this */
static void set_journal_device_size(char *str)
{
Journal_size = str2int(str);
/*
if (Journal_size < JOURNAL_MIN_SIZE)
die ("%s: wrong journal size specified: %lu. Should be at least %u",
program_name,
Journal_size + 1, JOURNAL_MIN_SIZE + 1);
*/
}
/* reiserfs_create_journal will check this */
static void set_offset_in_journal_device(char *str)
{
Offset = str2int(str);
}
static int is_journal_default(char *name, char *jname, int blocksize)
{
if (jname && strcmp(name, jname))
return 0;
if (Journal_size && Journal_size !=
journal_default_size(REISERFS_DISK_OFFSET_IN_BYTES / blocksize,
blocksize) + 1)
/* journal size is set and it is not default size */
return 0;
if (Max_trans_size && Max_trans_size != JOURNAL_TRANS_MAX)
return 0;
return 1;
}
/* if running kernel is 2.2 - mkreiserfs creates 3.5 format, if 2.4 - 3.6,
otherwise - mkreiserfs fails */
static int select_format(void)
{
struct utsname sysinfo;
if (Format) {
if (!strcmp(Format, "3.5"))
return REISERFS_FORMAT_3_5;
if (strcmp(Format, "3.6")) {
message("Unknown fromat %s specified\n", Format);
exit(1);
}
return REISERFS_FORMAT_3_6;
}
reiserfs_warning(stdout, "Guessing about desired format.. ");
if (uname(&sysinfo) == -1) {
message("could not get system info: %s", strerror(errno));
exit(1);
}
reiserfs_warning(stdout, "Kernel %s is running.\n", sysinfo.release);
if (strncmp(sysinfo.release, "2.4", 3) >= 0)
return REISERFS_FORMAT_3_6;
if (strncmp(sysinfo.release, "2.2", 3)) {
message("You should run either 2.2 or 2.4 or higher to be able "
"to create reiserfs filesystem or specify desired format with --format");
exit(1);
}
reiserfs_warning(stdout, "Creating filesystem of format 3.5\n");
return REISERFS_FORMAT_3_5;
}
static int block_size_ok(int blocksize, int force)
{
int pagesize = getpagesize();
if (blocksize > 4096) {
reiserfs_warning(stderr, "Block sizes larger than 4k are not "
"supported on all architectures.\n");
if (blocksize > pagesize)
reiserfs_warning(stderr,
"The newly created filesystem will not "
"be mountable on this system.\n");
else
reiserfs_warning(stderr,
"The newly created filesystem may not "
"be mountable on other systems.\n");
check_forcing_ask_confirmation(force);
} else if (blocksize < 4096) {
reiserfs_warning(stderr, "Block sizes smaller than 4k "
"are not supported.\n");
return 0;
}
return 1;
}
int main(int argc, char **argv)
{
reiserfs_filsys_t fs;
int force = 0;
char *device_name = NULL;
char *jdevice_name = NULL;
__u64 fs_size = 0;
int c;
static int flag;
long error;
program_name = strrchr(argv[0], '/');
if (program_name)
program_name++;
else
program_name = argv[0];
if (argc < 2)
print_usage_and_exit();
memset(UUID, 0, 16);
while (1) {
static struct option options[] = {
{"block-size", required_argument, NULL, 'b'},
{"journal-device", required_argument, NULL, 'j'},
{"journal-size", required_argument, NULL, 's'},
{"transaction-max-size", required_argument, NULL, 't'},
{"journal-offset", required_argument, NULL, 'o'},
{"badblocks", required_argument, NULL, 'B'},
{"hash", required_argument, NULL, 'h'},
{"uuid", required_argument, NULL, 'u'},
{"label", required_argument, NULL, 'l'},
{"format", required_argument, &flag, 1},
{}
};
int option_index;
c = getopt_long(argc, argv, "b:j:s:t:o:h:u:l:VfdB:q",
options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
if (flag) {
Format = optarg;
flag = 0;
}
break;
case 'b': /* --block-size */
set_block_size(optarg, &Block_size);
break;
case 'j': /* --journal-device */
Create_default_journal = 0;
jdevice_name = optarg;
break;
case 's': /* --journal-size */
Create_default_journal = 0;
set_journal_device_size(optarg);
break;
case 't': /* --transaction-max-size */
Create_default_journal = 0;
set_transaction_max_size(optarg);
break;
case 'o': /* --offset */
Create_default_journal = 0;
set_offset_in_journal_device(optarg);
break;
case 'B': /* --badblock-list */
xasprintf(&badblocks_file, "%s", optarg);
break;
case 'h': /* --hash */
set_hash_function(optarg);
break;
case 'v': /* --format */
set_reiserfs_version(optarg);
break;
case 'V':
mode = DO_NOTHING;
break;
case 'f':
force++;
break;
case 'd':
mode |= DEBUG_MODE;
break;
case 'u':
#if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
if (uuid_parse(optarg, UUID) < 0) {
reiserfs_warning(stderr, "Invalid UUID '%s' is "
"specified\n", optarg);
return 1;
}
#else
message("Cannot set up the UUID, uuidlib was not "
"found by configure.\n");
return 1;
#endif
break;
case 'l':
LABEL = optarg;
break;
case 'q':
mode |= QUIET_MODE;
break;
default:
print_usage_and_exit();
}
}
print_banner(program_name);
if (mode & QUIET_MODE)
fclose(stdout);
if (mode == DO_NOTHING)
exit(0);
/* device to be formatted */
device_name = argv[optind];
if (optind == argc - 2) {
/* number of blocks for filesystem is specified */
fs_size = str2u64(argv[optind + 1]);
} else if (optind == argc - 1) {
/* number of blocks is not specified */
if (!(fs_size = count_blocks(device_name, Block_size)))
exit(1);
} else {
print_usage_and_exit();
}
if (fs_size >= UINT_MAX) {
fprintf(stderr,
">>> ReiserFS supports file systems of up to %u "
"blocks.\n>>> The maximum size with a block size of %u bytes "
"is about %Lu MiB.\n>>> This file system would occupy %Lu "
"blocks. ", UINT_MAX, Block_size,
((__u64) UINT_MAX * Block_size) / (1024 * 1024),
fs_size);
if (optind == argc - 1) {
if (!force &&
!user_confirmed(stderr, "Truncate? (y/N): ",
"y\n")) {
fprintf(stderr, "\nExiting.\n\n");
exit(1);
}
fprintf(stderr, "Truncating.\n\n");
fs_size = UINT_MAX;
} else {
fprintf(stderr, "Exiting.\n\n");
exit(1);
}
}
if (is_journal_default(device_name, jdevice_name, Block_size))
Create_default_journal = 1;
if (!(mode & QUIET_MODE) && !can_we_format_it(device_name, force))
return 1;
if (!(mode & QUIET_MODE) && !block_size_ok(Block_size, force))
return 1;
if (jdevice_name)
if (!(mode & QUIET_MODE)
&& !can_we_format_it(jdevice_name, force))
return 1;
fs = reiserfs_create(device_name, select_format(), fs_size, Block_size,
Create_default_journal, 1, &error);
if (!fs) {
reiserfs_warning(stderr, "reiserfs_create failed: %s %ld\n",
error_message(error), error);
return 1;
}
if (!reiserfs_create_journal(fs, jdevice_name, Offset, Journal_size,
Max_trans_size, force)) {
return 1;
}
if (!reiserfs_create_ondisk_bitmap(fs)) {
return 1;
}
/* these fill buffers (super block, first bitmap, root block) with
reiserfs structures */
#if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
if (!uuid_is_null(UUID) && fs->fs_format != REISERFS_FORMAT_3_6) {
reiserfs_warning(stderr,
"UUID can be specified only with 3.6 format\n");
return 1;
}
#endif
if (badblocks_file) {
if (create_badblock_bitmap(fs, badblocks_file))
exit(1);
}
make_super_block(fs);
make_bitmap(fs);
make_root_block(fs);
add_badblock_list(fs, 1);
report(fs, jdevice_name);
if (!force && !(mode & QUIET_MODE)) {
fprintf(stderr, "ATTENTION: YOU SHOULD REBOOT AFTER FDISK!\n"
"\tALL DATA WILL BE LOST ON '%s'", device_name);
if (jdevice_name && strcmp(jdevice_name, device_name))
fprintf(stderr, " AND ON JOURNAL DEVICE '%s'",
jdevice_name);
if (!user_confirmed(stderr, "!\nContinue (y/n):", "y\n"))
return 1;
}
invalidate_other_formats(fs->fs_dev);
zero_journal(fs);
reiserfs_close(fs);
printf("Syncing..");
fflush(stdout);
sync();
printf("ok\n");
if (mode & DEBUG_MODE)
return 0;
printf("ReiserFS is successfully created on %s.\n", device_name);
return 0;
}
/*
* Use BSD fomatting.
* Local variables:
* c-indentation-style: "bsd"
* mode-name: "BSDC"
* c-basic-offset: 4
* tab-width: 4
* End:
*/