다음은 기본을 구현하는 컷 다운 차단 솔루션입니다. 제한된 테스트, 제한된 오류 확인, 페더만큼 강력합니다. 모든 기능이 완벽하지는 않으며 많은 기능이 빠져 있습니다 (코드에서 fseeki64를 사용하고 여기에서 구현하는 경우). 그것은 내가 제안한 것처럼 퓨즈를 시도 할 것입니다. 그러나 다른 누군가가이 방법으로 이것을 원한다면 이것은 출발점 일 수 있습니다.
주요
#include <stdio>
#include "concat_streams.h"
int main(int argc, char*argv[])
{
char buf[16];
concat_streams_global_init('?');
FILE* file = fopen("file1?file2?file3?file4", "rb");
...
fseek(file, 12, SEEK_SET);
...
fread(buf, 1, 16, file);
...
fclose(file);
}
concat_streams.h
#define CONCAT_STREAMS_MAX 10 /*max number of concat streams*/
FILE*** concat_streams=NULL;
size_t** concat_streams_boundaries=NULL;
size_t* concat_streams_count=NULL;
size_t* concat_streams_selector=NULL;
size_t* concat_streams_tot_size=NULL;
char concat_streams_delim='?';
/*return index of stream if it is concat, CONCAT_STREAMS_MAX otherwise*/
int is_stream_concat(FILE* stream)
{
unsigned int index=0;
while(index<CONCAT_STREAMS_MAX)
{
if(concat_streams[index]!=NULL)
{
if(concat_streams[index][0]==stream)
break;
}
++index;
}
return index;
}
/*Initialise concat_stream store*/
void concat_streams_global_init(char delim_use)
{
concat_streams_delim=delim_use;
concat_streams=(FILE***) malloc(sizeof(FILE**)*CONCAT_STREAMS_MAX);
concat_streams_boundaries=(size_t**) malloc(sizeof(size_t*)*CONCAT_STREAMS_MAX);
concat_streams_count=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX);
concat_streams_selector=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX);
concat_streams_tot_size=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX);
memset(concat_streams, 0, sizeof(FILE**)*CONCAT_STREAMS_MAX);
memset(concat_streams_boundaries, 0, sizeof(size_t*)*CONCAT_STREAMS_MAX);
memset(concat_streams_count, 0, sizeof(size_t)*CONCAT_STREAMS_MAX);
memset(concat_streams_selector, 0, sizeof(size_t)*CONCAT_STREAMS_MAX);
memset(concat_streams_tot_size, 0, sizeof(size_t)*CONCAT_STREAMS_MAX);
}
/*The meat of fopen*/
FILE* concat_streams_init(char* files_question_delim, char * mode)
{
unsigned int concat_streams_next_set=0;
while(concat_streams_next_set<CONCAT_STREAMS_MAX)
{
if(concat_streams[concat_streams_next_set]==NULL)
break;
++concat_streams_next_set;
}
if(concat_streams_next_set==CONCAT_STREAMS_MAX)
return NULL;
char*files_question_delim_cpy=NULL;
unsigned int i=0;
while(files_question_delim[i]!=0)
{
if(files_question_delim[i]=='?')
++concat_streams_count[concat_streams_next_set];
++i;
}
++concat_streams_count[concat_streams_next_set];
files_question_delim_cpy=(char*)malloc(i);
memcpy(files_question_delim_cpy, files_question_delim, i);
concat_streams[concat_streams_next_set]=(FILE**)malloc(sizeof(FILE*)*concat_streams_count[concat_streams_next_set]);
concat_streams_boundaries[concat_streams_next_set]=(size_t*)malloc(sizeof(size_t)*(concat_streams_count[concat_streams_next_set]+1));
concat_streams_boundaries[concat_streams_next_set][0]=0;
char* next_file;
next_file=strtok(files_question_delim_cpy, "?");
while(next_file!=NULL)
{
concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]=fopen(next_file, "rb");
if(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]==NULL)
{
fclose_concat_streams(concat_streams[concat_streams_next_set][0]);
return NULL;/*fopen failed*/
}
fseek(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]], 0, SEEK_END);
concat_streams_boundaries[concat_streams_next_set][1+concat_streams_selector[concat_streams_next_set]] = concat_streams_boundaries[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]] + ftell(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]);
concat_streams_tot_size[concat_streams_next_set]+=ftell(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]);
rewind(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]);
++concat_streams_selector[concat_streams_next_set];
next_file=strtok(NULL, "?");
}
concat_streams_selector[concat_streams_next_set]=0;
free(files_question_delim_cpy);
return concat_streams[concat_streams_next_set][0];
}
FILE * fopen_concat_streams (char * filename, char * mode)
{
if(strchr(filename, '?')!=NULL)
return concat_streams_init(filename, mode);
else
return fopen(filename, mode);
}
/*only implemented origin==SEEK_SET*/
int fseek_concat_streams(FILE * stream, long int offset, int origin)
{
unsigned int i=0;
unsigned int index=is_stream_concat(stream);
if(index!=CONCAT_STREAMS_MAX)
{
switch(origin)
{
case SEEK_SET:
while(i<concat_streams_count[index])
{
if(offset>=concat_streams_boundaries[index][i] && offset<concat_streams_boundaries[index][i+1])
break;
++i;
}
if(i==concat_streams_count[index])
return 1;/*out of range*/
concat_streams_selector[index]=i;
return fseek(concat_streams[index][concat_streams_selector[index]], offset-concat_streams_boundaries[index][concat_streams_selector[index]], SEEK_SET);
default:
puts("error, Only SEEK_SET supported when using cat streams");
return 1;/*not implemented*/
}
}
else
return fseek(stream, offset, origin);/*just a normal file*/
}
long int ftell_concat_streams(FILE * stream)
{
unsigned int index=is_stream_concat(stream);
if(index!=CONCAT_STREAMS_MAX)
{
/*Found*/
return concat_streams_boundaries[index][concat_streams_selector[index]] + ftell(concat_streams[index][concat_streams_selector[index]]);
}
else
return ftell(stream);
}
int feof_concat_streams(FILE * stream)
{
unsigned int index=is_stream_concat(stream);
if(index!=CONCAT_STREAMS_MAX)
{
if(concat_streams_selector[index]==concat_streams_count[index])
return 1;/*EOF*/
else
return 0;
}
else
return feof(stream);
}
size_t fread_concat_streams (void * ptr, size_t size, size_t count, FILE * stream)
{
size_t mult=size*count;
size_t num_to_go=mult;
char* buffer=NULL;
unsigned int index=is_stream_concat(stream);
unsigned int num_read;
char* out_ptr=(char*)ptr;
if(index!=CONCAT_STREAMS_MAX)
{
if(concat_streams_selector[index]==concat_streams_count[index])
return 0;/*at eof*/
buffer=(char*)malloc(2048*4096);
while(num_to_go!=0)
{
num_read=fread(buffer, 1, num_to_go>=2048*4096?2048*4096:num_to_go, concat_streams[index][concat_streams_selector[index]]);
if(num_read != (num_to_go>=2048*4096?2048*4096:num_to_go))
{
if(feof(concat_streams[index][concat_streams_selector[index]])==0)
{
puts("EOF not set, read error");
memcpy(out_ptr, buffer, num_read);
out_ptr+=num_read;
num_to_go-=num_read;
free(buffer);
return mult-num_to_go;
}
else
{
rewind(concat_streams[index][concat_streams_selector[index]]);
++concat_streams_selector[index];
if(concat_streams_selector[index]==concat_streams_count[index])
{
memcpy(out_ptr, buffer, num_read);
out_ptr+=num_read;
num_to_go-=num_read;
free(buffer);
return mult-num_to_go;
}
else
rewind(concat_streams[index][concat_streams_selector[index]]);
}
}
memcpy(out_ptr, buffer, num_read);
out_ptr+=num_read;
num_to_go-=num_read;
}
free(buffer);
return mult;
}
else
return fread(ptr, size, count, stream);
}
size_t fwrite_concat_streams (const void * ptr, size_t size, size_t count, FILE * stream)
{
unsigned int index=is_stream_concat(stream);
if(index!=CONCAT_STREAMS_MAX)
{
puts("error, writing to cat_streams not supported");
return 0;
}
else
return fwrite(ptr, size, count, stream);
}
int fclose_concat_streams (FILE * stream)
{
unsigned int i=0;
unsigned int index=is_stream_concat(stream);
if(index!=CONCAT_STREAMS_MAX)
{
while(i<concat_streams_count[index])
{
fclose(concat_streams[index][i]);
++i;
}
free(concat_streams[index]);
concat_streams[index]=NULL;
free(concat_streams_boundaries[index]);
concat_streams_boundaries[index]=NULL;
concat_streams_count[index]=0;
concat_streams_selector[index]=0;
concat_streams_tot_size[index]=0;
}
else
return fclose(stream);
}
#define fseek(x, y, z) fseek_concat_streams(x, y, z)
#define fread(w, x, y, z) fread_concat_streams(w, x, y, z)
#define fwrite(w, x, y, z) fwrite_concat_streams(w, x, y, z)
#define fopen(x, y) fopen_concat_streams(x, y)
#define ftell(x) ftell_concat_streams(x)
#define feof(x) feof_concat_streams(x)
#define fclose(x) fclose_concat_streams(x)
예, '가상 파일'을 설명하는 좋은 방법입니다. 나는 구현의 중간에 있지만 상당히 오래갑니다. 나는 중요한 기능을 위해 많은 맞춤 코드를 작성하는데 조심 스럽다. 특히 가로 채기로 투명하다. 전용 라이브러리가 더 강력 할 것입니다. 불행하게도 고양이와 배관 할 수는 없지만 질문에서 설명했지만 분명하지 않을 수 있습니다. 답장을 보내 주셔서 감사 드리며 퓨즈 API를 제안 해 주시면 다음 내용을 읽으 실 수 있습니다 :) –
FUSE를 사용하여 구현하십시오. Python으로 간단한 파일 시스템을 작성할 수 있습니다. 그런 식으로 새로운 (위대한) 프로그래밍 언어를 배우고, 파일 시스템에 대해 배우고, 노력을 덜하면서 문제를 해결할 수 있습니다. 두 개의 자습서에 대한 링크를 추가했습니다. –