summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/dpkg/dpkg/dpkg-deb-avoid-fflush.patch
blob: a5d6b616c0f3015d36a45c94cd2a009f957a4eb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
From 78eaf928d30d0b16e05d8d63c55a3632a135ed9a Mon Sep 17 00:00:00 2001
From: Guillem Jover <guillem@debian.org>
Date: Thu, 4 Nov 2010 00:51:13 +0100
Subject: [PATCH] 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.

Upstream-Status: Backport of revision 2d420ee1d05033d237462a0075facfe406b08043 (in 1.16.x)

---
 dpkg-deb/extract.c |   83 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 62 insertions(+), 21 deletions(-)

diff --git a/dpkg-deb/extract.c b/dpkg-deb/extract.c
index 22aea98..0f5ac88 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>
@@ -61,13 +62,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
@@ -115,19 +144,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,_("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;
@@ -137,8 +173,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,_("between members"));
+      r = read(arfd, &arh, sizeof(arh));
+      if (r != sizeof(arh))
+        read_fail(r, debar, _("archive member header"));
 
       dpkg_ar_normalize_name(&arh);
 
@@ -153,8 +190,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,_("header info 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"));
@@ -174,7 +212,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 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;
@@ -198,7 +237,8 @@ void extracthalf(const char *debar, const char *directory,
           ctrllennum= memberlen;
         }
         if (!adminmember != !admininfo) {
-	  stream_null_copy(ar, memberlen + (memberlen&1),_("skipped member data from %s"), debar);
+          fd_null_copy(arfd, memberlen + (memberlen & 1),
+                       _("skipped archive member data from %s"), debar);
         } else {
           break; /* Yes ! - found it. */
         }
@@ -221,8 +261,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, _("control information length"));
+
+    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 length `%s'"), ctrllenbuf);
 
@@ -230,7 +272,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 control area from %s"), debar);
+      fd_null_copy(arfd, ctrllennum,
+                   _("skipped archive control member data from %s"), debar);
     }
 
     if (admininfo >= 2) {
@@ -252,13 +295,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);
@@ -275,7 +316,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) {
-- 
1.7.7.6