|
|
@@ -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) {
|