Problems interpreting ar file within code - c++

I've been trying to interpret an ar(the libglib-2.0.a) file using this struct here declared in ar.h. Acording to the wiki the ending characters shoud be 0x60 and 0x0A, but what I got is 0x35 and 0x34, in fact the ending characters are actually 8 bytes ahead in the stream!
Here's the code:
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <ar.h>
int main(){
int fd = open("libglib-2.0.a", O_RDONLY);
char b[1000];
read(fd, b, 1000);
ar_hdr *arS = (ar_hdr*) b;
int dummy = 0;
}
Am I missing something?

First of all, you miss the 8 bytes offset at the top.
#define ARMAG "!<arch>\n" /* String that begins an archive file. */
#define SARMAG 8 /* Size of that string. */
Then, you create a buffer of a bizarre size — 1000. That value makes absolutely no sense, we have a correct buffer size for it, which is the size of header itself — we know it statically, it's 60 bytes. Not to mention that to interpret the buffer as a correct struct, memory representation should be properly aligned.
Here's a working example, for the sake of brevity, error-checking is omitted.
#include <stdio.h>
#include "unistd.h"
#include <fcntl.h>
#include <string.h>
#include "ar.h"
int main() {
int fd = open("/usr/lib/libc.a", O_RDONLY);
lseek(fd, SARMAG, SEEK_SET);
ssize_t bufSize = sizeof(struct ar_hdr);
char buf[bufSize];
read(fd, buf, bufSize);
struct ar_hdr header;
memcpy(&header, buf, bufSize);
printf("\%02hhx, \%02hhx\n", header.ar_fmag[0], header.ar_fmag[1]);
return 0;
}
$ ./read
60, 0a

Related

Issue reading in a char array using sscanf in octal using either C or C++

When trying to read in the octal value for "24" to an unsigned int, I get 0. Simply passing in the decimal value as a char array works.
I need the final value as a 32 bit unsigned int. The initial value is read in from a binary file.
MCVE
simple.cpp
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char count[4] = "\030\000\000"; // Just "24" works
__uint32_t value;
sscanf(count, "%x", &value);
fprintf(stderr, "%x", value);
return 0;
}
Compiled and executed using
$ g++ simple.cpp -g
$ ./a.out
0
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
The octal value 030 is a single character representing the special "CAN" (Cancel) control character in ASCII encoding (which is the most common encoding for the English alphabet and digits and punctuation).
When you use scanf (or its sibling sscanf) it will try to read digits, which in the ASCII encoding are the values 060 to 071 (for the digits 0 to 9, inclusive).
To be able to use sscanf to read the number 24 you need to the two characters '2' and '4'. I.e. "24" (or "\062\064").
If you want to convert the single character '\030' to the integer value 24, then just do e.g.
value = count[0];
I assumed that you get 4 bytes in a record coming from a binary file, and you want to convert those 4 bytes to an uint32_t value. I also assume that the bytes come with the expected endianness.
The simplest (and most standard conformant way) to do the conversion is to copy the byte representation to a variable:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char count[4] = "\030\000\000"; // Just "24" works
__uint32_t value;
memcpy(&value, count, sizeof(value));
fprintf(stderr, "%d", value);
return 0;
}
will return as expected 24.
here is a version of your code, that checks for an error on the call to scanf()
Note: that the unneeded C++ header files are commented out.
//#include <iostream>
//#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main( void )
{
char count[4] = "\030\000\000"; // Just "24" works
uint32_t value;
if( 1 != sscanf(count, "%x", &value) )
{
fprintf( stderr, "sscanf failed" );
exit( EXIT_FAILURE );
}
// implied else, sscanf successful
printf( "%x", value);
return 0;
}
and here is the resulting output:
sscanf failed

read file descriptor HANGS

