C check if archive file is truncated with struct ar_hdr (ar.h) - c

I'm using the ar.h's structure : struct ar_hdr to retrieve informations inside my archive file (lib.a) using read to iterate over it, and i'm running into a little problem if the file is truncated.
In using the C language and when the file was truncated it currently makes me get a segmentation fault.
Is there any way to check if the file is truncated beforehand ? like by using stat or stuff like that ?
Thanks in advance
PS: be free to tell me if my question wasn't really understandable and clear
#define SIZE atoi(ar->ar_size)
struct ar_hdr *get_header(int fd)
{
struct ar_hdr *ar = (struct ar_hdr *)malloc(sizeof(struct ar_hdr));
if (read(fd, ar, sizeof(struct ar_hdr)) != sizeof(struct ar_hdr)) {
free(ar);
return NULL;
}
return ar;
}
int handle_ar_files(int fd, char *names[2], int ret)
{
struct ar_hdr *ar = NULL;
void *buf = NULL;
int index = 0;
while ((ar = get_header(fd)) != NULL) {
index = 0;
buf = malloc(SIZE);
if (ar->ar_name[0] == '/') {
my_free(ar, buf, (int [2]){fd, SIZE}, 1);
continue;
}
for (; ar->ar_name[index] && ar->ar_name[index] != '/'; index++);
ar->ar_name[index] = 0;
if ((read(fd, buf, SIZE)) != SIZE)
return my_free(ar, buf, (int [2]){fd, SIZE}, 0);
if ((parse_ar(buf, SIZE, (char *[2]){names[1], ar->ar_name})) == 84)
return my_free(ar, buf, (int [2]){fd, SIZE}, 0);
else
my_free(ar, buf, (int [2]){fd, SIZE}, 0);
}
return ret;
}
void *buf32 = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (strncmp((char *)buf32, ARMAG, SARMAG) == 0) {
read(fd, tmp, SARMAG);
return handle_ar_files(fd, names, 0);
}
#ifndef _AR_H
#define _AR_H 1
#include <sys/cdefs.h>
/* Archive files start with the ARMAG identifying string. Then follows a
`struct ar_hdr', and as many bytes of member file data as its `ar_size'
member indicates, for each member file. */
#define ARMAG "!<arch>\n" /* String that begins an archive file. */
#define SARMAG 8 /* Size of that string. */
#define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
__BEGIN_DECLS
struct ar_hdr
{
char ar_name[16]; /* Member file name, sometimes / terminated. */
char ar_date[12]; /* File date, decimal seconds since Epoch. */
char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
char ar_mode[8]; /* File mode, in ASCII octal. */
char ar_size[10]; /* File size, in ASCII decimal. */
char ar_fmag[2]; /* Always contains ARFMAG. */
};
__END_DECLS
#endif /* ar.h */

Related

Abort 6 issues when using memcpy()

I am getting Abort 6 error and I have looked it up. I don't see where in my code a strcpy() is used but possibly memcpy() could be the issue? Not sure where and why its happening but it only starting appearing when I implementing the root directory update in the code.
NOTE: I have left out dir.name and will implement later when this other issue resolves.
It prints out the print functions but seems to abort when implementing the root directory code below.
The global file is below:
#include "../sifs.h"
#include "md5.h"
// CONCRETE STRUCTURES AND CONSTANTS USED THROUGHOUT THE SIFS LIBRARY.
// DO NOT CHANGE ANYTHING IN THIS FILE.
#define SIFS_MIN_BLOCKSIZE 1024
#define SIFS_MAX_NAME_LENGTH 32 // including the NULL byte
#define SIFS_MAX_ENTRIES 24 // for both directory and file entries
#define SIFS_UNUSED 'u'
#define SIFS_DIR 'd'
#define SIFS_FILE 'f'
#define SIFS_DATABLOCK 'b'
#define SIFS_ROOTDIR_BLOCKID 0
typedef struct {
size_t blocksize;
uint32_t nblocks;
} SIFS_VOLUME_HEADER;
typedef char SIFS_BIT; // SIFS_UNUSED, SIFS_DIR, ...
typedef uint32_t SIFS_BLOCKID;
// DEFINITION OF EACH DIRECTORY BLOCK - MUST FIT INSIDE A SINGLE BLOCK
typedef struct {
char name[SIFS_MAX_NAME_LENGTH];
time_t modtime; // time last modified <- time()
uint32_t nentries;
struct {
SIFS_BLOCKID blockID; // of the entry's subdirectory or file
uint32_t fileindex; // into a SIFS_FILEBLOCK's filenames[]
} entries[SIFS_MAX_ENTRIES];
} SIFS_DIRBLOCK;
// DEFINITION OF EACH FILE BLOCK - MUST FIT INSIDE A SINGLE BLOCK
typedef struct {
time_t modtime; // time first file added <- time()
size_t length; // length of files' contents in bytes
unsigned char md5[MD5_BYTELEN];
SIFS_BLOCKID firstblockID;
uint32_t nfiles; // n files with identical contents
char filenames[SIFS_MAX_ENTRIES][SIFS_MAX_NAME_LENGTH];
} SIFS_FILEBLOCK;
FILE1.C
#include "sifs-internal.h"
// make a new directory within an existing volume
int SIFS_mkdir(const char *volumename, const char *dirname)
{
FILE *fp = fopen(volumename, "r+");
if(fp != NULL){
//read in the header information
SIFS_VOLUME_HEADER header;
fread(&header,sizeof header,1,fp);
printf("%zu\n", header.blocksize);
printf("%u", header.nblocks);
// Check for vaidty of variables
if (header.nblocks == 0 || header.blocksize < SIFS_MIN_BLOCKSIZE) {
SIFS_errno = SIFS_EINVAL;
return 1;
}
//read in the bitmap information
SIFS_BIT bitmap[header.nblocks];
fseek(fp ,sizeof header, SEEK_SET);
fread(&bitmap, header.nblocks,1,fp);
for (int i = 1; i < header.nblocks; i++){
if (bitmap[i] == SIFS_UNUSED){
bitmap[i] = SIFS_DIR;
// update the root directory
char rootblock[header.blocksize];
SIFS_DIRBLOCK rootdir_block;
fseek(fp, sizeof header + sizeof bitmap, SEEK_SET);
fread(&rootdir_block, header.blocksize,1,fp);
for (int j = 0; j < SIFS_MAX_ENTRIES; j++){
rootdir_block.entries[j].blockID = i;
rootdir_block.nentries += rootdir_block.nentries + 1;
break;
}
//write the new updated root dir into the vol
memset(rootblock, 0, sizeof rootblock);
memcpy(rootblock, &rootdir_block, sizeof(rootdir_block));
fseek(fp ,sizeof header + sizeof bitmap, SEEK_SET);
fwrite(rootblock, sizeof rootblock, 1, fp);
char oneblock[header.blocksize];
time_t now;
SIFS_DIRBLOCK dir;
memset(&dir, 0, sizeof(dir)); // set all to zero
memset(oneblock, 0, sizeof oneblock);
dir.modtime = time(&now);
dir.nentries = 0;
//set the block to 0 and assign memory of dir into block
memcpy(oneblock, &dir, sizeof(dir));
//write the dir data into the volume
fseek(fp ,sizeof header + sizeof bitmap + i * header.blocksize, SEEK_SET);
fwrite(oneblock, sizeof oneblock, 1, fp);
//memset(oneblock, 0, sizeof oneblock);
//Update the bitmap
fseek(fp ,sizeof header, SEEK_SET);
fwrite(bitmap, sizeof bitmap, 1, fp);
fclose(fp);
return 0;
}
}
}
SIFS_errno = SIFS_ENOTYET;
return 1;
}

