The following commit has been merged in the master branch:
commit 2d420ee1d05033d237462a0075facfe406b08043
Author: Guillem Jover <[email protected]>
Date: Thu Nov 4 00:51:13 2010 +0100
dpkg-deb: Use fd instead of stream based buffered I/O
Behaviour of fflush() on input streams is undefined per POSIX, avoid
mixing stream and file descriptor based I/O, and only use the latter
instead.
diff --git a/dpkg-deb/extract.c b/dpkg-deb/extract.c
index d85b337..91fc89a 100644
--- a/dpkg-deb/extract.c
+++ b/dpkg-deb/extract.c
@@ -31,6 +31,7 @@
#include <ctype.h>
#include <string.h>
#include <dirent.h>
+#include <fcntl.h>
#include <unistd.h>
#include <ar.h>
#include <stdbool.h>
@@ -62,13 +63,41 @@ static void movecontrolfiles(const char *thing) {
}
static void DPKG_ATTR_NORET
-readfail(FILE *a, const char *filename, const char *what)
+read_fail(int rc, const char *filename, const char *what)
{
- if (ferror(a)) {
- ohshite(_("error reading %s from file %.255s"), what, filename);
- } else {
+ if (rc == 0)
ohshit(_("unexpected end of file in %s in %.255s"),what,filename);
+ else
+ ohshite(_("error reading %s from file %.255s"), what, filename);
+}
+
+static ssize_t
+read_line(int fd, char *buf, size_t min_size, size_t max_size)
+{
+ ssize_t line_size = 0;
+ size_t n = min_size;
+
+ while (line_size < (ssize_t)max_size) {
+ ssize_t r;
+ char *nl;
+
+ r = read(fd, buf + line_size, n);
+ if (r <= 0)
+ return r;
+
+ nl = strchr(buf + line_size, '\n');
+ line_size += r;
+
+ if (nl != NULL) {
+ nl[1] = '\0';
+ return line_size;
+ }
+
+ n = 1;
}
+
+ buf[line_size] = '\0';
+ return line_size;
}
static size_t
@@ -116,20 +145,26 @@ void extracthalf(const char *debar, const char *directory,
char versionbuf[40];
float versionnum;
size_t ctrllennum, memberlen= 0;
+ ssize_t r;
int dummy;
pid_t c1=0,c2,c3;
int p1[2], p2[2];
- FILE *ar;
+ int arfd;
struct stat stab;
char nlc;
int adminmember;
bool oldformat, header_done;
struct compressor *decompressor = &compressor_gzip;
- ar= fopen(debar,"r"); if (!ar) ohshite(_("failed to read archive
`%.255s'"),debar);
- if (fstat(fileno(ar),&stab)) ohshite(_("failed to fstat archive"));
- if (!fgets(versionbuf, sizeof(versionbuf), ar))
- readfail(ar, debar, _("archive magic version number"));
+ arfd = open(debar, O_RDONLY);
+ if (arfd < 0)
+ ohshite(_("failed to read archive `%.255s'"), debar);
+ if (fstat(arfd, &stab))
+ ohshite(_("failed to fstat archive"));
+
+ r = read_line(arfd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf));
+ if (r < 0)
+ read_fail(r, debar, _("archive magic version number"));
if (!strcmp(versionbuf, DPKG_AR_MAGIC)) {
oldformat = false;
@@ -139,8 +174,9 @@ void extracthalf(const char *debar, const char *directory,
for (;;) {
struct ar_hdr arh;
- if (fread(&arh,1,sizeof(arh),ar) != sizeof(arh))
- readfail(ar, debar, _("archive member header"));
+ r = read(arfd, &arh, sizeof(arh));
+ if (r != sizeof(arh))
+ read_fail(r, debar, _("archive member header"));
dpkg_ar_normalize_name(&arh);
@@ -155,8 +191,9 @@ void extracthalf(const char *debar, const char *directory,
if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
ohshit(_("file `%.250s' is not a debian binary archive (try
dpkg-split?)"),debar);
infobuf= m_malloc(memberlen+1);
- if (fread(infobuf,1, memberlen + (memberlen&1), ar) != memberlen +
(memberlen&1))
- readfail(ar, debar, _("archive information header member"));
+ r = read(arfd, infobuf, memberlen + (memberlen & 1));
+ if ((size_t)r != (memberlen + (memberlen & 1)))
+ read_fail(r, debar, _("archive information header member"));
infobuf[memberlen] = '\0';
cur= strchr(infobuf,'\n');
if (!cur) ohshit(_("archive has no newlines in header"));
@@ -176,8 +213,8 @@ void extracthalf(const char *debar, const char *directory,
/* Members with `_' are noncritical, and if we don't understand them
* we skip them.
*/
- stream_null_copy(ar, memberlen + (memberlen & 1),
- _("skipped archive member data from %s"), debar);
+ fd_null_copy(arfd, memberlen + (memberlen & 1),
+ _("skipped archive member data from %s"), debar);
} else {
if (strncmp(arh.ar_name, ADMINMEMBER, sizeof(arh.ar_name)) == 0)
adminmember = 1;
@@ -202,8 +239,8 @@ void extracthalf(const char *debar, const char *directory,
ctrllennum= memberlen;
}
if (!adminmember != !admininfo) {
- stream_null_copy(ar, memberlen + (memberlen & 1),
- _("skipped archive member data from %s"), debar);
+ fd_null_copy(arfd, memberlen + (memberlen & 1),
+ _("skipped archive member data from %s"), debar);
} else {
break; /* Yes ! - found it. */
}
@@ -226,8 +263,10 @@ void extracthalf(const char *debar, const char *directory,
l = strlen(versionbuf);
if (l && versionbuf[l - 1] == '\n')
versionbuf[l - 1] = '\0';
- if (!fgets(ctrllenbuf,sizeof(ctrllenbuf),ar))
- readfail(ar, debar, _("archive control member size"));
+
+ r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf));
+ if (r < 0)
+ read_fail(r, debar, _("archive control member size"));
if (sscanf(ctrllenbuf,"%zi%c%d",&ctrllennum,&nlc,&dummy) !=2 || nlc !=
'\n')
ohshit(_("archive has malformatted control member size '%s'"),
ctrllenbuf);
@@ -235,8 +274,8 @@ void extracthalf(const char *debar, const char *directory,
memberlen = ctrllennum;
} else {
memberlen = stab.st_size - ctrllennum - strlen(ctrllenbuf) - l;
- stream_null_copy(ar, ctrllennum,
- _("skipped archive control member data from %s"),
debar);
+ fd_null_copy(arfd, ctrllennum,
+ _("skipped archive control member data from %s"), debar);
}
if (admininfo >= 2) {
@@ -258,13 +297,11 @@ void extracthalf(const char *debar, const char *directory,
}
- safe_fflush(ar);
-
m_pipe(p1);
c1 = subproc_fork();
if (!c1) {
close(p1[0]);
- stream_fd_copy(ar, p1[1], memberlen, _("failed to write to pipe in copy"));
+ fd_fd_copy(arfd, p1[1], memberlen, _("failed to write to pipe in copy"));
if (close(p1[1]))
ohshite(_("failed to close pipe in copy"));
exit(0);
@@ -281,7 +318,7 @@ void extracthalf(const char *debar, const char *directory,
decompress_filter(decompressor, 0, 1, _("data"));
}
close(p1[0]);
- fclose(ar);
+ close(arfd);
if (taroption) close(p2[1]);
if (taroption && directory) {
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]