[英]Adapt code to copy/paste .zip and .tar.gzip files?
Introduction 介绍
I'm writing my own cp
program. 我正在编写自己的
cp
程序。 With the code I currently have I'm able to copy and paste files. 使用当前可用的代码,我可以复制和粘贴文件。
Code 码
char *buf;
int fd;
int ret;
struct stat sb;
FILE *stream;
/*opening and getting size of file to copy*/
fd = open(argv[1],O_RDONLY);
if(fd == -1)
{
perror("open");
return 1;
}
/*obtaining size of file*/
ret = fstat(fd,&sb);
if(ret)
{
perror("stat");
return 1;
}
/*opening a stream for reading/writing file*/
stream fdopen(fd,"rb");
if(!stream)
{
perror("fdopen");
return 1;
}
/*allocating space for reading binary file*/
buf = malloc(sb.st_size);
/*reading data*/
if(!fread(buf,sb.st_size,1,stream))
{
perror("fread");
return 1;
}
/*writing file to a duplicate*/
fclose(stream);
stream = fopen("duplicate","wb");
if(!fwrite(buf,sb.st_size,1,stream))
{
perror("fwrite");
return 1;
}
fclose(stream);
close(fd);
free(buf);
return 0;
The problem 问题
I'm unable to copy and paste .zip files and .tar.gz files. 我无法复制和粘贴.zip文件和.tar.gz文件。 If i alter the code and give an extension such as 'duplicate.zip' (assuming im copying a zip file) such as .zip and then try and copy a .zip file everything is copied, however the new duplicated file does not act like a zip file and when i use cat it outputs nothing and this error when i attempt to unzip it anyway:
如果我更改代码并给出扩展名,例如“ duplicate.zip”(假设我正在复制一个zip文件),然后尝试复制一个.zip文件,则所有内容都会被复制,但是新的重复文件却不会像一个zip文件,当我使用cat时,它什么也不会输出,而无论如何,我尝试将其解压缩时都会出现此错误:
End-of-central-directory signature not found.
找不到中央目录末尾签名。 Either this file is not a zipfile, or it constitutes one disk of a multi-part archive.
该文件不是zip文件,或者它是一个多部分归档文件的一个磁盘。 In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive.
在后一种情况下,将在此存档的最后一个磁盘上找到中央目录和zipfile注释。
So how do i go about copying zip and pasting zip files and also .tar.gz files. 因此,我该如何复制zip并粘贴zip文件以及.tar.gz文件。 Any pointers will be helpful, thanks in advance.
任何指点都会有所帮助,在此先感谢。
You are using malloc()
incorrectly. 您使用的
malloc()
错误。 You want to allocate sb.st_size
bytes. 您要分配
sb.st_size
字节。
malloc(sb.st_size * sizeof buf)
should be 应该
malloc(sb.st_size)
The use of fread()
is dubious and you are throwing away the result of fread()
. fread()
的使用是可疑的,您将丢弃fread()
的结果。 Instead of 代替
if(!fread(buf,sb.st_size,1,stream))
you should have 你应该有
size_t num_bytes_read = fread (buf, 1, sb.st_size, stream); if (num_bytes_read < sb.st_size)
You are using strlen()
incorrectly. 您使用的
strlen()
错误。 The content of buf
is not guaranteed to be a string; buf
的内容不能保证是字符串。 and anyway you already know how many bytes you have in buf
: sb.st_size
. 无论如何, 您已经知道
buf
有多少字节: sb.st_size
。 (Because if fread()
returned a smaller number of bytes read you got angry and terminated the process.) So instead of (因为如果
fread()
返回的字节数较少,您会生气并终止了该过程。)
fwrite(buf,strlen(buf),1,stream)
you should have 你应该有
fwrite (buf, 1, sb.st_size, stream)
In addition to AlexP's notes ... 除了AlexP的注释 ...
/*obtaining size of file*/
ret = fstat(fd,&sb);
if(ret)
{
perror("stat");
return 1;
}
// ...some code...
/*allocating space for reading binary file*/
buf = malloc(sb.st_size);
/*reading data*/
if(!fread(buf,sb.st_size,1,stream))
{
perror("fread");
return 1;
}
You have a race condition here. 您在这里有比赛条件 。 If the file size changes between your
fstat
call and malloc
or fread
you will read too much or too little of the file. 如果文件大小在
fstat
调用和malloc
或fread
之间变化,则将读取过多或过少的文件。
Fixing this leads us to the next issue, you're slurping the entire file into memory. 解决此问题将导致我们遇到下一个问题,您正在将整个文件插入内存。 While this might work for small files, it is extremely inefficient with your memory on large ones.
尽管这可能适用于小文件,但是对于大文件来说,内存效率极低。 For very large files it might be too large for a single
malloc
, and you're not checking if your malloc
succeeds. 对于非常大的文件,对于单个
malloc
来说可能太大了,并且您不检查malloc
成功。
Instead, read and write the file a piece at a time. 而是一次一次读写文件。 And read until there isn't any more to read.
并阅读,直到没有更多可阅读的内容为止。
uint8_t *buffer[4096]; // 4K buffer
size_t num_read;
while( (num_read = fread(buffer, sizeof(uint8_t), sizeof(buffer), in)) != 0 ) {
if( fwrite( buffer, sizeof(uint8_t), num_read, out ) == 0 ) {
perror("fwrite");
}
}
This avoids the race condition by not having to call fstat
in the first place. 这样就不必首先调用
fstat
来避免争用情况。 And it avoids allocating a potentially enormous hunk of memory. 而且它避免了分配潜在的巨大内存。 Instead it can all be done on the stack .
相反,它可以全部在堆栈上完成。
I've used uint8_t
to get a hunk of bytes. 我用过
uint8_t
来获取大量字节。 It's a standard fixed width integer type from stdint.h . 这是来自stdint.h的标准固定宽度整数类型 。 You can also use
unsigned char
to read bytes, and that's probably what uint8_t
really is, but uint8_t
makes it explicit. 您也可以使用
unsigned char
读取字节,这可能正是uint8_t
,但是uint8_t
使其明确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.