Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pack/unpack.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1993-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* unpack file ...
23
* pcat file ...
24
*
25
* unpack files that have been Huffman encoded
26
*
27
* David Korn
28
* AT&T Research
29
*
30
*/
31
32
static const char usage_head[] =
33
"[-?@(#)$Id: unpack (AT&T Research) 2003-04-28 $\n]"
34
USAGE_LICENSE
35
;
36
37
static const char usage_common[] =
38
"For each \afile\a specified, a search is made for a file named "
39
"\afile\a\b.z\b (or just \afile\a, if \afile\a ends in \b.z\b). If "
40
"this file appears to be a packed file, ";
41
42
static const char usage_tail[] = "\n\nfile ...\n\n"
43
"[+EXIT STATUS]{"
44
"[+0?All files unpacked successfully.]"
45
"[+\an\a?\an\a files failed to unpack, where \an\a is less than 125.]"
46
"[+125?125 or more files failed to unpack.]"
47
"}";
48
49
50
static const char usage_pcat1[] =
51
"[+NAME?pcat - unpack and concatenate files created by pack]"
52
"[+DESCRIPTION?\bpcat\b does for packed files what \bcat\b(1) does "
53
"for ordinary files, except that \bpcat\b cannot be used "
54
"as filter. ";
55
static const char usage_pcat2[] =
56
"\bpcat\b unpacks the file and writes it to standard output.]";
57
static const char pcat_see_also[] =
58
"[+SEE ALSO?pack(1), unpack(1), cat(1), zcat(1), gzcat(1)]";
59
60
static const char usage_unpack1[] =
61
"[+NAME?unpack - unpack files created by pack]"
62
"[+DESCRIPTION?\bunpack\b expands files created by \bpack\b. ";
63
64
static const char usage_unpack2[] =
65
"it is replaced by its original expanded version. The new file "
66
"has the \b.z\b suffix stripped from its name, and has the same "
67
"access modes, access and modification dates, and owner as those "
68
"of the packed file.]";
69
70
static const char unpack_see_also[] =
71
"[+SEE ALSO?pack(1), pcat(1), uncompress(1), gunzip(1)]";
72
73
74
75
#include "huffman.h"
76
#include <error.h>
77
#include <ls.h>
78
#include <times.h>
79
80
#define PERM(m) ((m)&(S_IRWXU|S_IRWXG|S_IRWXO))
81
82
static char *inname(char*);
83
static const char suffix[] = ".z";
84
85
int
86
main(int argc, char *argv[])
87
{
88
register Huff_t *hp;
89
register char *infile,*outfile;
90
char *command;
91
char *usage;
92
int out;
93
Sfio_t *fpin,*fpout,*iop;
94
int nunpack = 1;
95
int pcat;
96
int deleted;
97
int n;
98
struct stat statb;
99
100
if(command = strrchr(argv[0],'/'))
101
command++;
102
else
103
command = argv[0];
104
error_info.id = command;
105
pcat = (*command=='p');
106
if(!(iop = sfstropen()))
107
error(ERROR_system(1), "out of space [tmp string]");
108
sfputr(iop, usage_head, -1);
109
if(pcat)
110
{
111
sfputr(iop, usage_pcat1, -1);
112
sfputr(iop, usage_common, -1);
113
sfputr(iop, usage_pcat2, -1);
114
sfputr(iop, usage_tail, -1);
115
sfputr(iop, pcat_see_also, -1);
116
}
117
else
118
{
119
sfputr(iop, usage_unpack1, -1);
120
sfputr(iop, usage_common, -1);
121
sfputr(iop, usage_unpack2, -1);
122
sfputr(iop, usage_tail, -1);
123
sfputr(iop, unpack_see_also, -1);
124
}
125
if (!(usage = sfstruse(iop)))
126
error(ERROR_SYSTEM|3, "out of space");
127
128
while(n = optget(argv,usage)) switch(n)
129
{
130
case ':':
131
error(2, "%s", opt_info.arg);
132
break;
133
case '?':
134
error(ERROR_usage(2), "%s", opt_info.arg);
135
break;
136
}
137
argv += opt_info.index;
138
if(error_info.errors || !*argv)
139
error(ERROR_usage(2), "%s", optusage((char*)0));
140
sfclose(iop);
141
while (outfile = *argv++)
142
{
143
fpin = fpout = (Sfio_t*)0;
144
hp = (Huff_t*)0;
145
deleted = 0;
146
if(!(infile = inname(outfile)))
147
continue;
148
if(!(fpin=sfopen((Sfio_t*)0,infile,"r")))
149
{
150
error(ERROR_system(0), "%s: cannot open", infile);
151
continue;
152
}
153
if(pcat)
154
fpout = sfstdout;
155
else
156
{
157
if(fstat(sffileno(fpin),&statb) < 0)
158
error(ERROR_system(0), "%s: cannot stat", infile);
159
else if(S_ISDIR(statb.st_mode))
160
error(2, "%s: cannot pack a directory", infile);
161
else if(statb.st_nlink > 1)
162
error(2, "%s: has links", infile);
163
else if(access(outfile,F_OK) ==0)
164
error(2, "%s: already exists", outfile);
165
else if(((out=open(outfile,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,PERM(statb.st_mode))) < 0) ||
166
!((fpout = sfnew((Sfio_t*)0,(char*)0,SF_UNBOUND,out,SF_WRITE))))
167
error(2, "%s: cannot create", outfile);
168
else if((deleted++,chmod(outfile,statb.st_mode)) < 0)
169
error(ERROR_system(0), "%s: cannot change mode to %o",outfile,statb.st_mode);
170
else
171
{
172
chown(outfile,statb.st_uid,statb.st_gid);
173
goto ok;
174
}
175
goto skip;
176
}
177
ok:
178
if(!(hp = huffgethdr(fpin)))
179
error(2, "%s: read error", infile);
180
else if(huffdecode(hp,fpin,fpout,SF_UNBOUND)<0)
181
error(2, "%s: read error", outfile);
182
else
183
{
184
if(!pcat)
185
{
186
touch(outfile,statb.st_atime,statb.st_mtime,1);
187
sfprintf(sfstdout,"%s: %s: unpacked\n",command, infile);
188
deleted = 0;
189
if(remove(infile) < 0)
190
error(ERROR_system(0), "%s: cannot remove", infile);
191
}
192
nunpack++;
193
}
194
skip:
195
if(hp)
196
huffend(hp);
197
if(fpin)
198
sfclose(fpin);
199
if(fpout)
200
sfclose(fpout);
201
if(deleted)
202
remove(outfile);
203
if(infile)
204
free(infile);
205
}
206
argc -= nunpack;
207
if(argc > 125)
208
argc = 125;
209
exit(argc);
210
}
211
212
213
static char *inname(register char *outfile)
214
{
215
register char *cp;
216
register int n = strlen(outfile);
217
register int sufflen = strlen(suffix);
218
if(cp = (char*)malloc(n+sufflen+1))
219
{
220
strcpy(cp,outfile);
221
if(streq(suffix,cp+n-sufflen))
222
outfile[n-sufflen] = 0;
223
else
224
strcat(cp+n,suffix);
225
}
226
return(cp);
227
}
228
229