我想在这里扩展这个问题:
C theory on how to extract files from an archived file
它讨论如何获取已归档的文件并将其解压缩并将其返回到文件表单,而不使用命令ar -x
。
答案中的算法说明了以下几个步骤:
有人可以给我一些关于在这些步骤中使用的功能的提示吗?我真的不知道它在第2步中谈论的是什么结构。
答案 0 :(得分:0)
标题包含有关文件的元数据,包括标题的大小,不包括标题大小数据,文件名和由/分隔的相应文件大小。我使用/作为分隔符,因为它们不会出现在Linux简单文件名中,除非它是路径名。如果您打算包含路径名,则可以使用其他分隔符。
Body包含一个接一个附加的每个文件的内容。
以下是我的归档文件的格式。
我使用以下C结构来收集有关归档和提取的单个文件的元数据。
struct mdata
{
char name[255];
FILE *fp;
int size;
int nsize;
int ssize;
struct mdata *next;
};
我使用链表来包含文件元数据列表。
存档代码:./ archive file1 file2 archive1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BSIZE 2048
struct mdata
{
char name[255];
FILE *fp;
int size;
int nsize;
int ssize;
struct mdata *next;
};
struct mdata *mhead = NULL, *current = NULL;
int getsize(FILE *fp)
{
int size = 0;
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
return size;
}
int add(char *name)
{
FILE *fp;
char ntemp[255];
struct mdata *newm;
newm = (struct mdata *)malloc(sizeof(struct mdata));
strcpy(newm->name, name);
fp = fopen(name, "r+");
newm->fp = fp;
newm->size = getsize(fp);
newm->nsize = strlen(name);
sprintf(ntemp, "%d", newm->size);
newm->ssize = strlen(ntemp);
newm->next = NULL;
printf("File %s is being processed...\n", name);
if(mhead == NULL)
{
mhead = newm;
current = newm;
}
else
{
current->next = newm;
current = newm;
}
}
int preproc(int argc, char** argv)
{
int i;
for(i = 1; i <= argc-2; i++)
{
add(argv[i]);
}
}
int main(int argc, char** argv)
{
char block[BSIZE];
char stsize[5];
char shsize[100];
int rsize = 0;
int tnsize = 0, tssize = 0, hsize = 0, scount = 0;
struct mdata *ptr;
FILE *fpar, *fp;
//CREATE HEADER
printf("Pre-processing the files to collect meta data...\n");
preproc(argc, argv);
printf("Pre-processing completed.\n");
printf("Compiling header information.\n");
fpar = fopen(argv[argc-1], "w+");
ptr = mhead;
while(ptr != NULL)
{
tnsize += ptr->nsize;
tssize += ptr->ssize;
ptr = ptr->next;
scount +=2;
}
hsize = tnsize+tssize+scount+1;
printf("Total length of file names is %d\n", tnsize);
printf("Total length of file sizes is %d\n", tssize);
printf("Total size of header except file size is %d.\n", hsize);
sprintf(shsize, "%d/", hsize); //10 bytes of header size
fwrite(shsize, 1, strlen(shsize), fpar);
ptr = mhead;
while(ptr != NULL)
{
fwrite(ptr->name, 1, ptr->nsize, fpar);
fwrite("/", 1, 1, fpar);
sprintf(stsize, "%d", ptr->size);
fwrite(stsize, 1, ptr->ssize, fpar);
fwrite("/", 1, 1, fpar);
ptr = ptr->next;
}
printf("The header created and written to archieve file.\n");
//CREATE BODY
ptr = mhead;
while(ptr != NULL)
{
fp = ptr->fp;
while(rsize = fread(block, 1, sizeof(block), fp))
{
fwrite(block, 1, rsize, fpar);
}
ptr = ptr->next;
}
printf("Contents of all files written to archieve file.\n");
fclose(fpar);
return 0;
}
提取代码:./提取存档
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BSIZE 2048
struct mdata
{
char name[255];
FILE *fp;
int size;
int nsize;
int ssize;
struct mdata *next;
};
struct mdata *mhead = NULL, *current = NULL;
int min(int x, int y)
{
if(x < y) return x;
else return y;
}
int getsize(FILE *fp)
{
int size = 0;
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
return size;
}
int add(char *name, int size)
{
char ntemp[255];
struct mdata *newm;
newm = (struct mdata *)malloc(sizeof(struct mdata));
strcpy(newm->name, name);
newm->size = size;
newm->nsize = strlen(name);
sprintf(ntemp, "%d", newm->size);
newm->ssize = strlen(ntemp);
newm->next = NULL;
printf("File %s is being processed...\n", name);
if(mhead == NULL)
{
mhead = newm;
current = newm;
}
else
{
current->next = newm;
current = newm;
}
}
int readh(FILE *fp1)
{
int i = 0, j= 1 ;
int hsize = 0, size = 0;
int byte;
char shsize[50];
char name[255];
char ssize[50];
while((byte = fgetc(fp1))!='/')
{
shsize[i] = (char)byte;
i++;
}
shsize[i] = '\0';
hsize = atoi(shsize);
hsize += strlen(shsize);
printf("The total size of header is %d.\n", hsize);
printf("Contents starts at %dth byte.\n", hsize);
//COLLECT NAMES AND SIZES
j = strlen(shsize)+1;
while(j <= hsize-1)
{
i = 0;
while((byte = fgetc(fp1))!='/')
{
name[i++] = byte;
j++;
}
j++;
name[i] = '\0';
i = 0;
while((byte = fgetc(fp1))!='/')
{
ssize[i++] = byte;
j++;
}
j++;
ssize[i] = '\0';
size = atoi(ssize);
printf("File '%s' with size %d added to list.\n", name, size);
add(name, size);
printf("File '%s' processing completed.\n", name);
}
printf("File meta data collection successfully completed.\n");
}
int main(int argc, char** argv)
{
char block[BSIZE];
char stsize[5];
char shsize[100];
int rsize = 0;
int tnsize = 0, tssize = 0, hsize = 0, scount = 0;
int totsize = 0;
int unreadcount = 0;
struct mdata *ptr;
FILE *fpar, *fp;
//COLLECTING HEADER
printf("Opening file %s...\n", argv[1]);
fpar = fopen(argv[1], "r+");
if(fpar == NULL)
{
printf("Error opening file %s.\n", argv[1]);
}
readh(fpar);
ptr = mhead;
lseek(fpar, hsize+1, SEEK_SET);
while(ptr != NULL)
{
totsize = 0;
printf("Creating file %s...\n", ptr->name);
fp = fopen(ptr->name, "w+");
printf("Writing %d bytes of %s...\n", ptr->size, ptr->name);
unreadcount = ptr->size;
while(unreadcount > 0)
{
if(sizeof(block)>= unreadcount)
{
rsize = fread(block, 1, unreadcount, fpar);
}
else
{
rsize = fread(block, 1, sizeof(block), fpar);
}
unreadcount -= rsize;
totsize += rsize;
fwrite(block, 1, rsize, fp);
}
printf("Written %d bytes to file %s.\n", totsize, ptr->name);
ptr = ptr->next;
}
printf("Extraction completed.\n");
fclose(fpar);
return 0;
}