How do I return a pointer to location in a buffer? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm currently working on a project in C which I'm required to create a buffer program. For the most part my program is finished but I'm just missing one required function: a location function to return the distance between the head (beginning of array) to the desired location designated by short loc_offset.
Given what I already have, how do I return a pointer to an index or location from my short?
Here is my given and created code:
Main (plat_bt.c):
/* File name: platy_bt.c
* Purpose:This is the main program for Assignment #1, CST8152
* Version: 1.18.1
* Author: Svillen Ranev
* Date: 16 January 2018
*/
/* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects
* to suppress the warnings about using "unsafe" functions like fopen()
* and standard sting library functions defined in string.h.
* The define directive does not have any effect on other compiler projects (gcc, Borland).
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* constant definitions */
#define INIT_CAPACITY 200 /* initial buffer capacity */
#define INC_FACTOR 15 /* increment factor */
/*check for ANSI C compliancy */
#define ANSI_C 0
#if defined(__STDC__)
#undef ANSI_C
#define ANSI_C 1
#endif
/* Declaration of an error printing function with
* variable number of arguments
*/
void err_printf(char *fmt, ...);
/* Declaration of a buffer contents display function */
void display (Buffer *ptr_Buffer);
long get_filesize(char *fname);
int main(int argc, char **argv){
pBuffer ptr_Buffer; /* pointer to Buffer structure */
FILE *fi; /* input file handle */
int loadsize = 0; /*the size of the file loaded in the buffer */
int ansi_c = !ANSI_C; /* ANSI C compliancy flag */
/* Check if the compiler option is set to compile ANSI C */
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
if(ansi_c){
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
err_printf("ERROR: Compiler is not ANSI C compliant!\n");
exit(1);
}
/* missing file name or/and mode parameter */
if (argc <= 2){
err_printf("\nDate: %s Time: %s",__DATE__, __TIME__);
err_printf("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__);
err_printf("%s\b\b\b\b%s%s",argv[0],": ","Missing parameters.");
err_printf("Usage: platybt source_file_name mode");
exit(1);
}
/* create a source code input buffer */
switch(*argv[2]){
case 'f': case 'a': case 'm': break;
default:
err_printf("%s%s%s",argv[0],": ","Wrong mode parameter.");
exit(1);
}
/*create the input buffer */
ptr_Buffer = b_allocate(INIT_CAPACITY,INC_FACTOR,*argv[2]);
if (ptr_Buffer == NULL){
err_printf("%s%s%s",argv[0],": ","Cannot allocate buffer.");
exit(1);
}
/* open the source file */
if ((fi = fopen(argv[1],"r")) == NULL){
err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
exit (1);
}
/* load a source file into the input buffer */
printf("Reading file %s ....Please wait\n",argv[1]);
loadsize = b_load (fi,ptr_Buffer);
if(loadsize == RT_FAIL1)
err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");
/* close the source file */
fclose(fi);
/*find the size of the file */
if (loadsize == LOAD_FAIL){
printf("The input file %s %s\n", argv[1],"is not completely loaded.");
printf("Input file size: %ld\n", get_filesize(argv[1]));
}
/* display the contents of the input buffer */
display(ptr_Buffer);
/* compact the buffer
* add end-of-file character (EOF) to the buffer
* display again
*/
if(!b_compact(ptr_Buffer,EOF)){
err_printf("%s%s%s",argv[0],": ","Error in compacting buffer.");
}
display(ptr_Buffer);
/* free the dynamic memory used by the buffer */
b_free(ptr_Buffer);
/* make the buffer invalid
It is not necessary here because the function terminates anyway,
but will prevent run-time errors and crashes in future expansions
*/
ptr_Buffer = NULL;
/*return success */
return (0);
}
/* error printing function with variable number of arguments*/
void err_printf( char *fmt, ... ){
/*Initialize variable list */
va_list ap;
va_start(ap, fmt);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
/* Move to new line */
if( strchr(fmt,'\n') == NULL )
fprintf(stderr,"\n");
}
void display (Buffer *ptr_Buffer){
printf("\nPrinting buffer parameters:\n\n");
printf("The capacity of the buffer is: %d\n",b_capacity(ptr_Buffer));
printf("The current size of the buffer is: %d\n",b_limit(ptr_Buffer));
printf("The operational mode of the buffer is: %d\n",b_mode(ptr_Buffer));
printf("The increment factor of the buffer is: %lu\n",b_incfactor(ptr_Buffer));
printf("The current mark of the buffer is: %d\n", b_mark(ptr_Buffer, b_limit(ptr_Buffer)));
/*printf("The reallocation flag is: %d\n",b_rflag(ptr_Buffer));*/
printf("\nPrinting buffer contents:\n\n");
b_rewind(ptr_Buffer);
b_print(ptr_Buffer);
}
long get_filesize(char *fname){
FILE *input;
long flength;
input = fopen(fname, "r");
if(input == NULL){
err_printf("%s%s","Cannot open file: ",fname);
return 0;
}
fseek(input, 0L, SEEK_END);
flength = ftell(input);
fclose(input);
return flength;
}
That main file has no errors or warnings, it was given to me to be used as my main.
Here is my edited source file (buffer.c):
/* File name: buffer.c
* Purpose: This is the main program for Assignment #01, CST8152
* Version: 1.0.3
* Author: Jack Loveday
* Date: 7 Febuary, 2018
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* b_allocate: Creates new buffer on heap
Tries to allocate memory for:
- one Buffer (calloc)
- one dynamic character buffer (char array) (malloc)
Sets buffer operational mode and inc factor
Copies given init_capacity into Buffer capacity val */
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode) {
Buffer *pBuffer;
if (init_capacity < 0 || (unsigned char)inc_factor < 0)
return NULL;
pBuffer = (Buffer *)calloc(1, sizeof(Buffer));
if (!pBuffer) {
free(pBuffer);
return NULL;
}
pBuffer->cb_head = (char *)malloc(init_capacity);
if (o_mode == 'f' || (unsigned char)inc_factor == 0) {
pBuffer->mode = 0;
pBuffer->inc_factor = 0;
}
else if (o_mode == 'a') {
pBuffer->mode = ADD_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else if (o_mode == 'm' && (unsigned char)inc_factor <= 100) {
pBuffer->mode = MULTI_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else {
free(pBuffer->cb_head);
free(pBuffer);
return NULL;
}
pBuffer->capacity = init_capacity;
return pBuffer;
}
/* b_addc: resets r_flag to 0 & tries to add symbol to char array pointed by pBD */
pBuffer b_addc(pBuffer const pBD, char symbol) {
char *tBuffer;
short aSpace = 0, newInc = 0, newCapacity = 0;
if (!pBD)
return NULL;
pBD->r_flag = 0;
if ((short)(pBD->addc_offset * sizeof(char)) < pBD->capacity) {
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
}
else if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity) {
if (pBD->mode == 0)
return NULL;
else if (pBD->mode == 1) {
newCapacity = pBD->capacity + (unsigned char)pBD->inc_factor * sizeof(char);
if (newCapacity <= 0)
return NULL;
pBD->capacity = newCapacity;
}
else if (pBD->mode == -1) {
if (pBD->capacity == SHRT_MAX)
return NULL;
else {
aSpace = SHRT_MAX - pBD->capacity;
newInc = (short)((aSpace * pBD->inc_factor) / 100);
if (!newInc)
newInc = NEW_ONE;
newCapacity = (short)((pBD->capacity + newInc));
if (newCapacity <= 0)
newCapacity = SHRT_MAX;
}
}
tBuffer = (char *)realloc(pBD->cb_head, newCapacity);
if (tBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tBuffer;
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
pBD->capacity = newCapacity;
}
return pBD;
}
/* b_clear: retains memory space currently allocated to buffer, but
re-initializes all appropriate members of given Buffer */
int b_clear(Buffer * const pBD){
if (!pBD)
return RT_FAIL1;
pBD->capacity = 0;
pBD->addc_offset = 0;
pBD->getc_offset = 0;
pBD->eob = 0;
return 1;
}
/* b_free: de-allocates memory for char array & Buffer struct */
void b_free(Buffer * const pBD) {
if (pBD) {
free(pBD->cb_head);
free(pBD);
}
}
/* b_isfull: returns 1 if buffer is full, otherwise returns 0, if rt error return -1 */
int b_isfull(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity)
return 1;
else
return 0;
}
/* b_limit: returns current limit of buffer, return -1 on error */
short b_limit(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->addc_offset;
}
/* b_capacity: returns current capacity of buffer, return -1 on error */
short b_capacity(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->capacity;
}
/* b_mark: sets markc_offset to mark, must be between 0 and addc_offset, return -1 on error */
short b_mark(pBuffer const pBD, short mark) {
if (!pBD || mark < 0 || mark > pBD->addc_offset)
return RT_FAIL1;
pBD->markc_offset = mark;
return pBD->markc_offset;
}
/* b_mode: returns value of mode, or -1 on error */
int b_mode(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->mode;
}
/* b_infactor: returns non-negative value of inc_factor, return 0x100 (256) */
size_t b_incfactor(Buffer * const pBD) {
if (!pBD)
return NEW_FULL;
return (unsigned char)pBD->inc_factor;
}
/* b_load: returns value of mode */
int b_load(FILE * const fi, Buffer * const pBD) {
char c;
int cNum = 0;
if (!fi || !pBD)
return RT_FAIL1;
for (;;) {
c = (char)fgetc(fi);
if (feof(fi))
break;
if (!b_addc(pBD, c))
return LOAD_FAIL;
++cNum;
}
fclose(fi);
return cNum;
}
/* b_isempty: if addc_offset is 0 return 1, otherwise return 0, return -1 on error */
int b_isempty(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if (!pBD->addc_offset)
return 1;
else
return 0;
}
/* b_eob: returns eob (end of buffer), returns -1 on error */
int b_eob(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->eob;
}
/* b_getc: checks logic, if not valid returns -2, if getc_offset and addc_offset
are equal, set eob to 1 and returns -1, otherwise set eob to 0 */
char b_getc(Buffer * const pBD) {
char returner;
if (!pBD || !pBD->cb_head)
return RT_FAIL2;
if (pBD->getc_offset == pBD->addc_offset) {
pBD->eob = 1;
return RT_FAIL1;
}
else {
pBD->eob = 0;
}
returner = *(pBD->cb_head + pBD->getc_offset);
pBD->getc_offset++;
return returner;
}
/* b_print: used for diagnostic purposes only, returns -1 on error */
int b_print(Buffer * const pBD) {
int numOfChars = 0;
char c;
if (!pBD->addc_offset) {
printf("The Buffer is empty.\n");
return numOfChars;
}
pBD->getc_offset = 0;
while (1) {
c = b_getc(pBD);
if (b_eob(pBD))
break;
printf("%c", c);
++numOfChars;
}
numOfChars = pBD->getc_offset;
pBD->getc_offset = 0;
printf("\n");
return numOfChars;
}
/* b_compact: shrinks buffer to new capacity, before returning to a pointer add symbol
to the end of buffer, must set r_flag appropriatley */
Buffer * b_compact(Buffer * const pBD, char symbol) {
char *tempBuffer;
short tempCap;
if (!pBD)
return NULL;
tempCap = (pBD->addc_offset + 1) * sizeof(char);
if (tempCap == SHRT_MAX)
return pBD;
tempBuffer = (char *)realloc(pBD->cb_head, (unsigned short)tempCap);
if (tempCap == 0)
return NULL;
if (tempBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tempBuffer;
pBD->capacity = tempCap;
return pBD;
}
/* b_rflag: returns r_flag, returns -1 on error */
char b_rflag(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->r_flag;
}
/* b_retract: decrements getc_offset by 1, returns -1 on error, otherwise returns getc_offset */
short b_retract(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset--;
return pBD->getc_offset;
}
/* b_reset: sets getc_offset to current markc_offset, returns -1 on error and getc_offset otherwise */
short b_reset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset = pBD->markc_offset;
return pBD->getc_offset;
}
/* b_getcoffset: returns getc_offset, or returns -1 on error */
short b_getcoffset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->getc_offset;
}
/* b_rewind: set getc_offset and markc_offset to 0, return -1 on error and 0 otherwise */
int b_rewind(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->addc_offset = 0;
pBD->markc_offset = 0;
return 0;
}
/* b_location: returns a pointer to location indicated by loc_offset, returns null on error */
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
return *loc_offset;
}
And finally my buffer.h:
/*File Name: buffer.h
* Version: 1.18.1
* Author: S^R
* Date: 16 January 2018
* Preprocessor directives, type declarations and prototypes necessary for buffer implementation
* as required for CST8152-Assignment #1.
* The file is not completed.
* You must add your function declarations (prototypes).
* You must also add your constant definitions and macros,if any.
*/
#ifndef BUFFER_H_
#define BUFFER_H_
/*#pragma warning(1:4001) *//*to enforce C89 type comments - to make //comments an warning */
/* standard header files */
#include <stdio.h> /* standard input/output */
#include <malloc.h> /* for dynamic memory allocation*/
#include <limits.h> /* implementation-defined data type ranges and limits */
/* constant definitions */
/* You may add your own constant definitions here */
#define RT_FAIL1 -1 /* fail return value */
#define RT_FAIL2 -2 /* fail return value */
#define LOAD_FAIL -2 /* load fail error */
#define SET_R_FLAG 1 /* realloc flag set value */
#define ADD_MODE 1; /* named constant for additive mode */
#define MULTI_MODE -1; /* named constant for multiplicative mode */
#define NEW_ONE 1; /* generic named constant value of 1 */
#define NEW_FULL 256; /* generic named constant value of 256 */
/* user data type declarations */
typedef struct BufferDescriptor {
char *cb_head; /* pointer to the beginning of character array (character buffer) */
short capacity; /* current dynamic memory size (in bytes) allocated to character buffer */
short addc_offset; /* the offset (in chars) to the add-character location */
short getc_offset; /* the offset (in chars) to the get-character location */
short markc_offset; /* the offset (in chars) to the mark location */
char inc_factor; /* character array increment factor */
char r_flag; /* reallocation flag */
char mode; /* operational mode indicator*/
int eob; /* end-of-buffer flag */
} Buffer, *pBuffer;
/* function declarations */
/*
Place your function declarations here.
Do not include the function header comments here.
Place them in the buffer.c file
*/
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode);
pBuffer b_addc(pBuffer const pBD, char symbol);
int b_clear(Buffer * const pBD);
void b_free(Buffer * const pBD);
int b_isfull(Buffer * const pBD);
short b_limit(Buffer * const pBD);
short b_capacity(Buffer * const pBD);
short b_mark(pBuffer const pBD, short mark);
int b_mode(Buffer * const pBD);
size_t b_incfactor(Buffer * const pBD);
int b_load(FILE * const fi, Buffer * const pBD);
int b_isempty(Buffer * const pBD);
int b_eob(Buffer * const pBD);
char b_getc(Buffer * const pBD);
int b_print(Buffer * const pBD);
Buffer * b_compact(Buffer * const pBD, char symbol);
char b_rflag(Buffer * const pBD);
short b_retract(Buffer * const pBD);
short b_reset(Buffer * const pBD);
short b_getcoffset(Buffer * const pBD);
int b_rewind(Buffer * const pBD);
char * b_location(Buffer * const pBD, short loc_offset);
#endif
So again, I need to find the location of loc_offset in my b_location function and return it as a pointer. Thanks in advance!
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
/* Make sure loc_offset doesn't go beyond the length of the array */
if( ! in_bounds )
return NULL;
return &(pBD->cb_head[loc_offset]);
}

