How do I get an equivalent of /dev/one in Linux

19,414

Solution 1

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.

Solution 2

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.

Solution 3

Well, you could do this:

dd if=/dev/zero count=1024 bs=1024 |
  tr '\000' '\001' > file

Solution 4

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.

Solution 5

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
Share:
19,414

Related videos on Youtube

Ankur Agarwal
Author by

Ankur Agarwal

Updated on July 11, 2022

Comments

  • Ankur Agarwal
    Ankur Agarwal almost 2 years

    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?

    • נשמה קשוחה
      נשמה קשוחה about 12 years
      Write a C program to do it, should be trivial.
  • Neil
    Neil about 12 years
    One fill would be '\377', no?
  • larsks
    larsks about 12 years
    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.
  • Skippy le Grand Gourou
    Skippy le Grand Gourou over 10 years
    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).
  • Brent Bradburn
    Brent Bradburn over 7 years
    Note: If you are trying to fill an entire device, it's probably better to avoid dd since that will slow things down (by a lot) if you don't manually select an optimum bs value.
  • Brent Bradburn
    Brent Bradburn over 7 years
    pv will also give an estimate of time remaining if it has enough information to do so.
  • Brent Bradburn
    Brent Bradburn over 7 years
    While you're at it, maybe prefix with time and nice.
  • Matt Sephton
    Matt Sephton almost 6 years
    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
  • SourceSeeker
    SourceSeeker almost 6 years
    @MattSephton: I just tested it on MacOS Sierra and it works fine for me without changing LANG (mine is en_US.UTF-8).
  • Matt Sephton
    Matt Sephton almost 6 years
    Interesting. I was changing \00 to \xFF and was getting something other than \xFF until I used LANG="C"
  • SourceSeeker
    SourceSeeker almost 6 years
    @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.
  • Chris Stryczynski
    Chris Stryczynski over 5 years
    This gives me an error of: dd: failed to open '/dev/fd/63': No such file or directory
  • SourceSeeker
    SourceSeeker over 5 years
    @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'
  • Chris Stryczynski
    Chris Stryczynski over 5 years
    @DennisWilliamson yes was using sudo. The bash -c ... works however!
  • SourceSeeker
    SourceSeeker over 5 years
    @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.
  • Johnny Wong
    Johnny Wong almost 3 years
    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.