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