28

You can use

dd if=/dev/zero of=file count=1024 bs=1024 

to zero fill a file.

Instead of that I want to one fill a file. How do I do that?

There is no /dev/one file, so how can I simulate that effect via on bash shell?

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208

6 Answers6

41
tr '\0' '\377' < /dev/zero | dd bs=64K of=/dev/sdx

This should be much faster. Choose your blocksizes (or add counts) like you need at. Writing ones to a SSD-Disk till full with a blocksize of 99M gave me 350M/s write performance.

monkeybus
  • 543
  • 1
  • 4
  • 5
  • 1
    I confirm this is at least twice as fast as the accepted solution. However I didn't notice any noticeable performance improvement from varying the blocksize (though there is a huge decrease of performance without the bs argument). – Skippy le Grand Gourou Oct 29 '13 at 17:40
  • 1
    Thanks. I successfully used this modified command to one-fills my 2GB micro SD: `tr '\0' '\377' < /dev/zero | pv | sudo dd bs=512K of=/dev/sdx` with speed ~8MB/s. The command `pv` shows you how many bytes are done, and the speed. You may need to install it, but it's very useful. – Johnny Wong Sep 18 '21 at 01:07
  • @JohnnyWong: Adding `status=progress` to the arguments of `dd` gives a throughput measure output directly by `dd`. – Golar Ramblar Jan 10 '23 at 11:51
  • Note that `tr` conversions depend on the locale — `\377` may not be all `1` bits, for example on Mac with the `en_US.UTF-8` locale, this encodes `bfc3 bfc3 bfc3…`. To get all ones consistently, you could set: `env LC_ALL=C tr '\000' '\377'` – semenko Jan 17 '23 at 15:58
21

Try this:

dd if=<(yes $'\01' | tr -d "\n") of=file count=1024 bs=1024

Substitute $'\377' or $'\xFF' if you want all the bits to be ones.

MacOS tr may complain about "Illegal byte sequence". Setting LC_CTYPE=C will prevent that. This version can also be used in Linux:

dd if=<(yes $'\01' | LC_CTYPE=C tr -d "\n") of=file count=1024 bs=1024
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • 3
    For others: on macOS you will need to set environment variable LANG="C" to get `tr` to behave in the way that makes this command work – Matt Sephton Jul 23 '18 at 22:07
  • @MattSephton: I just tested it on MacOS Sierra and it works fine for me without changing `LANG` (mine is en_US.UTF-8). – Dennis Williamson Jul 23 '18 at 23:08
  • Interesting. I was changing \00 to \xFF and was getting something other than \xFF until I used LANG="C" – Matt Sephton Jul 24 '18 at 00:28
  • 1
    @MattSephton: Anything `\x80` or above. Evidently it doesn't like the 8th bit set unless `LANG=C`. For those that might not be aware, you can do that for just the environment of `tr`: `dd if=<(yes $'\xFF' | LANG=C tr -d "\n") of=file count=1024 bs=1024` and it doesn't affect the general environment. – Dennis Williamson Jul 24 '18 at 02:08
  • This gives me an error of: `dd: failed to open '/dev/fd/63': No such file or directory` – Chris Stryczynski Feb 25 '19 at 21:05
  • 1
    @ChrisStryczynski: Did you run it using `sudo`? That's one possible reason for that error. If so, then this is one way to make it work: `sudo bash -c 'dd if=<(yes $'\01' | tr -d "\n") of=file count=1024 bs=1024'` – Dennis Williamson Feb 25 '19 at 22:43
  • @DennisWilliamson yes was using sudo. The `bash -c ...` works however! – Chris Stryczynski Feb 26 '19 at 08:42
  • @ChrisStryczynski: The process substitution creates a file descriptor which `sudo` then closes making it unavailable. Wrapping the whole thing in `bash -c` delays the creation of the file descriptor until after `sudo` starts. – Dennis Williamson Feb 26 '19 at 14:22
  • `$'\xFF'` gave me `0x78`-bytes. `$'\377'` gave me correctly `0xFF`-bytes. – Golar Ramblar Jan 10 '23 at 11:51
  • @GolarRamblar: `0x78` is "x" (lowercase x) so perhaps you omitted the backslash. – Dennis Williamson Jan 10 '23 at 13:21
5

Well, you could do this:

dd if=/dev/zero count=1024 bs=1024 |
  tr '\000' '\001' > file
larsks
  • 277,717
  • 41
  • 399
  • 399
  • One fill would be '\377', no? – Neil Jun 05 '12 at 21:24
  • 1
    Hmm, I guess it depends on what you want. This will fill a file with bytes of value `1` (`01 01 01 01 ...`). Using `\377` gets you all *bits* set to 1 (so `FF FF FF FF ...`). Depends on the OP's requirements. – larsks Jun 05 '12 at 21:33
1
pv /dev/zero |tr \\000 \\377 >targetfile

...where \377 is the octal representation of 255 (a byte with all bits set to one). Why tr only works with octal numbers, I don't know -- but be careful not to subconsciously translate this to 3FF.


The syntax for using tr is error prone. I recommend verifying that it is making the desired translation...

