On 28 Feb., 13:44, Mark Bluemel <mark_blue...@pobox.comwrote:
thomas.mer...@gmx.at wrote:
Hello
Recently I discovered some problem. I have some C code
which determines how many bytes are available in a
file.
[snip]
The code works for normal files under
windows and linux.
[snip]
When I open a file with _popen I get a different result:
- Under linux the tell() of step 1 returns -1 which means
the file is not seekable. I can recognice this situation
and react accordingly (I cannot malloc the buffer beforehand.
Instead I malloc a smaller buffer which is realloced until
all bytes are read).
I hope you don't grow it a byte at a time :-)
Actually I grow it in steps of 4096.
- Under windows the tell() of step 1 returns 0 which
means the file is seekable and is currently at position 0.
The other calls of fseek() and ftell() succeed also and
indicate that the number of available bytes is 0.
Therefore my program thinks that there are no bytes
available in the file opened with _popen.
The information that it is a file opened with _popen is
not available at that place in my program.
Could you consider making it available, by providing a wrapper
mechanism? (That would probably be my favoured approach, rather
than looking for platform specifics...)
A simplified version of the function using this functionality
is (please don't start nitpicking):
-----------------------------------------------
#include "stdlib.h"
#include "stdio.h"
#define READ_BLOCK_SIZE 4096
#define SIZ_STRI(len) ((sizeof(struct stristruct) - \
sizeof(unsigned char)) + (len) * sizeof(unsigned char))
typedef struct stristruct {
unsigned long int size;
unsigned char mem[1];
} *stritype;
stritype filGets (FILE *aFile, long length)
{
long current_file_position;
unsigned long int bytes_requested;
unsigned long int bytes_there;
unsigned long int read_size_requested;
unsigned long int block_size_read;
unsigned long int allocated_size;
unsigned long int result_size;
unsigned char *memory;
stritype resized_result;
stritype result;
/* filGets */
if (length < 0) {
result = NULL;
} else {
bytes_requested = (unsigned long int) length;
allocated_size = bytes_requested;
result = (stritype) malloc(SIZ_STRI(allocated_size));
if (result == NULL) {
/* Determine how many bytes are available in aFile */
if ((current_file_position = ftell(aFile)) != -1) {
fseek(aFile, 0, SEEK_END);
bytes_there = (ftell(aFile) - current_file_position);
fseek(aFile, current_file_position, SEEK_SET);
/* Now we know that bytes_there bytes are available
in aFile */
if (bytes_there < bytes_requested) {
allocated_size = bytes_there;
result = (stritype) malloc(SIZ_STRI(allocated_size));
if (result == NULL) {
return(NULL);
} /* if */
} else {
return(NULL);
} /* if */
} /* if */
} /* if */
if (result != NULL) {
/* We have allocated at least as many bytes as
are available in the file */
result_size = (unsigned long int) fread(result->mem, 1,
(size_t) allocated_size, aFile);
} else {
/* We do not know how many bytes are avaliable therefore we
read blocks of READ_BLOCK_SIZE until we reach EOF */
allocated_size = READ_BLOCK_SIZE;
result = (stritype) malloc(SIZ_STRI(allocated_size));
if (result == NULL) {
return(NULL);
} else {
read_size_requested = READ_BLOCK_SIZE;
if (read_size_requested bytes_requested) {
read_size_requested = bytes_requested;
} /* if */
block_size_read = fread(result->mem, 1,
read_size_requested, aFile);
result_size = block_size_read;
while (block_size_read == READ_BLOCK_SIZE &&
result_size < bytes_requested) {
allocated_size = result_size + READ_BLOCK_SIZE;
resized_result = (stritype)
realloc(result, SIZ_STRI(allocated_size));
if (resized_result == NULL) {
free(result);
return(NULL);
} else {
result = resized_result;
memory = (unsigned char *) result->mem;
read_size_requested = READ_BLOCK_SIZE;
if (result_size + read_size_requested >
bytes_requested) {
read_size_requested = bytes_requested - result_size;
} /* if */
block_size_read = fread(&memory[result_size], 1,
read_size_requested, aFile);
result_size += block_size_read;
} /* if */
} /* while */
} /* if */
} /* if */
result->size = result_size;
if (result_size < allocated_size) {
resized_result = (stritype)
realloc(result, SIZ_STRI(result_size));
if (resized_result == NULL) {
free(result);
return(NULL);
} else {
result = resized_result;
} /* if */
} /* if */
} /* if */
return(result);
} /* filGets */
-------------------------------------------
The function _popen() is not a standard function, but popen()
is. Btw.: Under windows I use MinGW and there the function
is also popen(). The problem stays open:
if you open a file with popen() (MinGW probably also cygwin)
under windows and you do a ftell() or fseek() you just
succeed as if it is an empty file. If you do the same in
linux the ftell() and fseek() functions return -1 which
indicate that the file is not seekable.
If someone has an idea: Please help.
Greetings Thomas Mertes
Seed7 Homepage:
http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.