I have a very simple source reading file descriptor which hangs.
Could anyone notice the problem the code has?
The first one is the problematic source and the second one is the working source found on the web. Two sources are almost identical.
First source
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char ** argv) {
int n, in;
char buf[1024];
if ((in = open(argv[1], O_RDONLY)<0)) {
perror(argv[1]);
return -1;
}
while((n = read(in, buf, sizeof(buf))) > 0 ) { //HANGS at THIS LINE!!!!!!!!!!!
printf("TEST\n");
}
close(in);
return 0;
}
Second Working source got from online
/*
* ============================================================================
* Name : sp_linux_copy.c
* Author : Marko Martinović
* Description : Copy input file into output file
* ============================================================================
**/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 8192
int main(int argc, char* argv[]) {
int input_fd; /* Input and output file descriptors */
ssize_t ret_in; /* Number of bytes returned by read() and write() */
char buffer[BUF_SIZE]; /* Character buffer */
/* Create input file descriptor */
input_fd = open (argv [1], O_RDONLY);
if (input_fd == -1) {
perror ("open");
return 2;
}
/* Copy process */
while((ret_in = read (input_fd, &buffer, BUF_SIZE)) > 0){
printf("TEST\n");
}
/* Close file descriptors */
close (input_fd);
}
By a funny coincidence, you are reading from stdin. This is because in your if(in = ... you misplaced some brackets.
What is happening is that first open(argv[1], O_RDONLY)<0 gets evaluated, and the result gets put into in. Since the result of open() is not smaller than zero (on succesfull open), in becomes 0. And stdin is the name for the filedescriptor which is zero (on most systems). So it is a valid file descriptor, and read is very happy to read from it. It is just not getting any, until you type something in your console.
quick fix:
if ( (in = open(argv[1], O_RDONLY)) < 0) {

Sending TFTP packets in C++

I am relatively new to C++, so please forgive my lack of knowledge. I need help regarding TFTP packets. Below is the code I am using to generate a WRQ (write request package) and DATA packet which will be sent to a designated server.
bool createWRQ(char * filename) {
/* structure is the same as RRQ */
clear();
addWord(TFTP_OPCODE_WRITE);
addString(filename);
addByte(0);
addString(TFTP_DEFAULT_TRANSFER_MODE);
addByte(0);
return true;
}
bool createData(int block, char * mData, int data_size) {
/* 2 bytes 2 bytes n bytes
----------------------------------------
DATA | 03 | Block # | Data |
---------------------------------------- */
clear(); // to clean the memory location
addWord(TFTP_OPCODE_DATA);
addWord(block);
addMemory(mData, data_size);
return true;
}
I will include the declarations and required functions.
#include "stdafx.h"
#include "WebComm.h"
#include "WebCommDlg.h"
#include <stdio.h>
#include <stdlib.h>
#include "visa.h"
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winsock.h>
#include <string.h>
#include <string>
#include <fstream>
#include <cstdio>
#include <cerrno>
int mCurPacketSize = 512;
char mData[512];
#define VIBUF_LEN 255
#define TFTP_OPCODE_READ 1
#define TFTP_OPCODE_WRITE 2
#define TFTP_OPCODE_DATA 3
#define TFTP_OPCODE_ACK 4
#define TFTP_OPCODE_ERROR 5
#define cTFTPPacket_MAX_SIZE 1024
#define cTFTPPacket_DATA_SIZE 512
#define TFTP_DEFAULT_TRANSFER_MODE "octet" //"netascii", "octet", or "mail"
typedef unsigned char BYTE;
typedef unsigned short WORD;
bool addByte(BYTE b) {
if(mCurPacketSize >= cTFTPPacket_MAX_SIZE)
return false;
mData[mCurPacketSize] = (unsigned char)b;
mCurPacketSize++;
return true;
}
bool addWord(WORD w) {
w = htons(w);
if(!addByte(*(((BYTE*)&w)+1)))
return false;
return !addByte(*((BYTE*)&w));
}
bool addString(char * str) {
int n = strlen(str);
for(int i=0; i<n; i++)
if(!addByte(str[i]))
return false;
return true;
}
bool addMemory(char * buffer, int len) {
bool oStatus = false;
if(mCurPacketSize + len >= cTFTPPacket_MAX_SIZE) {
AfxMessageBox("Packet max size exceeded");
return false;
} else {
memcpy(mData + mCurPacketSize), buffer, len);
mCurPacketSize += len;
return true;
}
}
void clear() {
mCurPacketSize = 0;
memset(mData, mCurPacketSize, cTFTPPacket_MAX_SIZE);
}
I am aware these function have been declared mostly as type bool, however I need to send a WRQ packet to the server and wait for an ACK response before sending a DATA packet.
Something along the lines of:
while(/* something */)
if(!sendto(socket, WRQ, 512, NULL, (sockaddr*)&Addr, sizeof(struct sockaddr_in)))){
if(!recvfrom(socket, ACK, /* ... */))
sendto(socket, DATA_Packet, 512, NULL, (sockaddr*)&Addr, sizeof(struct sockaddr_in))));
My question is: how can I modify the createWRQ() and createData() functions so that I can return them as packets to use for transmission, since bool only returns true or false as 1 or 0.
I need to be able to send them using the winsock send and receive functions. Apologies for the silly question. If anyone could point me in the right direction I would greatly appreciate it.
your whole approach has a few issues...
When you create your packets relying on functions like
bool addByte(BYTE b)
they use global variables
mCurPacketSize, mData
that's not good. You could use instead something on these lines
int addByte(char* Pkt, int PktIdx, BYTE b)
{
if (PktIdx > cTFTPPacket_MAX_SIZE)
{
return 0;
}
Pkt[PktIdx] = (unsigned char)b;
PktIdx++;
return PktIdx;
}
then you know that Pkt is always the head of your packet and PktIdx is either the place for a new byte (or string) and "also" the size of the packet.
When you create packets that have a fixed length structure (or a fixed length header followed by a variable length payload area) it is a good idea to represent the fixed length area with a "packed" (pay attention to memory alignment) C/C++ structure and then populate the structure.