Queue Linux Can't Write

I got problem in my code for process code:
FILE *fp;
int i,
counter; // Liczba liter w wiadomosci
wchar_t buffer[1024], *line;
struct MsgStructure WB; // Write Buffor
setlocale(LC_ALL, "pl_PL.UTF-8");
while(run)
{
fp = fopen(FIFO, "r");
fwide(fp, 1);
while ((line = fgetws(buffer, sizeof buffer / sizeof buffer[0], fp)) != NULL)
{
counter = 0;
for (i = 0; line[i] != L'\0'; i++)
if (iswalpha(line[i]))
counter++;
WB.Msg = counter;
if ((WriteToQueue( qid, &WB )) == -1)
{
perror("Error\n");
}
}
fclose(fp);
}
My program read from FIFO file then count the amount of letters and then i want to write it to queue but i got an error that i can't write to queue because "Wrong argument"
My structure:
struct MsgStructure {
long int MsgType;
int Msg;
};
WriteToQueue is a simple function:
int WriteToQueue( int qid, struct MsgStructure *qbuf ){
int result, BufSize;
BufSize = sizeof(struct MsgStructure) - sizeof(long);
result = msgsnd( qid, qbuf, BufSize, 0);
return(result);
}
My message type is int and counter is int too. I don't know why this isn't work. Maybe this is problem with setlocale ??
Queue is creating in other process.
As discussed in the comments:
EINVAL Invalid msqid value, or nonpositive mtype value,
or invalid msgsz value (less than 0 or greater than
the system value MSGMAX).
The former has been ruled out and the latter is obviously not true, i.e. BufSize being sizeof(int) in the example code.
Leaves mtype<=0. From the man page:
The msgp argument is a pointer to caller-defined
structure of the following general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
This is in accordance to msgrcv() whose msgtyp argument, if 0, has a special meaning.
Solution is to set MsgType in struct MsgStructure to something greater than 0.

