1 #ifndef LINT
2 /* @(#) misc2.c 2.7 88/01/24 12:47:36 */
3 static char sccsid[]="@(#) misc2.c 2.7 88/01/24 12:47:36";
4 #endif /* LINT */
5 
6 /*
7 Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
8 (C) Copyright 1988 Rahul Dhesi -- All rights reserved
9 */
10 #include "options.h"
11 /* Miscellaneous routines */
12 #include "portable.h"
13 #include "zooio.h"
14 #include "various.h"
15 #include "errors.i"
16 #include "zoomem.h"
17 #include "zoo.h"
18 #include "zoofns.h"     /* only for malloc */
19 
20 void makepath PARMS((char *));
21 
22 /**********************/
23 /* memerr() */
24 /* Give error message on memory error and abort */
memerr(i)25 void memerr(i)
26 unsigned int i;
27 {
28 #ifdef OOZ
29    prterror ('f', no_memory, "", "");
30 #else
31 	if (i != 0)
32 		prterror ('f', no_memory);
33 	else
34 		prterror('f', "needed %u bytes: %s", no_memory);
35 #endif
36 }
37 
38 /**********************/
39 /*
40 emalloc() allocates memory like malloc() does (and it calls malloc).  However,
41 it automatically calls the error function memerr() if memory couldn't be
42 allocated.  It also assumes that memory will never be freed and conserves it
43 by allocating memory in large chunks and then partitioning it out with no
44 administrative overhead.  This avoids many problems due to various bugs in
45 various implementations of malloc, and also avoids a very high amount of
46 malloc overhead for repeated allocations to store numerous filenames etc.
47 The down side is that we can't use free().
48 
49 WARNING:  No alignment of allocated memory is attempted, so memory
50 allocated through emalloc should be used only for storing strings.
51 For allocating memory for other data types use ealloc().  */
52 
emalloc(size)53 VOIDPTR emalloc (size)
54 unsigned int size;
55 {
56 #define  BLOCK_SIZE  512      /* memory allocation granularity */
57 
58 #ifdef USE_MALLOC
59 /* Pass on memory requests to malloc() */
60    char *ptr;
61    if ((ptr = malloc (size)) == NULL)
62       memerr(size);
63    return (ptr);
64 #else
65    static char *memptr;
66    static unsigned avail = 0;
67    unsigned malloc_incr;
68    char *retval;
69 
70    if (size == 0)
71       return (NULL);
72 
73    /* if not enough space avail get some more */
74    if (avail < size) {
75       malloc_incr = BLOCK_SIZE;
76       if (malloc_incr < size)
77          malloc_incr = size;
78       while (malloc_incr >= size && (memptr = malloc (malloc_incr)) == NULL)
79          malloc_incr = (malloc_incr / 6) * 5;
80       avail = malloc_incr;
81    }
82 
83    if (avail < size)
84       memerr(size);                             /* no return from this */
85    retval = memptr;
86    memptr += size;
87    avail -= size;
88    return (retval);
89 #endif  /* end of not USE_MALLOC */
90 }
91 
92 /**********************/
93 /*
94 ealloc() is just a wrapper around malloc(), which causes memerr() to be
95 called if memory cannot be allocated.  All memory requests are passed on
96 to malloc.   Allocated memory can later be freed.  */
97 
ealloc(size)98 VOIDPTR ealloc(size)
99 unsigned int size;
100 {
101    char *ptr;
102    if ((ptr = malloc (size)) == NULL)
103       memerr(size);
104    return ptr;
105 }
106 
107 /**********************/
108 /* erealloc() is a wrapper around realloc() the way ealloc is a wrapper
109 around malloc().  It calls memerr() on error. */
110 
erealloc(p,size)111 VOIDPTR erealloc(p, size)
112 VOIDPTR p;
113 unsigned int size;
114 {
115    char *ptr;
116    if ((ptr = realloc (p, size)) == NULL)
117       memerr(size);
118    return ptr;
119 }
120 
121 /**********************/
122 /* putstr()
123 This function prints a string to standard output.  If the received
124 string pointer is NULL, it is handled safely.  This function is here
125 for historical reasons:  Ooz was once coded to not use printf under
126 MSDOS to save space, and at that time putstr() printed a string
127 without using printf.  It should eventually be eliminated and all
128 calls to it replaced with calls to printf directly.
129 */
putstr(str)130 void putstr (str)
131 register char *str;
132 {
133    if (str == NULL)
134       return;
135 	printf ("%s", str);
136 }
137 
138 /**********************/
139 /* exists()
140 This function checks the existence of a file.
141 
142 If the symbol EXISTS is defined, that is called as a macro and
143 supplied the filename.  It must return 1 if the file exists and
144 0 if it does not.
145 
146 If EXISTS is not defined, exists() tests to see if the file can be
147 opened for reading or writing;  if so, it returns 1 else it returns 0.
148 
149 Because of the delay between the time existence is checked and the time Zoo
150 creates a files, a race condition exists.  It would be better to
151 use open() with the O_EXCL flag but that will not work for many
152 systems.
153 */
154 
exists(fname)155 int exists (fname)
156 char *fname;
157 {
158 #ifdef EXISTS
159 	return EXISTS(fname);
160 #else
161    ZOOFILE f;
162 
163    if ( (f = zooopen (fname, Z_READ )) != NOFILE ||
164 		  (f = zooopen (fname, Z_WRITE)) != NOFILE ) {
165       zooclose (f);
166       return (1);
167    } else
168       return (0);
169 #endif /* ifdef EXISTS */
170 }
171 
172 /****************
173 newcat() allocates enough space to concatenate two strings then returns
174 a pointer to the concatenated result */
175 
newcat(r,s)176 char *newcat (r, s)
177 char *r, *s;
178 {
179    char *temp = emalloc (strlen (r) + strlen (s) + 2); /* 1 spare */
180    strcpy (temp, r);
181    strcat (temp, s);
182    return (temp);
183 }
184 
185 
186 /* Creates a path */
makepath(path)187 void makepath(path)
188 char *path;
189 {
190    char tmppath[PATHSIZE];
191    char *slashpos;
192    if (path == NULL)
193       return;
194    while (*lastptr(path) == *(char *) PATH_CH)  /* remove trailing slashes */
195       *lastptr(path) = '\0';
196    if (*path == '\0')
197       return;
198 
199    slashpos = findlast(path, PATH_CH);    /* find last slash */
200    if (slashpos == NULL) {                /* if not, just create dir. */
201       MKDIR(path);
202       return;
203    } else {                               /* otherwise...         */
204       if (slashpos == path) {             /* if leading slash */
205          MKDIR(slashpos);                 /* make that directory */
206          return;                          /* and done */
207       } else {
208          strcpy(tmppath,path);            /* save path */
209          *slashpos = '\0';                /* split into prefix & suffix */
210 #ifdef DEBUG
211          printf("making path from [%s]\n", path);
212 #endif
213          makepath(path);                     /* make path from prefix */
214 #ifdef DEBUG
215          printf("making dir from [%s]\n", tmppath);
216 #endif
217          MKDIR(tmppath);                  /* make dir from suffix */
218       }
219    }
220 } /* makepath() */
221 
222 /*
223 If no extension in filename add supplied extension
224 */
addext(fname,ext)225 char *addext (fname, ext)
226 char *fname;
227 char *ext;
228 {
229    if (strchr (nameptr (fname), EXT_CH) == NULL)
230       return (newcat (fname, ext));
231    else
232       return (fname);
233 }
234 
235 #ifdef VER_CH       /* remove any trailing extension field */
strip_ver(fname)236 char *strip_ver (fname)
237 char *fname;
238 {
239    char *p = strchr (fname, VER_CH);
240    if (p != NULL)
241       *p = '\0';
242 }
243 #endif
244 
245 /*
246 Function samefile() compares two filenames to see if they are the
247 same file.  Just strcmp() or str_icmp() could have been used, except
248 that if the filenames have trailing version fields, we want to
249 compare those always equal.  samefile() is called by routines
250 that want to avoid adding an archive to itself.
251 */
samefile(f1,f2)252 int samefile (f1, f2)
253 char *f1;
254 char *f2;
255 {
256 #ifdef IGNORECASE
257 #define COMPARE str_icmp
258 #else
259 #define COMPARE strcmp
260 #endif
261 
262 #ifdef VER_CH
263    char tf1[LFNAMESIZE];
264    char tf2[LFNAMESIZE];
265    strcpy (tf1, f1);
266    strcpy (tf2, f2);
267    strip_ver (tf1);   /* strip version fields */
268    strip_ver (tf2);
269    return (COMPARE (tf1, tf2) == 0);
270 #else
271 /* if no version fields, just use strcmp(i) */
272    return (COMPARE (f1, f2) == 0);
273 #endif
274 }
275 
276 #ifdef USE_ASCII
isdigit(c)277 int isdigit (c)
278 int c;
279 {
280 	return (c >= '0' && c <= '9');
281 }
isupper(c)282 int isupper (c)
283 int c;
284 {
285 	return (c >= 'A' && c <= 'Z');
286 }
287 
toascii(c)288 int toascii (c)
289 int c;
290 {
291 	return (c & 0x7f);
292 }
293 
tolower(c)294 int tolower (c)
295 int c;
296 {
297 	return (isupper(c) ? (c | 0x20) : c);
298 }
299 #endif
300 
301 #ifdef GETTZ
302 /****************
303 Function tzadj() accepts a directory entry and adjusts its timestamp
304 to reflect its timezone.  Uses function mstime() from mstime.i
305 and mstonix() from nixtime.i.
306 */
307 
308 long mstonix();
309 long gettz();
310 #include "mstime.i"	/* get mstime() */
311 
tzadj(direntry)312 void tzadj (direntry)
313 struct direntry *direntry;
314 {
315 	long diff_tz;
316 	long longtime;
317 	long t;
318 	if (direntry->tz == NO_TZ)		/* none stored */
319 		return;
320 	t = mstonix (direntry->date, direntry->time);
321 	diff_tz = (long) direntry->tz * (3600/4) - gettz(t); /* diff. in seconds */
322 	longtime = t + diff_tz; /* adj tz */
323 	mstime (longtime, &direntry->date, &direntry->time);
324 }
325 #endif /* GETTZ */
326 
327 /* how long an int can be in text form -- allow 64-bit ints */
328 #define INT_TEXT 21
329 
330 /* Function add_version adds a version suffix to a filename, given
331 the directory entry corresponding to the file */
add_version(fname,direntry)332 void add_version (fname, direntry)
333 char *fname;
334 struct direntry *direntry;
335 {
336 	char verstr[INT_TEXT];	/* string buffer for conversion to text */
337 	if (direntry->vflag & VFL_ON) {
338 		sprintf (verstr, "%u", direntry->version_no);
339 		strcat (fname, VER_DISPLAY);
340 		strcat (fname, verstr);
341 	}
342 }
343