4646 */
4747static int
4848pad_to (struct archive * a , int fd , int can_lseek ,
49- size_t nulls_size , const char * nulls ,
50- int64_t target_offset , int64_t actual_offset )
49+ char * * nulls , int64_t target_offset , int64_t actual_offset )
5150{
51+ const size_t nulls_size = 16384 ;
5252 size_t to_write ;
5353 ssize_t bytes_written ;
5454
5555 if (can_lseek ) {
5656 actual_offset = lseek (fd ,
5757 target_offset - actual_offset , SEEK_CUR );
5858 if (actual_offset != target_offset ) {
59- archive_set_error (a , errno , "Seek error" );
59+ archive_set_error (a ,
60+ actual_offset == -1 ? errno : ARCHIVE_ERRNO_MISC ,
61+ "Seek error" );
6062 return (ARCHIVE_FATAL );
6163 }
6264 return (ARCHIVE_OK );
6365 }
66+ if (* nulls == NULL ) {
67+ * nulls = calloc (1 , nulls_size );
68+ if (* nulls == NULL ) {
69+ archive_set_error (a , errno , "Out of memory" );
70+ return (ARCHIVE_FATAL );
71+ }
72+ }
73+
6474 while (target_offset > actual_offset ) {
6575 to_write = nulls_size ;
6676 if (target_offset < actual_offset + (int64_t )nulls_size )
6777 to_write = (size_t )(target_offset - actual_offset );
68- bytes_written = write (fd , nulls , to_write );
78+ bytes_written = write (fd , * nulls , to_write );
6979 if (bytes_written < 0 ) {
7080 archive_set_error (a , errno , "Write error" );
7181 return (ARCHIVE_FATAL );
@@ -84,29 +94,27 @@ archive_read_data_into_fd(struct archive *a, int fd)
8494 const void * buff ;
8595 size_t size , bytes_to_write ;
8696 ssize_t bytes_written ;
97+ int64_t fd_offset ;
8798 int64_t target_offset ;
8899 int64_t actual_offset = 0 ;
89100 int can_lseek ;
90101 char * nulls = NULL ;
91- size_t nulls_size = 16384 ;
92102
93103 archive_check_magic (a , ARCHIVE_READ_MAGIC , ARCHIVE_STATE_DATA ,
94104 "archive_read_data_into_fd" );
95105
96106 can_lseek = (fstat (fd , & st ) == 0 ) && S_ISREG (st .st_mode );
97- if (!can_lseek ) {
98- nulls = calloc (1 , nulls_size );
99- if (!nulls ) {
100- r = ARCHIVE_FATAL ;
101- goto cleanup ;
102- }
107+ if (can_lseek ) {
108+ fd_offset = lseek (fd , 0 , SEEK_CUR );
109+ if (fd_offset == -1 )
110+ can_lseek = 0 ;
103111 }
104112
105113 while ((r = archive_read_data_block (a , & buff , & size , & target_offset )) ==
106114 ARCHIVE_OK ) {
107115 const char * p = buff ;
108116 if (target_offset > actual_offset ) {
109- r = pad_to (a , fd , can_lseek , nulls_size , nulls ,
117+ r = pad_to (a , fd , can_lseek , & nulls ,
110118 target_offset , actual_offset );
111119 if (r != ARCHIVE_OK )
112120 break ;
@@ -129,7 +137,7 @@ archive_read_data_into_fd(struct archive *a, int fd)
129137 }
130138
131139 if (r == ARCHIVE_EOF && target_offset > actual_offset ) {
132- r2 = pad_to (a , fd , can_lseek , nulls_size , nulls ,
140+ r2 = pad_to (a , fd , can_lseek , & nulls ,
133141 target_offset , actual_offset );
134142 if (r2 != ARCHIVE_OK )
135143 r = r2 ;
@@ -139,5 +147,15 @@ archive_read_data_into_fd(struct archive *a, int fd)
139147 free (nulls );
140148 if (r != ARCHIVE_EOF )
141149 return (r );
142- return (ARCHIVE_OK );
150+ r = ARCHIVE_OK ;
151+ if (can_lseek ) {
152+ int64_t offset = lseek (fd , 0 , SEEK_CUR );
153+ if (offset - fd_offset != actual_offset ) {
154+ archive_set_error (a ,
155+ offset == -1 ? errno : ARCHIVE_ERRNO_MISC ,
156+ "Seek error" );
157+ r = ARCHIVE_FATAL ;
158+ }
159+ }
160+ return (r );
143161}
0 commit comments