An element of a struct loses its value after a function is called passing another struct as argument

I have a problem that I can't figure out. I have the following files: file_reader.c, file_reader.h, file_writer.c, file_writer.h, test_file_reader.c
I'm working with 'struct' to read and write files. For better understanding I wrote the following code test_file_reader.c:
#include <stdio.h>
#include "file_reader.h"
#include "file_writer.h"
int main ()
{
char *file_path = "/home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml";
struct FileReader *fr = malloc(sizeof(struct FileReader));
file_reader_new (file_path, fr);
show_file_reader_values(fr);
struct FileWriter *fw = malloc(sizeof(struct FileWriter));
fw->file_path = "/tmp/text1.txt";
fw->content = "aaa";
write (fw);
show_file_reader_values(fr);
return 0;
}
void show_file_reader_values(const struct FileReader *fr)
{
printf("==========FILE READER==========\n");
printf("file path: %s\n", fr->file_path);
printf("----------file content---------\n");
printf("content:\n%s\n", fr->content);
printf("----------file content---------\n");
printf("n lines: %d\n", fr->n_lines);
printf("n characters: %d\n", fr->n_characters);
printf("==========FILE READER==========\n\n");
}
The function 'file_reader_new' reads the file and then signs the content, file path, number of lines and number of characters to the 'struct' 'FileReader'.
When I call the function 'show_file_reader_values' in the first time I do not have problems with the content but when I call the function 'write' and then call the function 'show_file_reader_values' again, the content is not the same anymore. The question is that the function 'write' of the file 'file_writer.c' and its struct does not have any relation to the file 'file_reader' and its struct. So, how can a function using another struct change the values of another struct of another file ?
The output:
[freitas#localhost test]$ ./test_file_reader
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc writing software</description> <option> <id>log</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> <option> <id>log2</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> </cleaner>
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k��U�N
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
Did you see ? In the first call I had the entire output:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc wri...
but in the second call I had:
<cleaner> <id>k��U�N
file_reader.c
#include <stdio.h>
#include <stdlib.h>
#include "file_reader.h"
int file_reader_new(const char *file_path, struct FileReader *fr)
{
char *content; // holds the file content.
int counter; // holds the file number of lines.
size_t i; // indexing into content.
size_t buffer_size; // size of the content.
char *temp; // for realloc().
char c; // for reading from the input.
FILE *input; // our input stream.
if ((input = fopen(file_path, "r")) == NULL) {
fprintf(stderr, "Error opening input file %s\n", file_path);
exit(EXIT_FAILURE);
}
/* Initial allocation of content */
counter = 0;
i = 0;
buffer_size = BUFSIZ;
if ((content = malloc(buffer_size)) == NULL) {
fprintf(stderr, "Error allocating memory (before reading file).\n");
fclose(input);
}
while ((c = fgetc(input)) != EOF) {
/* Enlarge content if necessary. */
if (i == buffer_size) {
buffer_size += BUFSIZ;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core while reading file.\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
/* Add input char to the content. */
content[i++] = c;
/* If the character is a break of line
* then the counter will be incremented.
*/
if (c == '\n')
counter++;
}
/* Test if loop terminated from error. */
if (ferror(input)) {
fprintf(stderr, "There was a file input error.\n");
free(content);
fclose(input);
exit(EXIT_FAILURE);
}
/* Make the content a bona-fide string. */
if (i == buffer_size) {
buffer_size += 1;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core (and only needed one more byte too ;_;).\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
content[i] = '\0';
/* Assigns the variables to the corresponding
* element of the struct.
*/
fr->file_path = file_path;
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
fclose(input);
return 0;
}
file_reader.h
#ifndef FILE_READER_H_
#define FILE_READER_H_
typedef struct FileReader
{
char *content; // holds the file content.
char *file_path; // holds the file path.
int *n_lines; // holds the number of lines.
int *n_characters; // holds the number of characters.
} FileReader;
// file_reader_new - reads the file
int file_reader_new(const char *file_path, struct FileReader *fr);
#endif
file_writer.c
#include <stdio.h>
#include "file_writer.h"
void write (struct FileWriter *fw)
{
FILE *f = fopen(fw->file_path, "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "%s", fw->content);
fclose(f);
}
file_writer.h
#ifndef FILE_WRITER_H_
#define FILE_WRITER_H_
typedef struct FileWriter
{
char *file_path;
char *content;
int *error;
} FileWriter;
#endif
Can you help me ? Thanks!
struct FileReader *fr = malloc(sizeof(struct FileReader));
There is no need to do this. All you need is this:
struct FileReader fr;
Same here:
struct FileWriter fw;
Then just pass the address of these variables to the requisite function(s).
Note this was not given to you as an answer, only as a comment to clean up your code a bit to remove extraneous calls to the heap. It just so happens that the real problem exists elsewhere, and what you're seeing here is undefined behavior in full glory.
I am not sure how are you reading from the file, character by character or block, but anyhow ,
since you update the read data in content buffer, and store the address of content buffer inside file_reader_new() into variable fr->content and immediately releasing the memory will end up loosing the data you read. and lead to condition called Dangling pointer
Dangling pointer
( a pointer variable, which points to a released memory )
that's why its always advised to set the pointer variable after releasing to NULL. Dereferencing a dangling pointer is will lead to Segmentation fault or undefined behavior in some scenarios.
Also, since all you member variables of struct are pointers its better to initialize them to NULL.
you can use calloc to initialize all the variables in a struct, instead of malloc to initialize all the members to NULL, if you are going with dynamic allocation. which goes for string also.
Here is an issue that I see:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content); /* <-- Danger */
You do this in your file_reader_new function. You then call show_file_reader_values and in that function, you're accessing content:
printf("content:\n%s\n", fr->content);
Since you called free() on the content, that pointer no longer points to valid memory, thus undefined behavior occurs.
The fix is to allocate space on fr for the content and copy the characters of content to this space, or simply not call free on content.
So either do this:
fr->content = malloc(i + 1);
strcpy(fr->content, content);
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
or this:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* No call to free(content) done */

Disassemble HTTP Response (C)

In continuation of this question I ask the following question.
I've managed to read and understand what D.Shawley has recommended and I already finished a lot of work. But a problem occured to me again. I've managed to get the Content-Length of the page out of the HTTP response, but now I'm experiencing some problems with getting the length of the HTTP response header. As I understand from the RFC 2616 document, a response header can be preceded with several CRLFs and must be followed by one or more CRLFs. Now I'm heaving trouble with determining the end of the response header.
I've came up with the following files:
IEFDowner.h
/*
* IEFDowner.h
* Downer
*
* Created by ief2 on 2/08/10.
* Copyright 2010 ief2. All rights reserved.
*
* http://developerief2.site11.com
*
*/
#include <stdio.h> /* snprintf() */
#include <sys/socket.h> /* SOCKET */
#include <netdb.h> /* struct addrinfo */
#include <stdlib.h> /* exit() */
#include <string.h> /* memset(), strlen(), strcpy(), strstr() */
#include <errno.h> /* errno */
#include <unistd.h> /* close() */
enum _IEFDownerErrorType {
IEFNoError,
IEFGAIError, /* Use gai_strerror() to get the error message */
IEFConnectError, /* Failed to connect with the socket */
IEFSendError, /* Use strerror() to get the error message */
IEFReceiveError /* Error with recv() */
};
typedef enum _IEFDownerErrorType IEFDownerErrorType;
/*
Requests the data from the host at the given path thru the given protocol.
PAREMTERS
- host
The host to connect to.
- filepath
The path to the file which to download from the host.
- buffer
A buffer to fill with the received data
- maxSize
The maximum size of the buffer
- receivedBytes
The amount of received bytes
- errorType
The type of error received. See the header file for more info (enum _IEFDownerErrorType)
RETURN VALUE
The function returns 0 if it succeeded or another code if it failed.
*/
int
IEFDownerHTTPDownload(const char *host,
const char *filepath,
void *buffer,
unsigned long maxSize,
long *receivedBytes,
IEFDownerErrorType *errorType);
/*
Returns a pointer to a structure containing the IP4 or IP6 addresss.
PARAMETERS
- sa
A pointer to a structure of sockaddr.
RETURN VALUE
Returns a pointer to a structure of the type sockaddr_in or the type sockaddr_in6.
*/
void *
IEFDownerGetInAddr(struct sockaddr *sa);
/*
Gets the content-length information out of an HTTP response header.
PARAMETERS
- httpHeader
The null terminated response.
- contentLength
Upon return it contains the content length.
RETURN VALUE
The function returns 0 if it succeeded or -1 if it did not.
*/
int
IEFDownerGetContentLengthOfPage(const char *httpHeader,
int *contentLength);
/*
Gets the string lenth of the header information
PARAMETERS
- received
The received header
- headerSize
Upon return contains the header length
RETURN VALUE
The function returns 0 if it succeeded. If there was no header information found, it returns -1.
DISCUSSION
The header size includes the trailing CRLF's behind the header data.
All empty CRLF's are included until a non-empty line is met.
If there're zero empty lines after the first non empty line, the header information was not found.
*/
int
IEFDownerGetSizeOfHeader(const char *received,
int *headerSize);
IEFDowner.c
/*
* IEFDowner.c
* Downer
*
* Created by ief2 on 2/08/10.
* Copyright 2010 ief2. All rights reserved.
*
* http://developerief2.site11.com
*
*/
#include "IEFDowner.h"
int
IEFDownerHTTPDownload(const char *host, const char *filepath, void *buffer, unsigned long maxSize, long *rB, IEFDownerErrorType *errorType) {
int status; // contains returned statuses
int sockfd; // the socket file descriptor
struct addrinfo *infos; // linked list
struct addrinfo hints; // hints to getaddrinfo()
struct addrinfo *p; // used in the loop to get valid addrinfo
long receivedBytes; // the received bytes
unsigned requestLength; // the length of the request
char *request; // the http request
// GET ADDRESS INFO
// fill hints
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
// getaddrinfo
status = getaddrinfo(host,
"80",
&hints,
&infos);
if(status != 0) {
if(errorType) *errorType = IEFGAIError;
return status;
}
// FIND FIRST VALID SOCKET
for(p = infos; p != NULL; p = p->ai_next) {
// create
sockfd = socket(p->ai_family,
p->ai_socktype,
p->ai_protocol);
if(sockfd == -1)
continue;
// try to connect
status = connect(sockfd,
p->ai_addr,
p->ai_addrlen);
if(status == -1) {
close(sockfd);
continue;
}
break;
}
// no valid socket found
if(p == NULL) {
if(errorType) *errorType = IEFConnectError;
return status;
}
// GET RID OF INFOS
freeaddrinfo(infos);
// SEND HTTP REQUEST
// calculate request length and make
requestLength = strlen("GET ") + strlen(filepath) + strlen(" HTTP\1.0\n") + strlen("Host: ") + strlen(host) + strlen(":80\n\n") + 1;
request = malloc(sizeof(char) * requestLength);
snprintf(request, requestLength, "GET %s HTTP\1.0\nHost: %s:80\n\n", filepath, host);
// send
status = send(sockfd,
request,
requestLength - 1,
0);
if(status == -1) {
if(errorType) *errorType = IEFSendError;
close(sockfd);
return errno;
}
// RECEIVE DATA
receivedBytes = recv(sockfd,
buffer,
maxSize,
0);
if(receivedBytes == -1 || receivedBytes == 0) {
if(errorType) *errorType = IEFReceiveError;
close(sockfd);
return receivedBytes;
}
// SET POINTERS
if(errorType) *errorType = IEFNoError;
if(rB) *rB = receivedBytes;
return 0;
}
void *
IEFDownerGetInAddr(struct sockaddr *sa) {
// IP4
if(sa->sa_family == AF_INET)
return &(((struct sockaddr_in *) sa)->sin_addr);
// IP6
return &(((struct sockaddr_in6 *) sa)->sin6_addr);
}
int
IEFDownerGetContentLengthOfPage(const char *httpHeader, int *contentLength) {
register int i;
int length;
char *next;
char *completeHeader;
char *header;
char *fieldName;
// MAKE HEADER MUTABLE
completeHeader = malloc(sizeof(char) * (strlen(httpHeader) + 1));
strcpy(completeHeader, httpHeader);
header = completeHeader;
// SEARCH FOR LINE
// loop for all lines
next = header;
do {
header = next;
// replace newline
next = strstr(header, "\n");
if(next == NULL) {
free(header);
return -1;
}
*next = '\0';
for(i = 0; i != strlen("\n"); i++)
next++;
} while (strcasestr(header, "Content-Length:") == NULL);
// SCAN INTEGER
fieldName = strcasestr(header, "Content-Length:");
for(i = 0; i != strlen("Content-Length:"); i++)
fieldName++;
sscanf(fieldName, "%d", &length);
if(contentLength) *contentLength = length;
free(completeHeader);
return 0;
}
int
IEFDownerGetSizeOfHeader(const char *received, int *headerSize) {
int length;
int receivedLength;
char *next;
char *completeHeader;
char *header;
char *checkChar;
int firstNonEmptyLineFound;
int emptiesFound;
// MAKE HEADER MUTABLE
completeHeader = malloc(sizeof(char) * (strlen(received) + 1));
strcpy(completeHeader, received);
header = completeHeader;
// SEARCH FOR FIRST NON EMPTY LINE
receivedLength = strlen(header);
firstNonEmptyLineFound = 0;
for(next = header; *next != (char)NULL; next++) {
printf("%c",*next);
if(*next != '\n' && *next != '\r') {
firstNonEmptyLineFound = 1;
printf("\nFirst Non Empty Found\n\n");
next++;
break;
}
}
if(firstNonEmptyLineFound == 0) {
free(completeHeader);
return -1;
}
// SEARCH FOR FIRST EMPTY LINE
emptiesFound = 0;
for(; *next != (char)NULL; next++) {
checkChar = next;
printf("%c", *checkChar);
if(*checkChar == '\n' || *checkChar == '\r') {
checkChar++;
printf("%c", *checkChar);
if(*checkChar == '\n' || *checkChar == '\r') {
emptiesFound = 1;
printf("Empty Line Found\n\n");
break;
}
}
}
if(emptiesFound == 0) {
free(completeHeader);
return -1;
}
// GET END OF HEADER
for(; *next != (char)NULL; next++) {
printf("%c", *next);
if(*next != '\n' && *next != '\r') {
printf("End of header found");
break;
}
}
// INSERT NULL
*next == '\0';
length = strlen(header);
if(headerSize) *headerSize = length;
free(completeHeader);
return 0;
}
main.c
#include <stdio.h>
#include <stdarg.h>
#include "IEFDowner.h"
#define SERVERNAME "developerief2.site11.com"
#define PROTOCOL "80"
#define FILENAME "http://developerief2.site11.com/welcome/welcome.php"
#define MAXHEADERSIZE (1024*1024)
#define DESTFILE "/Users/ief2/Desktop/file.png"
void errorOut(int status, const char *format, ...);
int main (int argc, const char * argv[]) {
int status; // return status
void *headerData; // header data
int headerSize; // size of header
long rB; // received bytes
int pageSize; // size of bytes of page
// GET PAGE SIZE
// get data
headerData = malloc(1024);
status = IEFDownerHTTPDownload(SERVERNAME,
FILENAME,
(void *)headerData,
1024 - 1,
&rB, NULL);
if(status != 0)
errorOut(status, "An error occured while downloading header info\n");
// null terminate data
((char *)headerData)[rB] = '\0';
// get size
status = IEFDownerGetContentLengthOfPage((const char *)headerData, &pageSize);
if(status != 0)
errorOut(status, "An error occured while retreiving page size\n");
printf("Page Size: %d\n", pageSize);
printf("---------------------\n%s\n---------------------\n", headerData);
// CALCULATE HEADER SIZE
status = IEFDownerGetSizeOfHeader(headerData, &headerSize);
if(status != 0)
errorOut(status, "An error occured while getting the header size\n");
printf("Header Size: %d\n", headerSize);
return 0;
}
void errorOut(int status, const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(status);
}
The result I'm getting is not correct. I'm getting the end of the response after the first line already:
[Session started at 2010-08-03 21:32:47 +0000.]
Page Size: 3600
---------------------
HTTP/1.1 200 OK
Date: Tue, 03 Aug 2010 19:32:44 GMT
Server: Apache
X-Powered-By: PHP/5.2.11
Content-Length: 3600
Connection: close
Content-Type: text/html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en">
<!-- HEAD -->
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-16" />
<meta name="description" content="A site containing quality freeware for Mac OS X Tiger and newer. All applications are made by a 14 year old developer who masters AppleScript Studio, Objective-C, HTML, PHP, CSS and JavaScript." />
<meta name="keywords" content="free, freeware, mac os x, 10, tiger, leopard, mac os x, young, developer, freeware, AppleScript, Studio, Xcode, Objective-C, Cocoa" />
<title>Free OSX Software :: Welcome</title>
<!-- Shared Styles -->
<link rel="stylesheet" href="../site-style/styles.css" type="text/css" media="screen" title="no title" charset="utf-8" />
</head>
<!-- PAGE CONTENTS -->
<body>
---------------------
H
First Non Empty Found
TTP/1.1 200 OK
Empty Line Found
DEnd of header foundHeader Size: 1023
The Debugger has exited with status 0.
I hope somebody can help me,
ief2
It seems I have to read things better people write. Due to the previous question I should have already known that the new line in the HTTP responses are two characters: Carriage Return and a Line Feed ("\r\n"), so I should do a string compare.
New Code
int
IEFDownerGetSizeOfHeader(const char *received, int *headerSize) {
int length;
int receivedLength;
char *next;
char *completeHeader;
char *header;
char *checkChar;
int firstNonEmptyLineFound;
int emptiesFound;
// MAKE HEADER MUTABLE
completeHeader = malloc(sizeof(char) * (strlen(received) + 1));
strcpy(completeHeader, received);
header = completeHeader;
// SEARCH FOR FIRST NON EMPTY LINE
receivedLength = strlen(header);
firstNonEmptyLineFound = 0;
for(next = header; *next != (char)NULL; next++) {
if(strncmp(next, "\r\n", 2) != 0) {
firstNonEmptyLineFound = 1;
next++;
break;
}
}
if(firstNonEmptyLineFound == 0) {
free(completeHeader);
return -1;
}
// SEARCH FOR FIRST EMPTY LINE
emptiesFound = 0;
for(; *next != (char)NULL; next++) {
checkChar = next;
if(strncmp(checkChar, "\r\n", 2) == 0) {
checkChar++;
checkChar++;
if(strncmp(checkChar, "\r\n", 2) == 0) {
emptiesFound = 1;
next = checkChar;
break;
}
}
}
if(emptiesFound == 0) {
free(completeHeader);
return -1;
}
// GET END OF HEADER
for(; *next != (char)NULL; next++) {
if(strncmp(next, "\r\n", 2) != 0) {
break;
}
next++;
}
// INSERT NULL
*next = '\0';
length = strlen(header);
if(headerSize) *headerSize = length;
free(completeHeader);
return 0;
}
I hope this can be useful to some people,
ief2

Resources