How to generate an image using C code - c

The function below simply serves html when it is called, however
void generateHTML (int socket) {
char* message;
// Sends HTTP response header
message = "HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n";
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
message = "<HTML><BODY><P>Hello World.</P></BODY></HTML>\n";
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
}
My output on the web browser would by a simple Hello World message. However, I want to change it so that it will display a bitmap image instead. Let's use a 1x1 red pixel as our bmp.
I've modified this function so far by:
void generateHTML (int socket) {
char* message;
// Sends HTTP response header
message = "HTTP/1.0 200 OK\r\n"
"Content-Type: image/bmp\r\n"
"Content-Length: ???WTF???\r\n";
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
message = "BMF8\n";
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
message = " "; //bmp file data goes here.
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
}
Quoting from Dan's answer, the data in hex looks like:
0000000: 424d 3a00 0000 0000 0000 3600 0000 2800 BM:.......6...(.
0000010: 0000 0100 0000 0100 0000 0100 1800 0000 ................
0000020: 0000 0400 0000 130b 0000 130b 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 ..........
However, I simply cannot place that inside the quotation marks. How would I do this?

this is an xxd dump of a 1x1 black windows bmp image:
0000000: 424d 3a00 0000 0000 0000 3600 0000 2800 BM:.......6...(.
0000010: 0000 0100 0000 0100 0000 0100 1800 0000 ................
0000020: 0000 0400 0000 130b 0000 130b 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 ..........

expanding on what #Dan D. said, you can use ImageMagick's "convert" command on a Linux (or possibly Windows also) box to convert raw data to an image. I tested with .png, you'll have to test the output on Windows yourself:
jcomeau#intrepid:~$ echo -en "\0000" | convert -size 1x1 -depth 8 gray:- /tmp/1black.bmp
jcomeau#intrepid:~$ xxd /tmp/1black.bmp
0000000: 424d 3a00 0000 0000 0000 3600 0000 2800 BM:.......6...(.
0000010: 0000 0100 0000 0100 0000 0100 1800 0000 ................
0000020: 0000 0400 0000 120b 0000 120b 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 ..........

To print it out you need to create an array
e.g. unsigned char bmp[] ={
and fill this part here with hexadecimal above. However because it is in hexadecimal you need to add 0x to the front of each pair of numbers.
E.g.
0x42, 0x4d
Etc.
This can just be included in the {} brackets.
E.g.
unsigned char bmp[] ={
0x42, 0x4d, 0x....
}
then just send this through the socket using the write function.
write (socket, bmp, sizeof(bmp));

Related

How to ensure writing 4 bytes to binary file

I want to program an EEPROM which is 16/32 bit. I am writing the file from a C program, but fwrite() seems to be doing only 8 bits? I wrote a simple example, and using xxd (and hexdump) to look at the results, but the file seems to be only 8 bits. I wonder if I'm only seeing 8 bits due to the limitations of hexdump & xxd, or if the problem is with fwrite()?
Anyone know how I can check that all the bits are being written to the file?
#include <stdio.h>
#include <stdlib.h>
const unsigned int dataSize = 255;
unsigned long tmp[] = { 0xFFFF, 0xFFDD, 0xFDDD, 0xF000, 0x0F0F, 0x0001, 0x1010 };
int main() {
const char *path = "text.bin";
FILE *fp = fopen(path, "wb");
const void *data = tmp;
if (!fp) {
fprintf(stderr, "fopen() failed for '%s'\n", path);
} else {
fwrite(data, 1, dataSize, fp);
}
return 0;
}
Using xxd I see:
00000000: ffff 0000 0000 0000 ddff 0000 0000 0000 ................
00000010: ddfd 0000 0000 0000 00f0 0000 0000 0000 ................
00000020: 0f0f 0000 0000 0000 0100 0000 0000 0000 ................
00000030: 1010 0000 0000 0000 0000 0000 0000 0000 ................
00000040: c005 5182 b27f 0000 0000 0000 0000 0000 ..Q.............
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000f0: 0000 0000 0000 0000 0000 0000 0000 00 ...............
EDIT:
I'm trying to ensure there are 32 bits written to the file. The results of xxd are:
00000000: 11111111 11111111 00000000 00000000 00000000 00000000 ......
Which show there are 16 bits for the 0xFFFF but where are the other 16 bits? Ideally I'd like to see 16 zeros followed by 16 ones for 0xFFFF for a 32 bit boundary.
I'm wondering if this is a problem with the xxd software not displaying it, rather than C not writing it.
(I realise the names and the file pointer isn't closed, it was just something I knocked up in 2 minutes to help display the problem, I picked 255 out of the air.)
To control the exact output in the file, you should use the exact width types from <stdint.h> instead of unsigned long, which seems to have 64 bits on your system.
The reason you do not see 16 zeroes followed by 16 ones is your target system uses little-endian representation for integer types larger than 8 bits. Endianness determines the order of bytes in memory for these types.
Furthermore, you should not write 255 bytes from the tmp array which has a size of 28 bytes.
Here is a modified version:
#include <stdio.h>
#include <stdint.h>
// data has 256 bytes
uint32_t data[64] = { 0xFFFF, 0xFFDD, 0xFDDD, 0xF000, 0x0F0F, 0x0001, 0x1010 };
int main() {
const char *path = "text.bin";
FILE *fp = fopen(path, "wb");
if (!fp) {
fprintf(stderr, "fopen() failed for '%s'\n", path);
} else {
size_t written = fwrite(data, 1, sizeof data, fp);
if (written != sizeof data) {
fprintf(stderr, "fwrite() only wrote %zu bytes\n", written);
}
fclose(fp);
}
return 0;
}
Problem: 16 bit data (2 byte) chunks are stored in 64-bit-type (8 byte) array. This explains the output.
Solution:
Assign x byte data to "x-byte type" (use "Fixed-Width Integer Types")
fwrite the exact number of bytes (do not guess)
Please note that 0xFFFF is 2 bytes. Assigned data is 7 * 2 = 14 bytes. "tmp" array is 7 * 8 = 56 bytes.

Ethernet type 0x0101 not working with raw socket

I tried to send a raw packet with ethernet type 0x0101 but it seems not to be working, if I use ethernet type 0x1000 it is working properly.
Basically I open a raw socket:
int sd = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(0x0101));
int r = sendmsg(sd, msgSend, 0);
accordingly with iana ethernet type 0101-01FF are experimental, so to my understating can be used for experiments.
If I use 0x0101 tcpdump shows:
00:00:01.001914 aa:00:00:2e:00:02 > 08:00:27:0b:ed:84, 802.3, length 257: LLC, dsap Null (0x00) Individual, ssap Null (0x00) Command, ctrl 0x0000: Information, send s0
0x0000: 0000 0000 efbe adde aaaa db00 0000 0000 ................
0x0010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0030: 0000
while when I use 0x1000 is shows:
00:00:00.439876 aa:00:00:2e:00:02 > 08:00:27:0b:ed:84, ethertype Trail (0x1000), length 64:
0x0000: 0000 0000 efbe adde aaaa db00 0000 0000 ................
0x0010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0030: 0000
What am I missing?
Tcpdump interprets the value 0x0101 in this position as Ethernet Frame Length.
Values smaller than 0x600 (1536 decimal) are assumed to be the frame length (parsed as Frametype IEEE 802.2 LLC) instead of the next protocol id (parsed as Frametype Ethernet II).
Here you see, that tcpdump indeed interprets 0x101 (257 decimal) as the length:
00:00:01.001914 aa:00:00:2e:00:02 > 08:00:27:0b:ed:84, 802.3, length 257: LLC, dsap Null (0x00) Individual, ssap Null (0x00) Command, ctrl 0x0000: Information, send s0
But your frame should be correctly on-wire as you intended it.

Working with HEX in C. [Stuck]

According to http://wiki.osdev.org/FAT I'm trying to get the total FAT size. But the result is riddiculus.
What am I doing wrong?
Any help is appreciated! Thank you.
int main(int argc, char *argv[]){
if(argc == 1){
printf("Root directory:\n");
} else {
char *file_name = argv[1];
printf("Checking %s...\n", file_name);
FILE *file = fopen(file_name, "r");
if (file==NULL) {fputs ("File error\n",stderr); exit (1);}
unsigned char boot[512];
fread(boot, 512, 1, file);
// Sectors per FAT. The size of the FAT in sectors.
unsigned int sectors_per_fat = (boot[39]<<24)|(boot[38]<<16)|(boot[37]<<8)|boot[36];
unsigned int fat_count = boot[16];
unsigned int bytes_per_block = (boot[12]<<8)|boot[11];
unsigned int total_fat_size = sectors_per_fat*fat_count*bytes_per_block;
printf("%d\n", total_fat_size);
/*
36-4 Sectors per FAT
16-1 Number of File Allocation Tables.
11-2 Number of bytes per block (almost always 512).
*/
fclose(file);
}
return 0;
}
the file:
0000000: eb58 906d 6b66 732e 6661 7400 0201 2000 .X.mkfs.fat... .
0000010: 0200 0000 00f8 0000 2000 4000 0000 0000 ........ .#.....
0000020: 400d 0300 0306 0000 0000 0000 0200 0000 #...............
0000030: 0100 0600 0000 0000 0000 0000 0000 0000 ................
0000040: 8000 29c8 a726 5e4e 4f20 4e41 4d45 2020 ..)..&^NO NAME
0000050: 2020 4641 5433 3220 2020 0e1f be77 7cac FAT32 ...w|.
0000060: 22c0 740b 56b4 0ebb 0700 cd10 5eeb f032 ".t.V.......^..2
0000070: e4cd 16cd 19eb fe54 6869 7320 6973 206e .......This is n
0000080: 6f74 2061 2062 6f6f 7461 626c 6520 6469 ot a bootable di
0000090: 736b 2e20 2050 6c65 6173 6520 696e 7365 sk. Please inse
00000a0: 7274 2061 2062 6f6f 7461 626c 6520 666c rt a bootable fl
00000b0: 6f70 7079 2061 6e64 0d0a 7072 6573 7320 oppy and..press
00000c0: 616e 7920 6b65 7920 746f 2074 7279 2061 any key to try a
00000d0: 6761 696e 202e 2e2e 200d 0a00 0000 0000 gain ... .......
00000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000130: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000140: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000160: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000170: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000180: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000190: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
0000200: 5252 6141 0000 0000 0000 0000 0000 0000 RRaA............
0000210: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000220: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000230: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000240: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000250: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................
....
I used these to create the file:
dd if=/dev/zero of=disk.img bs=1k count=100000
losetup /dev/loop0 disk.img
mkdosfs -s 1 -F 32 /dev/loop0 100000

how to write the members of structure to a file?

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
typedef struct {
char name[124];
int age;
int class;
} student;
main( ) {
student s1;
int fd = -1;
int fh = creat( "student.db", O_CREAT | S_IRUSR | S_IWUSR );
fd = open( "student.db", O_RDWR | O_APPEND );
if ( fd<0 ) {
perror( "failed to create student file:" );
return;
}
s1.age = 15;
s1.class = 9;
strcpy( s1.name, "John" );
int ret = write( fd, &s1, sizeof( student ) );
printf( "ret of write: %d \n", ret );
system( "gvim student.db" );
}
I am trying to write a record to a file. Since structure contains integer elements only name is written successfully, whereas the int elements are displayed as garbage. Could anyone please have a look at the code. Any help would be appreciated.
Using a command like od -x you can get a hex dump of file contents useful for debugging.
You'ld make it easier for yourself if you reorder the structure members, so the integers are first.
An example, showing a file with count of 64bit fibonacci sequence from 0.. :
ladm#ash:~/src/fib/fibs_tab> od -x < fib_uint64| head
0000000 005e 0000 0000 0000 0000 0000 0000 0000
0000020 0001 0000 0000 0000 0001 0000 0000 0000
0000040 0002 0000 0000 0000 0003 0000 0000 0000
0000060 0005 0000 0000 0000 0008 0000 0000 0000
0000100 000d 0000 0000 0000 0015 0000 0000 0000
0000120 0022 0000 0000 0000 0037 0000 0000 0000
0000140 0059 0000 0000 0000 0090 0000 0000 0000
0000160 00e9 0000 0000 0000 0179 0000 0000 0000
0000200 0262 0000 0000 0000 03db 0000 0000 0000
0000220 063d 0000 0000 0000 0a18 0000 0000 0000
First integer is a count 0x5e (93), followed by 3 empty higher significant bytes, then sequence begins. 0,1,1,2,3,5 and so on.

Why doesn't the data I'm receiving from a peer match the expected output?

In my spare time, I have been working on implementing a BitTorrent client in C. Currently it communicates with the tracker, connects to the swarm, requests pieces of the torrent file from peers, and receives pieces of the torrent file. However, when it comes to verifying that the received piece is correct (by taking a SHA1 hash and comparing it to the hash provided in the .torrent metadata), it always fails.
To debug this, I downloaded a torrent with a known-working BitTorrent client, and then modified my own BitTorrent implementation to request and download only the very beginning of the torrent (the first piece). I then compared the two files with Emacs' hexl-mode.
Known good:
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
...
00008000: 0143 4430 3031 0100 4c49 4e55 5820 2020 .CD001..LINUX
00008010: 2020 2020 2020 2020 2020 2020 2020 2020
00008020: 2020 2020 2020 2020 5562 756e 7475 2031 Ubuntu 1
00008030: 312e 3034 2069 3338 3620 2020 2020 2020 1.04 i386
My implementation:
00000000: a616 f132 7f00 0080 5066 0000 0000 0080 ...2....Pf......
00000010: 5066 0000 0000 0060 3b62 0000 0000 0098 Pf.....`;b......
00000020: 3b62 0000 0000 00d0 3b62 0000 0000 0008 ;b......;b......
00000030: 3c62 0000 0000 0040 3c62 0000 0000 0078 <b.....#<b.....x
00000040: 3c62 0000 0000 00b0 3c62 0000 0000 00e8 <b......<b......
00000050: 3c62 0000 0000 0020 3d62 0000 0000 0058 <b..... =b.....X
00000060: 3d62 0000 0000 0090 3d62 0000 0000 00c8 =b......=b......
00000070: 3d62 0000 0000 0000 3e62 0000 0000 0038 =b......>b.....8
...
0000d000: 0243 4430 3031 0100 004c 0049 004e 0055 .CD001...L.I.N.U
0000d010: 0058 0020 0020 0020 0020 0020 0020 0020 .X. . . . . . .
0000d020: 0020 0020 0020 0020 0055 0062 0075 006e . . . . .U.b.u.n
0000d030: 0074 0075 0020 0031 0031 002e 0030 0034 .t.u. .1.1...0.4
0000d040: 0020 0069 0033 0038 0000 0000 0000 0000 . .i.3.8........
I figured, then, that I must be writing the received piece to the incorrect offset, resulting in the correct data occuring at the wrong location in the file. To verify this, I fired up gdb and inspected the very beginning of the first piece after receiving it from a peer, expecting it to contain all zeroes, like the beginning of the known-good file.
(gdb) break network.c:40
Breakpoint 1 at 0x402fe7: file network.c, line 40.
(gdb) run
Starting program: /home/robb/slug/slug
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffcb58d700 (LWP 12936)]
[Thread 0x7fffcb58d700 (LWP 12936) exited]
ANNOUNCE: 50 peers.
CONNECTED: 62.245.41.28
CONNECTED: 89.178.142.45
CONNECTED: 66.65.166.17
...
UNCHOKE: 95.26.0.1
Requested piece 0 from peer 95.26.0.1.
UNCHOKE: 202.231.116.163
PIECE: #0 from 95.26.0.1
Breakpoint 1, handle_piece (p=0x42d7e0) at network.c:41
41 memcpy(p->torrent->mmap + length, &p->message[9], REQUEST_LENGTH);
(gdb) p off
$1 = 0
(gdb) p index
$2 = 0
(gdb) p p->message[9]
$3 = 46 '.'
(gdb) p p->message[10]
$4 = 67 'C'
(gdb) p p->message[11]
$5 = 0 '\000'
(gdb) p p->message[12]
$6 = 0 '\000'
(gdb) p p->message[13]
$7 = 0 '\000'
(gdb) p p->message[14]
$8 = 0 '\000'
(gdb) p p->message[15]
$9 = 0 '\000'
(gdb) p p->message[16]
$10 = 128 '\200'
(gdb) p p->message[17]
$11 = 46 '.'
(gdb) p p->message[18]
$12 = 67 'C'
As you can see, the data I received from the peer doesn't contain all zeroes like the beginning of the known-good file. Why?
The full source of my program is availabe at https://github.com/robertseaton/slug.
This fails to take into account that bufferevent_read may fail and return a negative amount:
void get_msg (struct bufferevent* bufev, struct Peer* p)
{
uint64_t amount_read = p->message_length - p->amount_pending;
int64_t message_length = bufferevent_read(bufev, &p->message[amount_read], p->amount_pending);
Replace with:
void get_msg (struct bufferevent* bufev, struct Peer* p)
{
uint64_t amount_read = p->message_length - p->amount_pending;
int64_t message_length = bufferevent_read(bufev, &p->message[amount_read], p->amount_pending);
/* possible bufferevent_read found nothing */
if (message_length < 0)
message_length = 0;
Reading the source I found this in network.c:
memcpy(&index, &p->message[1], sizeof(index));
memcpy(&off, &p->message[5], sizeof(off));
index = ntohl(index);
off = ntohl(off);
length = index * p->torrent->piece_length + off;
#ifdef DEBUG
if (off == 0)
printf("PIECE: #%d from %s\n", index, inet_ntoa(p->addr.sin_addr));
#endif
memcpy(p->torrent->mmap + length, &p->message[9], REQUEST_LENGTH);
p->torrent->pieces[index].amount_downloaded += REQUEST_LENGTH;
I think the last two lines are intended to be:
memcpy(p->torrent->mmap + length, &p->message[9], length);
p->torrent->pieces[index].amount_downloaded += length;
BTW REQUEST_LENGTH = 16K.
More probably this "length-thing" should be p->message_length, or (p->message_length - 9)
The other bug is probably a strlen()+1 type of bug.

Resources