C/C++ Arbitrary output size when decompressing GZIP

I'm using this to decompress a GZIP compressed file "input.gz" into the uncompressed "output.file". It works wonderfully, except I need a fixed size for the buffer (in this case 1MB) and if the output becomes larger the bytes get cut off. Is there a way to get this to work with any output size?
#include "zlib.h"
#include <stdio.h>
int main()
{
char buf[1024*1024];
gzFile in = gzopen("input.gz","rb8");
int len = gzread(in,buf,sizeof(buf));
gzclose(in);
FILE* out = fopen("output.file", "wb");
fwrite(buf,1,len,out);
fclose(out);
free(buf);
return 0;
}
gzread works the same way as fread. Consecutive calls to gzread just read more data from that file. I haven't tested the code, but this should work fine.
#include "zlib.h"
#include <stdio.h>
int main() {
char buf[1024];
gzFile in = gzopen("input.gz","rb8");
FILE* out = fopen("output.file", "wb");
while (int len = gzread(in, buf, sizeof(buf)))
fwrite(buf, 1, len, out);
gzclose(in);
fclose(out);
return 0;
}

C++ - Strangely formatted hexadecimal output

I'm sure this is a simple question, but I'm trying to output the hexadecimal value of each byte in a file (*.bmp in this case). I have successfully loaded the file in memory, and am able to print hex values of bytes. but when I print certain bytes,When I print certain bytes, for example the 3rd byte (at offset 2), it prints FFFFFFE6, but my hexdump(using HxD) of the file says it is just E6. This happens only on certain bytes, the others print just fine.
Main.cpp is:
#include "main.h"
int main ()
{
ifstream::pos_type size;
char * memblock;
ifstream file ("C:\\hex.bmp", ios::in|ios::binary|ios::ate);
size = file.tellg();
memblock = new char [size];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
printf("%X", memblock[2]);
delete[] memblock;
cin.get();
}
Main.h is:
#ifndef MAIN_H
#define MAIN_H
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
#endif
You need to understand how variable arguments and standard integral conversions work. When you char is signed, you're in trouble.
Always print bytes as unsigned chars:
char data[100];
printf("%02X", (unsigned char)data[i]);
// ^^^^^^^^^^^^^^^