cat /dev/zero |tr \\000 \\377 |hexdump -C

Note: pv is a nice utility that replaces cat and adds a progress/rate display.

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
1

I created a device driver in my github. Installing it creates a file /dev/one that is writing only bits set to 1.

The c file called one.c (the only interesting part is in device_file_read):

// File Driver to create a devince /dev/one like the /dev/zero

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

MODULE_LICENSE("GPL");

static int device_file_major_number = 0;
static const char device_name[] = "one";

static ssize_t device_file_read(
        struct file *file_ptr,
        char __user *user_buffer,
        size_t count,
        loff_t *position) {
    printk( KERN_NOTICE "One: Device file is read at offset = %i, read bytes count = %u\n" , (int)*position , (unsigned int)count );

    // Allocate Kernel buffer
    char* ptr = (char*) vmalloc(count);

    // Fill it with one, byte per byte
    // -- Note that byte is the smallest accesible data unit
    memset(ptr, 0xFF, count);

    char res = copy_to_user(user_buffer, ptr, count);
    if (res != 0){ return -EFAULT; }

    // Return number of byte read
    return count;
}

static struct file_operations simple_driver_fops = {
    .owner   = THIS_MODULE,
    .read    = device_file_read,
};

int register_device(void) {
    int res = 0;
    printk( KERN_NOTICE "One: register_device() is called.\n" );
    res = register_chrdev( 0, device_name, &simple_driver_fops );
    if( res < 0 ) {
        printk( KERN_WARNING "One:  can\'t register character device with error code = %i\n", res );
        return res;
    }
    device_file_major_number = res;
    printk( KERN_NOTICE "One: registered character device with major number = %i and minor numbers 0...255\n", device_file_major_number );
    return 0;
}

void unregister_device(void) {
    printk( KERN_NOTICE "One: unregister_device() is called\n" );
    if(device_file_major_number != 0) {
        unregister_chrdev(device_file_major_number, device_name);
    }
}

static int my_init(void) {
    register_device();
    return 0;
}

static void my_exit(void) {
    unregister_device();
    return;
}

// Declare register and unregister command
module_init(my_init);
module_exit(my_exit);

The Makefile

TARGET_MODULE:=one

BUILDSYSTEM_DIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
obj-m := $(TARGET_MODULE).o
# See: https://stackoverflow.com/questions/15910064/how-to-compile-a-linux-kernel-module-using-std-gnu99
ccflags-y := -std=gnu99 -Wno-declaration-after-statement

build:
    # run kernel build system to make module
    $(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules

clean:
    # run kernel build system to cleanup in current directory
    $(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean
    rm -f MOK.priv MOK*.der

key:
    echo "Creating key"
    openssl req -new -x509 -newkey rsa:2048 -days 36500 -keyout MOK.priv -outform DER -out MOK.der -nodes -subj "/CN=TinmarinoUnsafe/"
    #
    echo "\e[31;1mPlease enter a password you will be asked for on reboot:\e[0m"
    mokutil --import MOK.der
    echo "\e[31;1mNow you must: 1/ reboot, 2/ Select Unroll MOK, 3/ Enter password you previously gave\e[0m"

sign:
    cp one.ko one.ko.bck
    /usr/src/linux-headers-$(shell uname -r)/scripts/sign-file sha256 MOK.priv MOK.der one.ko

load:
    insmod ./$(TARGET_MODULE).ko

unload:
    rmmod ./$(TARGET_MODULE).ko

create:
    mknod /dev/one c $(shell cat /proc/devices | grep one$ | cut -d ' ' -f1) 0

delete:
    rm /dev/one

test:
    [ "$(shell xxd -p -l 10 /dev/one)" = "ffffffffffffffffffff" ] \
        && echo "\e[32mSUCCESS\e[0m" \
        || echo "\e[31mFAILED\e[0m"

The instalation is long (3min) due to the driver signature enforcement. Froget this part if you disabled it in your UEFI.

  1. git clone https://github.com/tinmarino/dev_one.git DevOne && cd DevOne # Download
  2. make build # Compile
  3. make key # Generate key for signing
  4. sudo make sign # Sign driver module to permit MOK enforcement (security)
  5. sudo reboot now # Reboot and enable Mok
    1. A blue screen (MOK manager) will appear
    2. Choose "Enroll MOK"
    3. Choose "Continue"
    4. Choose "Yes" (when asked "Enroll the key")
    5. Enter the password you gave at make sign
    6. Choose "Reboot" (again)
  6. sudo make load # Load
  7. sudo make device # Create /dev/one
  8. make test # Test if all is ok
Tinmarino
  • 3,693
  • 24
  • 33
1

You can simulate a /dev/one without a special device, with a FIFO + yes:

mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock count=1024 bs=1024 status=progress & yes "" | tr '\n' '\1' > ddfifo

tee may be used to double the throughput:

mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock count=1024 bs=1024 status=progress & yes "" | tr '\n' '\1' | tee ddfifo > ddfifo

If you'd like bytes with all bits set to one, swap '\1' for '\377'.