简体   繁体   English

修改代码以复制/粘贴.zip和.tar.gzip文件吗?

[英]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调用和mallocfread之间变化,则将读取过多或过少的文件。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM