"Fossies" - the Fresh Open Source Software Archive 
Member "afio-2.5.2/compfile.c" (30 Nov 2018, 9723 Bytes) of package /linux/misc/afio-2.5.2.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "compfile.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.5.1_vs_2.5.2.
1 /* afio file compresssion code */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <string.h>
7
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <sys/signal.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13
14 #include "patchlevel.h"
15
16 #include "afio.h"
17
18 int matchcompext(char *);
19 void meminit(void);
20 void memwrite(char *buf, int count);
21 int setupgzip(char *name);
22
23 int zipfdfd;
24
25 /* default value vor gzip 1.2.3 */
26 int gzipfactor=6;
27
28 /* compress all files? */
29 int forceZflag = 0;
30
31 /* this can be set to use something else but gzip: */
32 char *compressprog = NULL;
33 int compressargs = 0;
34
35
36 /* max. (virtual) memory usage for -Z option */
37 off_t maxmem=250*1024*1024;
38
39 /* files whose length is below this length won't be compressed */
40 long compthreshold=0;
41
42
43 /* stuff to build argument list for compression/decompression : */
44
45 #define MAX_ARGS 101
46
47 char * compress_arg_list[MAX_ARGS+1];
48 /* MAX_ARGS+1 because we need to leave room for a NULL to mark the end */
49 int compress_arg_no = 1;
50
51 void add_arg(char *arg)
52 {
53 if((compress_arg_no == 1)&&(*arg=='\0'))
54 {
55 /* special case: -Q "" means no arguments. */
56 return;
57 }
58
59 if(compress_arg_no < MAX_ARGS )
60 compress_arg_list[compress_arg_no++] = arg;
61 else
62 {
63 fprintf (stderr, "afio: Fatal: maximium number of -Q arguments exceeded.\n");
64 exit(1);
65 }
66
67 }
68
69 /*
70 * meminit, memwrite, memreset, memread, memfree.
71 */
72
73 int memerror;
74 char *membank=NULL;
75 size_t allocsize=0;
76 size_t memsize,membytesread,membytesleft;
77
78 void meminit(void)
79 {
80 memerror=0;
81 memsize=0;
82 /* RWWH: Initialize only the first time */
83 if (!allocsize) {
84 allocsize=100000;
85 membank=(char *)malloc(allocsize);
86 if(membank==NULL)
87 {
88 warn_nocount("Memory","Low on virtual memory, zipping twice instead.");
89 memerror=1;
90 allocsize=0;
91 }
92 }
93 }
94
95 void memwrite(char *buf, int count)
96 {
97 char *oldbank;
98
99 if(memerror) return;
100
101 oldbank=membank;
102 /* RWWH: don't increase by linear amount! grow exponentially! */
103 if (memsize+count>=allocsize) {
104 allocsize=1.25*(memsize+count);
105 if(allocsize/1024L/1024L > 2000)
106 {
107 /* safety: to avoid possible errors due to use of 32 bit int
108 and size_t types here and there, prevent membank going over 2GB if
109 compression programm actually expands filesize.
110 Note that -M is capped at 1.5GB anyway.
111 */
112 membank=NULL; /* simulate realloc running out of memory */
113 }
114 else
115 {
116 membank=(char *)realloc(membank,allocsize);
117 }
118 if(membank==NULL)
119 {
120 warn_nocount("Memory","Low on virtual memory, zipping twice instead.");
121 /* The free() both works and is necessary. I can't recall what
122 manpage documents this. */
123 free(oldbank);
124 memerror=1;
125 allocsize=0;
126 return;
127 }
128 }
129
130 memcpy(membank+memsize,buf,(size_t)count);
131 memsize+=count;
132 }
133
134 void memreset()
135 {
136 membytesread=0;
137 membytesleft=memsize;
138 }
139
140 int memread(char *buf,int count)
141 {
142 if(membytesleft==0) return 0;
143
144 if ((size_t)count > membytesleft) count=membytesleft;
145 memcpy(buf,membank+membytesread,(size_t)count);
146 membytesread+=count;
147 membytesleft-=count;
148 return count;
149 }
150
151 void memfree()
152 {
153 /* We do not free anymore, this should speed things up. */
154 #if 0
155 if(memerror==0) free(membank);
156 allocsize=0;
157 #endif
158 }
159
160
161 /*******/
162
163 /*
164 * Fork a gzip zipping the file name. The zipped version is output through a
165 * pipe, the pipe handle is returned.
166 * Returns -1 on failure.
167 */
168 int comppid;
169
170 int setupgzip(char *name)
171 {
172 int pipedes[2];
173 char farg[3];
174
175 farg[0]='-';
176 farg[1]=gzipfactor+'0';
177 farg[2]='\0';
178
179 if(pipe(pipedes)==-1) { perror("pipe"); return -1; }
180
181 mayberewind();
182
183 if ((comppid = xfork ("out(), compressing", NODIE)) == 0)
184 {
185 if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
186
187 dup2(pipedes[1],fileno(stdout));
188 close(pipedes[1]);
189 close(pipedes[0]);
190
191 VOID close (fileno (stdin));
192
193 if (open (name, O_RDONLY) >= 0)
194 {
195 if(! compressargs)
196 execlp (compressprog, compressprog, "-c", farg, NULL);
197 else
198 execvp (compressprog, compress_arg_list);
199 }
200 exit (1);
201 }
202
203 close(pipedes[1]);
204
205 /* fprintf(stderr,"pid %d init, pipedes=%d.\n",comppid,pipedes[0]); */
206
207 return pipedes[0];
208 }
209
210 #include <sys/wait.h>
211 #include <sys/types.h>
212
213 void waitforgzip()
214 {
215 /* fprintf(stderr,"wait for gzip %d.\n",comppid); */
216
217 xwait (comppid, "out(), wait for gzip child", FALSE);
218 }
219
220 /*
221 * compress "name" if we can
222 * If we compress we change the statbuf size, the file name, close
223 * the old pointer to the file and return the pointer to the compressed
224 * version;
225 */
226
227 #if ( defined(sun) && defined(__svr4__) ) || defined(__CYGWIN32__)
228 #include <dirent.h>
229 #else
230 #include <sys/dir.h>
231 #endif
232
233 void
234 compressfile (int *fdp, char *name, reg Stat *asb, int *cratio) {
235 int compout;
236 char *tmpcomp;
237 Stat asb2;
238 int zipfd;
239 ssize_t len;
240 char buf[40960];
241 off_t ziplen;
242 int usemem;
243
244 if (cratio)
245 *cratio = 100;
246
247 /* We need to mark the file as being suitable or not for decompression on
248 reading the archive. This is done by adding a .z extension.
249
250 There is a problem with this: a file that is not suitable for
251 compression may already have such an extension.
252 Since this is a regular file, we can use the
253 device number to indicate something weird going on here.
254
255 We look at the bit (asb->sb_rdev)&RDEV_NOTCOMPR:
256 If it is 1, it means that the file wasn't suitable for compression,
257 and thus that any .z present was there on the original name.
258 If it is 0, this does NOT imply that the file was compressed by afio.
259
260 Note that it being 0 doesn't mean `decompress me', it merely
261 indicates that a .z extender, _if_ _present_, was added by afio.
262 (However, as of version 2.3.6, false does mean that the file was
263 compressed by afio and a .z extender added. In older archives one may
264 see filenames with the bit 0 and not ending in .z. Such files
265 have a compressed version larger than the original.)
266
267 In pre-2.4.4 versions, files with size 0 do not have the bit
268 set to 1.
269 */
270
271 /* indicate unsuitable for compression, may change it later */
272 asb->sb_rdev |= RDEV_NOTCOMPR;
273
274 /* Hard link handling code will break if we do compression on the
275 file, so try to compress only if no links or hard link handling.
276 Note that if forceZflag==1 than also lflag==1 was set, so this
277 test will never return false.
278
279 Also only try to compress if not already compressed,
280 or length is >= threshold, or <= maxsizetocompress,
281 but always try if we force compression
282 */
283
284 if ( (lflag || (asb->sb_nlink == 1))
285 &&
286 ( ( !matchcompext(name)
287 && (asb->sb_size >= compthreshold)
288 && ((maxsizetocompress==0) || ((ulonglong)(asb->sb_size) <= maxsizetocompress))
289 )
290 || forceZflag
291 )
292 )
293 {
294 /* make sure compress could put on the .Z */
295 if ((tmpcomp = strrchr (name, '/')) != NULL)
296 tmpcomp++;
297 else
298 tmpcomp = name;
299 #ifdef NAME_MAX
300 if (strlen (tmpcomp) + 2 > NAME_MAX)
301 #else
302 #ifdef MAXNAMLEN /* BSD otherwise should be sysV (FFS on sysV?) */
303 if (strlen (tmpcomp) + 2 > MAXNAMLEN)
304 #else
305 if (strlen (tmpcomp) + 2 > DIRSIZ)
306 #endif /* MAXNAMLEN */
307 #endif /* NAME_MAX */
308 {
309 #ifndef LONGZFILE
310 VOID warn (name, " is too long to tack on .z");
311 return;
312 #endif
313 }
314
315 /* fprintf(stderr,"---nam: %s, len: %d ziplen: ",name,asb->sb_size); */
316
317 usemem=1;
318
319 if((zipfd=setupgzip(name))!=-1)
320 {
321 ziplen=0;
322 if(usemem) meminit();
323 while((len=read(zipfd,buf,sizeof(buf)))!=0)
324 {
325 if(len<0) { fprintf(stderr,
326 "Trouble zipping file, storing uncompressed\n");
327 /* read error on pipe, do not use gzip on this file */
328 ziplen=0; break;
329 }
330 if(usemem) memwrite(buf,len);
331
332 ziplen+=len;
333 /* too much memory used? */
334 if(usemem && ziplen>maxmem)
335 { /* prepare to zip twice and free memory */
336 usemem=0;
337 if (!memerror) memfree();
338 /* fprintf(stderr,"zipping twice."); */
339 }
340 }
341 close(zipfd);
342
343 /* wait for child to exit */
344 if(xwait (comppid, "out(), wait for gzip child", FALSE)!= 0)
345 { fprintf(stderr,
346 "Trouble zipping file, storing uncompressed\n");
347 ziplen=0;
348 }
349
350 if(memerror) usemem=0;
351
352 /* fprintf(stderr,"%ld\n",ziplen); */
353 asb2.sb_size=ziplen;
354
355 if (ziplen>0)
356 {
357 /* if compressed file is smaller than original, of if forceZflag
358 is set, use compressed data */
359 if (asb2.sb_size < asb->sb_size || forceZflag )
360 {
361 if(usemem)
362 {
363 close (*fdp);
364 strcat (name, ".z");
365 /* was suitable for compression */
366 asb->sb_rdev &= ~RDEV_NOTCOMPR;
367
368 if (cratio)
369 *cratio = (int)((asb2.sb_size * 100.0) / asb->sb_size);
370 asb->sb_size = asb2.sb_size;
371 *fdp = MEMFD;
372 }
373 else
374 if ((compout = setupgzip(name)) >= 0)
375 {
376 zipfdfd=compout;
377 compout=ZIPFD;
378
379 close (*fdp);
380 strcat (name, ".z");
381 /* was suitable for compression */
382 asb->sb_rdev &= ~RDEV_NOTCOMPR;
383
384 if (cratio)
385 *cratio = (int)((asb2.sb_size * 100.0) / asb->sb_size);
386 asb->sb_size = asb2.sb_size;
387 *fdp = compout;
388 }
389 }
390 else
391 {
392 if(usemem) memfree();
393 }
394 }
395 }
396
397 }
398 }
399
400