<enrico.scholz@informatik.tu-chemnitz.de>, his analysis follows.
libbb/unarchive.c: prevent opkg hang when subprocess is stuck in a
write() call on a filled pipe and main process (which assumes that end
of data from pipe has been reached) waits for this died subprocess.
This patch swaps the original wait(pid) + close(pipe) sequencse so
that pipe is closed first.
The 'ar' code path has been fixed too by breaking the loop when
requested data have been found. Previously, the loop continued at
the (wrongly calculated) next position in the stream. The patch
moves the stream cleanup at a better place.
Variable declarations were moved to inner scopes too to ease detection
of broken deallocation.
NOTE: the
| f = fdopen(...);
| while (... /* do fread(f) */ ...) { /* ==1== */
| /* this is done in gz_open() */
| pid = fork();
| if (pid == 0) {
| fread(f); /* ==2== */
| _exit(0);
| }
| }
code looks problematic because '==2==' might update f's internal
buffer. As ==2== is done in an own process, these changes are not
seen by ==1==. It works only because gz_open() is called not more
than one time and the loops break (after the patch).
git-svn-id: http://opkg.googlecode.com/svn/trunk@340
e8e0d7a0-c8d9-11dd-a880-
a1081c7ac358
const int extract_function, const char *prefix, const char *filename)
{
FILE *deb_stream = NULL;
const int extract_function, const char *prefix, const char *filename)
{
FILE *deb_stream = NULL;
- FILE *uncompressed_stream = NULL;
file_header_t *ar_header = NULL;
const char **file_list = NULL;
char *output_buffer = NULL;
char *ared_file = NULL;
char ar_magic[8];
file_header_t *ar_header = NULL;
const char **file_list = NULL;
char *output_buffer = NULL;
char *ared_file = NULL;
char ar_magic[8];
if (filename != NULL) {
file_list = xmalloc(sizeof(char *) * 2);
if (filename != NULL) {
file_list = xmalloc(sizeof(char *) * 2);
while ((ar_header = get_header_ar(deb_stream)) != NULL) {
if (strcmp(ared_file, ar_header->name) == 0) {
while ((ar_header = get_header_ar(deb_stream)) != NULL) {
if (strcmp(ared_file, ar_header->name) == 0) {
+ int gunzip_pid = 0;
+ FILE *uncompressed_stream;
/* open a stream of decompressed data */
uncompressed_stream = gz_open(deb_stream, &gunzip_pid);
if (uncompressed_stream == NULL) {
/* open a stream of decompressed data */
uncompressed_stream = gz_open(deb_stream, &gunzip_pid);
if (uncompressed_stream == NULL) {
archive_offset = 0;
output_buffer = unarchive(uncompressed_stream, out_stream, get_header_tar, free_header_tar, extract_function, prefix, file_list);
archive_offset = 0;
output_buffer = unarchive(uncompressed_stream, out_stream, get_header_tar, free_header_tar, extract_function, prefix, file_list);
+ fclose(uncompressed_stream);
+ gz_close(gunzip_pid);
+ break;
}
seek_sub_file(deb_stream, ar_header->size);
free (ar_header->name);
free (ar_header);
}
}
seek_sub_file(deb_stream, ar_header->size);
free (ar_header->name);
free (ar_header);
}
- gz_close(gunzip_pid);
- fclose(uncompressed_stream);
goto cleanup;
} else if (strncmp(ar_magic, "\037\213", 2) == 0) {
/* it's a gz file, let's assume it's an opkg */
goto cleanup;
} else if (strncmp(ar_magic, "\037\213", 2) == 0) {
/* it's a gz file, let's assume it's an opkg */
if (strncmp(tar_header->name, "./", 2) == 0)
name_offset = 2;
if (strcmp(ared_file, tar_header->name+name_offset) == 0) {
if (strncmp(tar_header->name, "./", 2) == 0)
name_offset = 2;
if (strcmp(ared_file, tar_header->name+name_offset) == 0) {
+ int gunzip_pid = 0;
+ FILE *uncompressed_stream;
/* open a stream of decompressed data */
uncompressed_stream = gz_open(unzipped_opkg_stream, &gunzip_pid);
if (uncompressed_stream == NULL) {
/* open a stream of decompressed data */
uncompressed_stream = gz_open(unzipped_opkg_stream, &gunzip_pid);
if (uncompressed_stream == NULL) {
file_list);
/*fprintf(stderr, __FUNCTION__ ":%d: unarchive complete\n", __LINE__);*/
free_header_tar(tar_header);
file_list);
/*fprintf(stderr, __FUNCTION__ ":%d: unarchive complete\n", __LINE__);*/
free_header_tar(tar_header);
fclose(uncompressed_stream);
fclose(uncompressed_stream);
break;
}
seek_sub_file(unzipped_opkg_stream, tar_header->size);
free_header_tar(tar_header);
}
break;
}
seek_sub_file(unzipped_opkg_stream, tar_header->size);
free_header_tar(tar_header);
}
- gz_close(unzipped_opkg_pid);
fclose(unzipped_opkg_stream);
fclose(unzipped_opkg_stream);
+ gz_close(unzipped_opkg_pid);
/*fprintf(stderr, __FUNCTION__ ":%d: done\n", __LINE__);*/
goto cleanup;
} else {
/*fprintf(stderr, __FUNCTION__ ":%d: done\n", __LINE__);*/
goto cleanup;
} else {