[英]C Systems Program - Read/Write Issues During Copy
I am coding up a C program that extracts from a standard UNIX archive ar and creates the files it stores. 我正在编写一个C程序,它从标准的UNIX存档中提取并创建它存储的文件。
Here is an example of what an ar looks like if I open it in vim: 这是一个例子,如果我在vim中打开它会是什么样的:
!<arch>
yo 1382105439 501 20 100644 10 `
test1 lol
yo2 1382105444 501 20 100644 10 `
test2 lol
...where "test1 lol" and "test2 lol" are the contents of each file, "yo" and "yo2" are two different file names, and the rest is metadata stored in a format corresponding to the standard ar.h (read more on it here: http://www.lehman.cuny.edu/cgi-bin/man-cgi?ar.h+3 ) ...其中“test1 lol”和“test2 lol”是每个文件的内容,“yo”和“yo2”是两个不同的文件名,其余的是以对应于标准ar.h的格式存储的元数据(在这里阅读更多内容: http : //www.lehman.cuny.edu/cgi-bin/man-cgi?ar.h + 3 )
Anyway, I am still in the process of writing out the function but here is what I have so far: 无论如何,我仍在编写函数的过程中,但这是我到目前为止所拥有的:
static void extract_files (int argc, char *argv[])
{
int fd;
int new_file_fd;
int num_read = 0;
int new_file_size;
struct ar_hdr current_header;
char name_buffer[16];
char date_buffer[12];
char uid_buffer[6];
char gid_buffer[6];
char mode_buffer[8];
char size_buffer[10];
char fmag_buffer[2];
// grab the fd #
fd = open(argv[2], O_RDWR | O_CREAT, 0666);
// go to the first header
lseek(fd, SARMAG, SEEK_CUR);
// store the number of bits read in a struct current_header
// until its size equal to the size of the entire
// header, or in other words, until the entire
// header is read
while ((num_read = read(fd, (char*) ¤t_header,
sizeof(struct ar_hdr))) == sizeof(struct ar_hdr))
{
// scans the current string in header and stores
// in nameStr array
sscanf(current_header.ar_name, "%s", name_buffer);
sscanf(current_header.ar_date, "%s", date_buffer);
sscanf(current_header.ar_uid, "%s", uid_buffer);
sscanf(current_header.ar_gid, "%s", gid_buffer);
int mode;
sscanf(current_header.ar_mode, "%o", &mode);
sscanf(current_header.ar_size, "%s", size_buffer);
int size = atoi(size_buffer);
sscanf(current_header.ar_fmag, "%s", fmag_buffer);
// Create a new file
new_file_fd = creat(name_buffer, mode);
// Grab new file size
new_file_size = atoi(size_buffer);
int io_size; // buffer size
char buff[size];
int read_cntr = 0;
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
if (read_cntr > new_file_size)
break;
write (new_file_fd, buff, new_file_size);
}
close(new_file_fd);
printf("%s\n", name_buffer);
printf("%s\n", date_buffer);
printf("%s\n", uid_buffer);
printf("%s\n", gid_buffer);
printf("%s\n", mode_buffer);
printf("%s\n", size_buffer);
printf("%s\n", fmag_buffer);
/* Seek to next header. */
lseek(fd, atoi(current_header.ar_size) + (atoi(current_header.ar_size)%2), SEEK_CUR);
}
}
The issue I am having lies in the second while loop in the above code: 我遇到的问题在于上面代码中的第二个while循环:
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
if (read_cntr > new_file_size)
break;
write (new_file_fd, buff, new_file_size);
}
For some reason, the files written in this while loop don't run to the length specified by write. 由于某种原因,在此while循环中写入的文件不会运行到write指定的长度。 The third argument for the standard read()/write() should be the number of bytes to write.
标准read()/ write()的第三个参数应该是要写入的字节数。 For some reason though, my code results in the entire archive being read in and written into the first file.
但是出于某种原因,我的代码导致整个存档被读入并写入第一个文件。
If I open up the resulting "yo" file, I find the entire archive file has been written to it 如果我打开生成的“yo”文件,我发现整个存档文件已写入其中
test1 lol
yo2 1382105444 501 20 100644 10 `
test2 lol
instead of terminating after reading 10 bytes and giving the expected outcome "test1 lol". 在读取10个字节并给出预期结果“test1 lol”之后,而不是终止。
I can also confirm that the "new_file_size" value is indeed 10. So my question is: what am I reading wrong about this while loop? 我还可以确认“new_file_size”值确实为10.所以我的问题是:我在读取循环时读错了什么?
Note: Expected input would be a command line argument that looks something like: ./extractor.c -x name_of_archive_file 注意:预期输入将是命令行参数,类似于:./ extractor.c -x name_of_archive_file
The only relevant information I think I need to deal with in this function is the name of the archive file which I get the fd for at the beginning of extract_files. 我认为我需要在此函数中处理的唯一相关信息是存档文件的名称,我在extract_files的开头获取了fd。
Added: Misc -- the output from when this is run: 补充:杂项 - 运行时的输出:
yo
1382105439
501
20
X
10
`
As you can see, it never sees the yo2 file or prints out its header because it gets written to "yo" before that can happen...because of this stray while loop :( 正如你所看到的,它永远不会看到yo2文件或打印出它的标题,因为它会被写入“yo”之前可能发生...因为这个流浪而循环:(
你的while()
循环应该在它之后有大括号( { ... }
),否则你只是在不做任何其他事情的情况下递增read_cntr
。
You read a value, size_buffer, and assign it to size and new_file_size, you also create a buffer[size]
of that same size, 你读取一个值size_buffer,并将其分配给size和new_file_size,你还创建一个相同大小的
buffer[size]
,
int size = atoi(size_buffer);
sscanf(current_header.ar_fmag, "%s", fmag_buffer);
//...
new_file_size = atoi(size_buffer);
//...
char buff[size];
Read returns a ssize_t count of bytes in range [0..new_file_size]
, which you set into io_size, realize that read(2) may return < new_file_size
bytes, which is why you need the while loop. Read返回范围
[0..new_file_size]
的ssize_t字节数,你设置为io_size,意识到read(2)可能return < new_file_size
字节,这就是你需要while循环的原因。 So you need to write everything you have read, until you reach your write limit. 因此,您需要编写已阅读的所有内容,直到达到写入限制为止。 I have made some comments to guide you.
我已经做了一些评论来指导你。
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
//perhaps you mean read_cntr += io_size;
//you probably mean to write io_size bytes here, regardless
//write(new_file_fd, buff, io_size);
if (read_cntr > new_file_size) //probably you want >= here
break;
//you may have broke before you write...
write (new_file_fd, buff, new_file_size);
}
A more typical idiom for this copy would be something where you pick a read/write buffer size, say 4*1024 (4K)
, 16*1024 (16K)
, etc, and read that blocksize, until you have less than that blocksize remaining; 这个副本的一个更典型的习惯用法是你选择一个读/写缓冲区大小,比如
4*1024 (4K)
, 16*1024 (16K)
等,并读取块大小,直到你剩下的块大小少于; for example, 例如,
//decide how big to make buffer for read()
#define BUFSIZE (16*1024) //16K
//you need min(
#define min(x,y) ( ((x)<(y)) ? (x) : (y) )
ssize_t fdreader(int fd, int ofd, ssize_t new_file_size )
{
ssize_t remaining = new_file_size;
ssize_t readtotal = 0;
ssize_t readcount;
unsigned char buffer[BUFSIZE];
for( ; readcount=read(fd,buffer,min(sizeof(buffer),remaining)); )
{
readtotal += readcount;
if( readcount > remaining ) //only keep remaining
readcount = remaining;
write( ofd, buffer, readcount);
remaining -= readcount;
if( remaining <= 0 ) break; //done
}
return readtotal;
}
Try this, 尝试这个,
#include<stdio.h>
#include<stdlib.h>
void usage(char*progname)
{
printf("need 2 files\n");
printf("%s <infile> <outfile>\n",progname);
}
//decide how big to make buffer for read()
#define BUFSIZE (16*1024) //16K
//you need min(
#define min(x,y) ( ((x)<(y)) ? (x) : (y) )
ssize_t fdreader(int fd, int ofd, ssize_t new_file_size )
{
ssize_t remaining = new_file_size;
ssize_t readtotal = 0;
ssize_t readcount;
unsigned char buffer[BUFSIZE];
for( ; readcount=read(fd,buffer,min(sizeof(buffer),remaining)); )
{
readtotal += readcount;
if( readcount > remaining ) //only keep remaining
readcount = remaining;
write( ofd, buffer, readcount);
remaining -= readcount;
if( remaining <= 0 ) break; //done
}
return readtotal;
}
int main(int argc,char**argv)
{
int i=0; /* the infamous 'i' */
FILE*infh;
FILE*outfh;
if( argc < 3 )
{
usage(argv[0]);
return 0;
}
printf("%s %s\n",argv[1],argv[2]); fflush(stdout);
if( !(infh=fopen(argv[1],"r")) )
{
printf("cannot open %s\n",argv[2]); fflush(stdout);
return(2);
}
if( !(outfh=fopen(argv[2],"w+")) )
{
printf("cannot open %s\n",argv[3]); fflush(stdout);
return(3);
}
int x = fdreader(fileno(infh), fileno(outfh), 512 );
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.