1 /***********************************************************************
2 This file is part of HA, a general purpose file archiver.
3 Copyright (C) 1995 Harri Hirvola
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 ************************************************************************
19 HA *nix specific routines
20 ***********************************************************************/
21
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <utime.h>
28 #include <time.h>
29 #include "ha.h"
30 #include "error.h"
31 #include "archive.h"
32
33 #define HA_ISVTX 0x0200
34 #define HA_ISGID 0x0400
35 #define HA_ISUID 0x0800
36 #define HA_IRUSR 0x0100
37 #define HA_IWUSR 0x0080
38 #define HA_IXUSR 0x0040
39 #define HA_IRGRP 0x0020
40 #define HA_IWGRP 0x0010
41 #define HA_IXGRP 0x0008
42 #define HA_IROTH 0x0004
43 #define HA_IWOTH 0x0002
44 #define HA_IXOTH 0x0001
45 #define HA_IFMT 0xf000
46 #define HA_IFIFO 0x1000
47 #define HA_IFCHR 0x2000
48 #define HA_IFDIR 0x4000
49 #define HA_IFBLK 0x6000
50 #define HA_IFREG 0x8000
51 #define HA_IFLNK 0xa000
52 #define HA_IFSOCK 0xc000
53 #define HA_ISDIR(m) ((m&HA_IFMT)==HA_IFDIR)
54 #define HA_ISCHR(m) ((m&HA_IFMT)==HA_IFCHR)
55 #define HA_ISBLK(m) ((m&HA_IFMT)==HA_IFBLK)
56 #define HA_ISLNK(m) ((m&HA_IFMT)==HA_IFLNK)
57 #define HA_ISFIFO(m) ((m&HA_IFMT)==HA_IFIFO)
58 #define HA_ISSOCK(m) ((m&HA_IFMT)==HA_IFSOCK)
59
60 typedef struct {
61 unsigned mtype;
62 unsigned attr;
63 unsigned user;
64 unsigned group;
65 } Mdhd;
66
67 #define MDHDLEN 7 /* Length of Mdhd in archive */
68
69 static Mdhd mdhd;
70 struct stat filestat;
71
72 void copy_path_relative(char *dest, char *src, size_t len);
73
sig_handler(int signo)74 static void sig_handler(int signo) {
75
76 error(1,ERR_INT,signo);
77 }
78
md_init(void)79 void md_init(void) {
80
81 signal(SIGINT,sig_handler);
82 signal(SIGTERM,sig_handler);
83 signal(SIGPIPE,sig_handler);
84 signal(SIGQUIT,sig_handler);
85 umask(0);
86 }
87
md_systime(void)88 U32B md_systime(void) {
89
90 return (U32B)time(NULL);
91 }
92
md_tomdattr(U16B haattr)93 static mode_t md_tomdattr(U16B haattr) {
94
95 mode_t mdattr;
96
97 mdattr=0;
98 if (haattr&HA_IRUSR) mdattr|=S_IRUSR;
99 if (haattr&HA_IWUSR) mdattr|=S_IWUSR;
100 if (haattr&HA_ISUID) mdattr|=S_ISUID;
101 if (haattr&HA_IXUSR) mdattr|=S_IXUSR;
102 if (haattr&HA_IRGRP) mdattr|=S_IRGRP;
103 if (haattr&HA_IWGRP) mdattr|=S_IWGRP;
104 if (haattr&HA_ISGID) mdattr|=S_ISGID;
105 if (haattr&HA_IXGRP) mdattr|=S_IXGRP;
106 if (haattr&HA_IROTH) mdattr|=S_IROTH;
107 if (haattr&HA_IWOTH) mdattr|=S_IWOTH;
108 #ifdef S_ISVTX
109 if (haattr&HA_ISVTX) mdattr|=S_ISVTX;
110 #endif
111 if (haattr&HA_IXOTH) mdattr|=S_IXOTH;
112 return mdattr;
113 }
114
md_tohaattr(mode_t mdattr)115 static U16B md_tohaattr(mode_t mdattr) {
116
117 U16B haattr;
118
119 haattr=0;
120 if (mdattr&S_IRUSR) haattr|=HA_IRUSR;
121 if (mdattr&S_IWUSR) haattr|=HA_IWUSR;
122 if (mdattr&S_ISUID) haattr|=HA_ISUID;
123 if (mdattr&S_IXUSR) haattr|=HA_IXUSR;
124 if (mdattr&S_IRGRP) haattr|=HA_IRGRP;
125 if (mdattr&S_IWGRP) haattr|=HA_IWGRP;
126 if (mdattr&S_ISGID) haattr|=HA_ISGID;
127 if (mdattr&S_IXGRP) haattr|=HA_IXGRP;
128 if (mdattr&S_IROTH) haattr|=HA_IROTH;
129 if (mdattr&S_IWOTH) haattr|=HA_IWOTH;
130 if (mdattr&S_IXOTH) haattr|=HA_IXOTH;
131 #ifdef S_ISVTX
132 if (mdattr&S_ISVTX) haattr|=HA_ISVTX;
133 #endif
134 if (S_ISDIR(mdattr)) haattr|=HA_IFDIR;
135 else if (S_ISCHR(mdattr)) haattr|=HA_IFCHR;
136 else if (S_ISBLK(mdattr)) haattr|=HA_IFBLK;
137 #ifdef S_ISLNK
138 else if (S_ISLNK(mdattr)) haattr|=HA_IFLNK;
139 #endif
140 #ifdef S_ISFIFO
141 else if (S_ISFIFO(mdattr)) haattr|=HA_IFIFO;
142 #endif
143 #ifdef S_ISSOCK
144 else if (S_ISSOCK(mdattr)) haattr|=HA_IFSOCK;
145 #endif
146 return haattr;
147 }
148
attrstring(unsigned haattr)149 static char *attrstring(unsigned haattr) {
150
151 static char as[11];
152
153 sprintf(as,"%c%c%c%c%c%c%c%c%c%c",
154 HA_ISFIFO(haattr)?'f':HA_ISSOCK(haattr)?'s':HA_ISLNK(haattr)?'l':
155 HA_ISDIR(haattr)?'d':HA_ISCHR(haattr)?'c':HA_ISBLK(haattr)?'b':'-',
156 (haattr&HA_IRUSR)?'r':'-',
157 (haattr&HA_IWUSR)?'w':'-',
158 (haattr&HA_ISUID)?(haattr&
159 HA_IXUSR)?'s':'S':(haattr&HA_IXUSR)?'x':'-',
160 (haattr&HA_IRGRP)?'r':'-',
161 (haattr&HA_IWGRP)?'w':'-',
162 (haattr&HA_ISGID)?(haattr&
163 HA_IXGRP)?'s':'S':(haattr&HA_IXGRP)?'x':'-',
164 (haattr&HA_IROTH)?'r':'-',
165 (haattr&HA_IWOTH)?'w':'-',
166 (haattr&HA_ISVTX)?(haattr&
167 HA_IXOTH)?'t':'T':(haattr&HA_IXOTH)?'x':'-'
168 );
169 return as;
170 }
171
md_gethdr(int len,int mode)172 void md_gethdr(int len, int mode) {
173
174 static int longest=0;
175 static unsigned char *buf=NULL;
176
177 if (len>longest) {
178 if (buf!=NULL) buf=realloc(buf,len);
179 else buf=malloc(len);
180 if (buf==NULL) error(1,ERR_MEM,"md_gethdr()");
181 longest=len;
182 }
183 read(arcfile,buf,len);
184 mdhd.mtype=buf[0];
185 if (mdhd.mtype==UNIXMDH) {
186 mdhd.attr=buf[1]|(buf[2]<<8);
187 mdhd.user=buf[3]|(buf[4]<<8);
188 mdhd.group=buf[5]|(buf[6]<<8);
189 }
190 else {
191 switch (mode) {
192 case M_DIR:
193 mdhd.attr=md_tohaattr(DEF_DIRATTR);
194 mdhd.attr|=HA_IFDIR;
195 break;
196 default:
197 mdhd.attr=md_tohaattr(DEF_FILEATTR);
198 break;
199 }
200 }
201 }
202
md_puthdr(void)203 void md_puthdr(void) {
204
205 unsigned char buf[MDHDLEN];
206
207 buf[0]=UNIXMDH;
208 buf[1]=mdhd.attr&0xff;
209 buf[2]=(mdhd.attr>>8)&0xff;
210 buf[3]=mdhd.user&0xff;
211 buf[4]=(mdhd.user>>8)&0xff;
212 buf[5]=mdhd.group&0xff;
213 buf[6]=(mdhd.group>>8)&0xff;
214 write(arcfile,buf,MDHDLEN);
215 }
216
md_filetype(char * path,char * name)217 int md_filetype(char *path, char *name) {
218
219 char *fullpath;
220
221 if (!strcmp(name,".") || !strcmp(name,"..")) return T_SKIP;
222 fullpath=md_pconcat(0,path,name);
223 if (lstat(fullpath,&filestat)<0) {
224 error(0,ERR_STAT,fullpath);
225 free(fullpath);
226 return T_SKIP;
227 }
228 free(fullpath);
229 if (filestat.st_ino==arcstat.st_ino) return T_SKIP;
230 if (S_ISDIR(filestat.st_mode)) return T_DIR;
231 if (S_ISREG(filestat.st_mode)) return T_REGULAR;
232 return T_SPECIAL;
233 }
234
md_newfile(void)235 int md_newfile(void) {
236
237 mdhd.attr=md_tohaattr(filestat.st_mode);
238 mdhd.user=filestat.st_uid;
239 mdhd.group=filestat.st_gid;
240 return MDHDLEN;
241 }
242
md_special(char * fullname,unsigned char ** sdata)243 int md_special(char *fullname, unsigned char **sdata) {
244
245 static unsigned char *dat=NULL;
246 int len;
247
248 if (dat!=NULL) {
249 free(dat);
250 dat=NULL;
251 }
252 if (HA_ISCHR(mdhd.attr)||HA_ISBLK(mdhd.attr)) {
253 if ((dat=malloc(sizeof(dev_t)))==NULL) error(1,ERR_MEM,"md_special()");
254 *(dev_t*)dat=filestat.st_rdev;
255 *sdata=dat;
256 return sizeof(dev_t);
257 }
258 if (HA_ISLNK(mdhd.attr)) {
259 if ((dat=malloc(1024))==NULL) error(1,ERR_MEM,"md_special()");
260 if ((len=readlink(fullname,(char*)dat,1024))<0)
261 error(1,ERR_RDLINK,fullname);
262 dat[len]=0;
263 *sdata=dat;
264 return len+1;
265 }
266 else {
267 *sdata=dat;
268 return 0;
269 }
270 }
271
md_mkspecial(char * ofname,unsigned sdlen,unsigned char * sdata)272 int md_mkspecial(char *ofname,unsigned sdlen,unsigned char *sdata) {
273
274 if (mdhd.mtype!=UNIXMDH) {
275 error(0,ERR_HOW,ofname);
276 return 0;
277 }
278 if (HA_ISCHR(mdhd.attr)) {
279 mknod(ofname,md_tomdattr(mdhd.attr)|S_IFCHR,*(dev_t*)sdata);
280 if (useattr) chown(ofname,mdhd.user,mdhd.group);
281 return 1;
282 }
283 else if (HA_ISBLK(mdhd.attr)) {
284 mknod(ofname,md_tomdattr(mdhd.attr)|S_IFBLK,*(dev_t*)sdata);
285 if (useattr) chown(ofname,mdhd.user,mdhd.group);
286 return 1;
287 }
288 #ifdef S_ISLNK
289 else if (HA_ISLNK(mdhd.attr)) {
290 if (symlink(ofname,(char*)sdata)<0) error(0,ERR_MKLINK,sdata,ofname);
291 if (useattr) {
292 chmod(ofname,md_tomdattr(mdhd.attr));
293 chown(ofname,mdhd.user,mdhd.group);
294 }
295 return 1;
296 }
297 #endif
298 #ifdef S_ISFIFO
299 else if (HA_ISFIFO(mdhd.attr)) {
300 if (mkfifo(ofname,md_tomdattr(mdhd.attr))<0)
301 error(0,ERR_MKFIFO,sdata,ofname);
302 if (useattr) chown(ofname,mdhd.user,mdhd.group);
303 return 1;
304 }
305 #endif
306 error(0,ERR_HOW,ofname);
307 return 0;
308 }
309
md_setfattrs(char * file)310 void md_setfattrs(char *file) {
311
312 if (useattr) {
313 chmod(file,md_tomdattr(mdhd.attr));
314 chown(file,mdhd.user,mdhd.group);
315 }
316 }
317
md_setft(char * file,U32B time)318 void md_setft(char *file,U32B time) {
319
320 struct utimbuf utb;
321
322 utb.actime=time;
323 utb.modtime=time;
324 utime(file,&utb);
325 }
326
md_listhdr(void)327 void md_listhdr(void) {
328
329 printf("\n attr");
330 }
331
md_listdat(void)332 void md_listdat(void) {
333
334 printf("\n %s",attrstring(mdhd.attr));
335 }
336
md_timestring(unsigned long t)337 char *md_timestring(unsigned long t) {
338
339 static char ts[22];
340 struct tm *tim;
341
342 tim=localtime((long *)&t);
343 sprintf(ts,"%04d-%02d-%02d %02d:%02d",tim->tm_year+1900,tim->tm_mon+1,
344 tim->tm_mday,tim->tm_hour,tim->tm_min);
345 return ts;
346 }
347
md_arcname(char * name_req)348 char *md_arcname(char *name_req) {
349
350 int pos;
351 char *newname;
352
353 pos=strlen(name_req);
354 if (pos>3 &&
355 tolower(name_req[pos-1])=='a' &&
356 tolower(name_req[pos-2])=='h' &&
357 name_req[pos-3]=='.') return name_req;
358 if ((newname=malloc(pos+4))==NULL) error(1,ERR_MEM,"md_arcname()");
359 strcpy(newname,name_req);
360 strcpy(newname+pos,".ha");
361 return newname;
362 }
363
md_truncfile(int fh,U32B len)364 void md_truncfile(int fh, U32B len) {
365
366 ftruncate(fh,len);
367 }
368
md_tohapath(char * mdpath)369 char *md_tohapath(char *mdpath) {
370
371 int i,j;
372 static char *hapath=NULL;
373
374 if (hapath!=NULL) free(hapath),hapath=NULL;
375 j=strlen(mdpath);
376 for (i=0;mdpath[i];++i) if (mdpath[i]!='.' && mdpath[i]!='/') break;
377 while (i>0 && mdpath[i-1]=='.') --i;
378 if (i==0) skipemptypath=1;
379 else skipemptypath=0;
380 if ((hapath=malloc(j+1-i))==NULL) error(1,ERR_MEM,"md_tohapath()");
381 copy_path_relative(hapath, mdpath+i, sizeof(hapath));
382 for (i=0;hapath[i];++i) if (hapath[i]=='/') hapath[i]=0xff;
383 return md_strcase(hapath);
384 }
385
md_tomdpath(char * hapath)386 char *md_tomdpath(char *hapath) {
387
388 int i;
389 static char *mdpath=NULL;
390
391 if (mdpath!=NULL) free(mdpath),mdpath=NULL;
392 if ((mdpath=malloc(strlen(hapath)+1))==NULL)
393 error(1,ERR_MEM,"md_tomdpath()");
394 /* Kludge to avoid temp string allocation */
395 for (i=0;hapath[i];++i) if (hapath[i]==0xff) hapath[i]='/';
396 copy_path_relative(mdpath, hapath, sizeof(mdpath));
397 for (i=0;hapath[i];++i) if (hapath[i]=='/') hapath[i]=0xff;
398 return mdpath;
399 }
400
md_strippath(char * mdfullpath)401 char *md_strippath(char *mdfullpath) {
402
403 int i;
404 static char *plainpath=NULL;
405
406 if (plainpath!=NULL) free(plainpath),plainpath=NULL;
407 if ((plainpath=malloc(strlen(mdfullpath)+1))==NULL)
408 error(1,ERR_MEM,"md_strippath()");
409 strcpy(plainpath,mdfullpath);
410 for (i=strlen(plainpath)-1;i>=0;i--) {
411 if (plainpath[i]=='/') break;
412 }
413 plainpath[i+1]=0;
414 return plainpath;
415 }
416
md_stripname(char * mdfullpath)417 char *md_stripname(char *mdfullpath) {
418
419 int i;
420 static char *plainname=NULL;
421
422 if (plainname!=NULL) free(plainname),plainname=NULL;
423 if ((plainname=malloc(strlen(mdfullpath)+1))==NULL)
424 error(1,ERR_MEM,"md_stripname()");
425 for (i=strlen(mdfullpath)-1;i>0;i--) {
426 if (mdfullpath[i]=='/') {
427 i++;
428 break;
429 }
430 }
431 strcpy(plainname,mdfullpath+i);
432 return plainname;
433 }
434
md_pconcat(int delim2,char * head,char * tail)435 char *md_pconcat(int delim2, char *head, char *tail) {
436
437 char *newpath;
438 int headlen,delim1;
439
440 delim1=0;
441 if ((headlen=strlen(head))!=0) {
442 if (head[headlen-1]!='/') delim1=1;
443 }
444 if ((newpath=malloc(headlen+strlen(tail)+delim2+delim1+1))==NULL)
445 error(1,ERR_MEM,"md_pconcat()");
446 if (headlen!=0) strcpy(newpath,head);
447 if (delim1) newpath[headlen]='/';
448 strcpy(newpath+headlen+delim1,tail);
449 if (delim2) strcpy(newpath+strlen(newpath),"/");
450 return newpath;
451 }
452
md_namecmp(char * pat,char * cmp)453 int md_namecmp(char *pat, char *cmp) {
454
455 if (*pat==0) return !*cmp;
456 if (*pat=='?') {
457 if (!*cmp) return 0;
458 return md_namecmp(pat+1,cmp+1);
459 }
460 if (*pat=='*') {
461 if (*(pat+1)==0) return 1;
462 for (;*cmp;++cmp) {
463 if (md_namecmp(pat+1,cmp)) return 1;
464 }
465 return 0;
466 }
467 if (*pat=='\\') {
468 ++pat;
469 if (*pat==0) return 0;
470 }
471 if (*pat==*cmp) return md_namecmp(pat+1,cmp+1);
472 return 0;
473 }
474
475
476
477