C-Python and Endianness

Ganesh Pal ganesh1pal at gmail.com
Sun Mar 26 02:47:40 EDT 2017


Hello Team ,




I want  to write the  hexadecimal string that is passed from python  as  it
is  on disk in C  , my problem is that  the values are getting stored  in
little endian and


the values are  swapped it has been quite a pain for me to fix this , any
suggestion on how to fix this (I am on Python 2.7 and Linux).




Example  :


 if I pass a PyObject  i.e “abcdef12345123”  it should be written on disk
 at the given offset as it  i.e. “abcdef12345123”





CLI:



#inject_failures.py --optype=add --fixcrc=1 --object=baddr
 --baddr=2,3,773463552:512  --offset=16 --mirror=1
 --op_value='abcdef12345123' --size=8



(op_value is the new variable that is passed as string )



static PyObject *

py_corrupt_disk_object(PyObject *self, PyObject *args)

{



        int size, optype, fixcrc;

        long offset;

        PyObject *baddr;

        char *op_value = NULL;



        if (!PyArg_ParseTuple(args,"Oliisi", &baddr, &offset, &size,
&optype,

            &op_value,&fixcrc))

                Py_RETURN_NONE;



        d_locn_t locn = {};

        locn.idx.devid  = ((struct py_ifs_baddr*)baddr)->baddr.devid;

        locn.idx.drive  = ((struct py_ifs_baddr*)baddr)->baddr.drive;

        locn.idx.subidx = ((struct py_ifs_baddr*)baddr)->baddr._subblk;

        locn.idx.index  = ((struct py_ifs_baddr*)baddr)->baddr._block;



        d_print("Printing args in py_corrupt_disk_object: \n");

        d_print("offset %lu \n",offset);

        d_print("fixcrc %d \n",fixcrc);

        d_print("size %d \n",size);

        d_print("optype %d \n",optype);

        d_print("op_value %s \n",op_value);





        d_cpr_write(&locn, offset, size, optype, op_value, fixcrc);

        Py_RETURN_NONE;

}





PyObject*

d_cpr_write(d_locn_t *locn, int offset, int size, int optype, char
*op_value, int fixcrc)

{



        cpr_obj* obj = NULL;

        struct po_typeinfo *tinfo = NULL;

        int obj_size = 0;

        d_print("The Values inside d_cpr_write():\n");

        d_print("offset %d \n",offset);

        d_print("fixcrc %d \n",fixcrc);

        d_print("size %d \n",size);

        d_print("optype %d \n",optype);

        d_print("op_value %s \n",op_value);





        if (locn->idx.subidx & BADDR_SIZE_512) {

                obj_size = BUFFER_512;

                tinfo = find_object('i');

                if (locn_iaddr_to_linsnap(locn) != d_OK) {

                        d_log(d_ERR, "lin snap conversion failed\n");

                        Py_RETURN_NONE;

                }

                locn->flags |= DLFLAG_HASXIADDRHINT;

                locn->xiaddrhint = d_index_to_baddr(locn->idx);

        } else {

                obj_size = BUFFER_8192;

                tinfo = find_object('b');

        }



        if (tinfo == NULL) {

                d_log(d_ERR, "Only Object i or b supported\n");

                Py_RETURN_NONE;

        }



        obj = alloc_objarg();



        // create cpr object

        obj->tinfo = tinfo;

        obj->locn = *locn;



        unsigned char *buff = NULL;

        if (!(buff = alloca(obj_size))) {

                d_log(d_ERR, "buffer allocation failed\n");

                Py_RETURN_NONE;

        }



        int index, xfered, bit_offset;



        if ((xfered = (*obj->tinfo->read)(&obj->locn, buff, obj_size)) < 0)
{

                d_log(d_ERR, "read failed %d\n", xfered);

                Py_RETURN_NONE;

        }



        if (obj->tinfo->insane != NULL) {

                if ((*obj->tinfo->insane)(&obj->locn, buff, obj_size, 0) <
0) {

                        d_log(d_ERR, "%c object sanity check failed\n",

                            obj->tinfo->type);

                        Py_RETURN_NONE;

                }

        }



       d_print("Entering optype\n");

        if (optype == 2) { //overwrite

                unsigned long opval = strtol(op_value, NULL, 16);

                d_print("after rev =%ld ", opval);

                memcpy(&buff[offset], &opval, sizeof(opval));



         }//End of overwrite

        if (fixcrc)

                obj->locn.flags |= DLFLAG_WRITE_CRC;



        if (!obj->tinfo->write) {

                d_log(d_ERR, "no write function supported\n");

                Py_RETURN_NONE;

        }



        if ((xfered = (*obj->tinfo->write)(&obj->locn, buff, obj_size)) <
0) {

                d_log(d_ERR, "write failed %d\n", xfered);

                Py_RETURN_NONE;

        }



        Py_RETURN_NONE;

}





Output:



pipe1-2# inject_failures.py --optype=add --fixcrc=1 --object=baddr
 --baddr=2,3,773463552:512  --offset=16 --mirror=1
 --op_value='abcdef12345123' --size=8

> /usr/local_qa/bin/isi_corrupt.py(848)main()

-> if 'add' in options.optype and options.op_value is None:

(Pdb) c

c

> /usr/local_qa/bin/ inject_failures.py (185)corrupt_diskobject()

-> logging.info("Corrupting disk object %s at %s", obj_type, disk_object)

(Pdb) c

Printing args in py_corrupt_disk_object:

offset 16

fixcrc 1

size 8

optype 2

op_value abcdef12345123

The Values inside d_cpr_write():

offset 16

fixcrc 1

size 8

optype 2

op_value abcdef12345123

Entering optype

after rev =48358647703818531



If I do an hexdump on the file  I can see that data is not written correctly



Before:

00000010  e0 01 04 00 01 00 00 00  02 00 00 00 00 00 00 00
 |................|

After :

00000010  23 51 34 12 ef cd ab 00  02 00 00 00 00 00 00 00
 |#Q4.............|  ==>





1.  I am on a little endian machine  and is there a way that I can  stop
this  translation  and write the values as it  ( looks like we are swapping
the  bytes )?


2.  The value passed i.e op_value is a string and its getting printed
correctly at C layer,my value is always a hex decimal string of size 14  or
7 bytes.



3. Is there something that I can take care in python layer to avoid this
swap ?



Regards,


Ganesh


More information about the Python-list mailing list