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