I'm having trouble with fseek. I have a file pointer that contains fetched HTTP data. I then let libmagic determine the mime type of the file and want to rewind afterwards:
char *mime_type (int fd)
{
char *mime;
magic_t magic;
magic = magic_open(MAGIC_MIME_TYPE);
magic_load(magic, MAGIC_FILE_NAME);
mime = (char*)magic_descriptor(magic, fd);
magic_close(magic);
return (mime);
}
int fetch_pull() {
fetch_state = fopen("/tmp/curl_0", "r");
if (fetch_state == NULL) {
perror("fetch_pull(): Could not open file handle");
return (1);
}
fd = fileno(fetch_state);
mime = mime_type(fd);
if (fseek(fetch_state, 0L, SEEK_SET) != 0) {
perror("fetch_pull(): Could not rewind file handle");
return (1);
}
if (mime != NULL && strstr(mime, "text/") != NULL) {
/* do things */
} else if (mime != NULL && strstr(mime, "image/") != NULL) {
/* do other things */
}
return (0);
}
This throws "fetch_pull(): Could not rewind file handle: Bad file descriptor". What is wrong?
/tmp/curl_0
is a pipe, isn't it? You cannot rewind a pipe. What's read is gone.
And you cannot combine FILE operations and file descriptor operations, since FILEs have an additional buffer, they read ahead.
If /tmp/curl_0
is a regular file, then open a file descriptor with open(const char *path, int oflag, ...)
. After invoking mime_type(fd)
, you can first rewind the stream, then wrap the file descriptor into FILE handle with fdopen(int fildes, const char *mode)
. Or just close the file descriptor and use the regular fopen()
afterwards:
int fd = open("/tmp/curl_0", O_RDONLY);
if (fd == -1) {
perror("Could not open file");
return -1;
}
char *mime = mime_type(fd);
/***** EITHER: */
close(fd);
FILE *file = fopen("/tmp/curl_0", "r");
/***** OR (the worse option!) */
if (lseek(fd, 0, SEEK_SET) == -1) {
perror("Could not seek");
return -1;
}
FILE *fdopen = fopen(fd, "r");
/***********/
if (!file) {
perror("Could not open file");
return -1;
}
/* do things */
fclose(file);