How to perform bitwise operations on files in linux?

Viewed 5168

I wanna do some bitwise operations (for example xor two files) on files in Linux , and I have no idea how I can do that. Is there any command for that or not?

any help will be appreciated.

4 Answers

Thanks to "phihag", this code is for doing binary operations on 2 files.
Ex.1: You have two files and want to compare those two, so you do a binary XOR on those.
Ex.2: You have downloaded a file with jdownloader or sth similar and you have moved the unfinished download to another folder and then the download manager continues unfinished parts and create another file. So you have two seprate files which can completes each other. Now if you do a binary OR on these two files you have a complete file.

WARNING: The larger file will be overwritten with the the operation result.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>

int main(int argc, char* argv[])
{
    int FP1 = 0, FP2 = 0;
    struct stat St1, St2;
    char *File1 = NULL, *File2 = NULL;
    int Rn = 0;

    if (argc != 4)
    {
        printf("Usage: %s File1 File2 Operator\n", argv[0]);
        exit(1);
    }

    //Opening and mapping File1
    FP1 = open(argv[1], O_RDWR);
    if (FP1 == -1)
    {
        perror("Error opening file1 for writing");
        exit(2);
    }

    if (fstat(FP1, &St1) == -1)
    {
        perror("Can't determine file1 size");
        exit(3);
    }

    File1 = (char*) mmap(NULL, St1.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, FP1, 0);
    if (File1 == MAP_FAILED)
    {
        perror("Can't map file1");
        exit(4);
    }
    //======================

    //Opening and mapping File2
    FP2 = open(argv[2], O_RDWR);
    if (FP2 == -1)
    {
        perror("Error opening file2 for writing");
        exit(2);
    }

    if (fstat(FP2, &St2) == -1)
    {
        perror("Can't determine file2 size");
        exit(3);
    }

    File2 = (char*) mmap(NULL, St2.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, FP2, 0);
    if (File2 == MAP_FAILED)
    {
        perror("Can't map file2");
        exit(4);
    }
    //======================

    //Binary operations
    ssize_t i = 0;
    switch (*(argv[3]))
    {
        case '|':
            if (St1.st_size <= St2.st_size)
                for (i = 0; i < St1.st_size; i ++)
                    File2[i] = File1[i] | File2[i];
            else
                for (i = 0; i < St2.st_size; i ++)
                    File1[i] = File1[i] | File2[i];
            break;
        case '&':
            if (St1.st_size <= St2.st_size)
                for (i = 0; i < St1.st_size; i ++)
                    File2[i] = File1[i] & File2[i];
            else
                for (i = 0; i < St2.st_size; i ++)
                    File1[i] = File1[i] & File2[i];
            break;
        case '^':
            if (St1.st_size <= St2.st_size)
                for (i = 0; i < St1.st_size; i ++)
                    File2[i] = File1[i] ^ File2[i];
            else
                for (i = 0; i < St2.st_size; i ++)
                    File1[i] = File1[i] ^ File2[i];
            break;
        default:
            perror("Unknown binary operator");
            exit(5);
    }
    //======================

    munmap(File1, St1.st_size);
    munmap(File2, St2.st_size);
    close(FP1);
    close(FP2);

    //Renaming the changed file and make output
    char Buffer[1024];
    if (St1.st_size <= St2.st_size)
    {
        Rn = system(strcat(strcat(strcat(strcat(strcpy(Buffer, "mv \""), argv[2]), "\" \""), argv[2]),"-Mapped\""));
        if (Rn == -1)
        {
            perror("Unable to rename the new file.");
            exit(6);
        }
        else
            printf("%s is mapped.\n", argv[2]);
    }
    else
    {
        Rn = system(strcat(strcat(strcat(strcat(strcpy(Buffer, "mv \""), argv[1]), "\" \""), argv[1]),"-Mapped\""));
        if (Rn == -1)
        {
            perror("Unable to rename the new file.");
            exit(6);
        }
        else
            printf("%s is mapped.\n", argv[1]);
    }
    //======================

    return 0;
}

For those who prefer a Python script:

#!/usr/bin/env python3

import binascii
import sys

blocksize = 4096

input1 = open(sys.argv[1], 'rb')
input2 = open(sys.argv[2], 'rb')
output = open(sys.argv[3], 'wb')

while True:
    block1 = input1.read(blocksize)
    block2 = input2.read(blocksize)
    if not block1 and not block2:
        break  # reached EOF in both files
    if len(block1) != len(block2):
        sys.stderr.write('Premature EOF, truncating to shorter file\n')
        block1 = block1[:min(len(block1), len(block2))]
        block2 = block2[:min(len(block1), len(block2))]
    # convert to large integer
    int1 = int(binascii.hexlify(block1), 16)
    int2 = int(binascii.hexlify(block2), 16)
    # apply logical operator: xor
    int_o = int1 ^ int2
    # covert back to binary
    hexformat = '%%0%dx' %(2*len(block1))  # e.g. '%0512x' for 256 bytes
    block_o = binascii.unhexlify(hexformat %int_o)
    output.write(block_o)

output.close()
input1.close()
input2.close()

With files of different lengths, it warns and stops. In some applications, it may be preferable to pad the shorter input with zero bytes or to wrap back to the start of the input file. This can be achieved on the command line by concatenating the shorter file with itself or output from /dev/zero.

Related