1/* 2 Copyright (c) 1990-1999 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 1999-Oct-05 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, both of these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html 8*/ 9#include "zip.h" 10 11#include <time.h> 12#include <stdio.h> 13#include <dirent.h> 14#ifndef UTIL 15#include <sys/dos.h> 16#endif 17 18#define MATCH shmatch 19 20#define PAD 0 21 22 23#ifndef UTIL 24 25/* Library functions not in (most) header files */ 26 27int utime OF((char *, ztimbuf *)); 28 29/* Local functions */ 30local char *readd OF((DIR *)); 31 32local char *readd(DIR* d) 33{ 34 struct dirent* e = readdir(d); 35 36 return e == NULL ? NULL : e->d_name; 37} 38 39int wild(char* w) 40{ 41 struct _filbuf inf; 42 /* convert FNAMX to malloc - 11/08/04 EG */ 43 char *name; 44 char *p; 45 46 if (strcmp(w, "-") == 0) /* if compressing stdin */ 47 return newname(w, 0, 0); 48 if ((name = malloc(strlen(w) + 1)) == NULL) { 49 ZIPERR(ZE_MEM, "wild"); 50 } 51 strcpy(name, w); 52 _toslash(name); 53 54 if ((p = strrchr(name, '/')) == NULL && (p = strrchr(name, ':')) == NULL) 55 p = name; 56 else 57 p++; 58 if (_dos_lfiles (&inf, w, 0xff) < 0) { 59 free(name); 60 return ZE_MISS; 61 } 62 do { 63 int r; 64 65 strcpy(p, inf.name); 66 r = procname(name, 0); 67 if (r != ZE_OK) { 68 free(name); 69 return r; 70 } 71 } while (_dos_nfiles(&inf) >= 0); 72 free(name); 73 74 return ZE_OK; 75} 76 77int procname(n, caseflag) 78char *n; /* name to process */ 79int caseflag; /* true to force case-sensitive match */ 80/* Process a name or sh expression to operate on (or exclude). Return 81 an error code in the ZE_ class. */ 82{ 83 char *a; /* path and name for recursion */ 84 DIR *d; /* directory stream from opendir() */ 85 char *e; /* pointer to name from readd() */ 86 int m; /* matched flag */ 87 char *p; /* path for recursion */ 88 struct stat s; /* result of stat() */ 89 struct zlist far *z; /* steps through zfiles list */ 90 91 if (strcmp(n, "-") == 0) /* if compressing stdin */ 92 return newname(n, 0, caseflag); 93 else if (LSSTAT(n, &s)) 94 { 95 /* Not a file or directory--search for shell expression in zip file */ 96 p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */ 97 m = 1; 98 for (z = zfiles; z != NULL; z = z->nxt) { 99 if (MATCH(p, z->iname, caseflag)) 100 { 101 z->mark = pcount ? filter(z->zname, caseflag) : 1; 102 if (verbose) 103 fprintf(mesg, "zip diagnostic: %scluding %s\n", 104 z->mark ? "in" : "ex", z->name); 105 m = 0; 106 } 107 } 108 free((zvoid *)p); 109 return m ? ZE_MISS : ZE_OK; 110 } 111 112 /* Live name--use if file, recurse if directory */ 113 _toslash(n); 114 if ((s.st_mode & S_IFDIR) == 0) 115 { 116 /* add or remove name of file */ 117 if ((m = newname(n, 0, caseflag)) != ZE_OK) 118 return m; 119 } else { 120 /* Add trailing / to the directory name */ 121 if ((p = malloc(strlen(n)+2)) == NULL) 122 return ZE_MEM; 123 if (strcmp(n, ".") == 0) { 124 *p = '\0'; /* avoid "./" prefix and do not create zip entry */ 125 } else { 126 strcpy(p, n); 127 a = p + strlen(p); 128 if (a[-1] != '/') 129 strcpy(a, "/"); 130 if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) { 131 free((zvoid *)p); 132 return m; 133 } 134 } 135 /* recurse into directory */ 136 if (recurse && (d = opendir(n)) != NULL) 137 { 138 while ((e = readd(d)) != NULL) { 139 if (strcmp(e, ".") && strcmp(e, "..")) 140 { 141 if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL) 142 { 143 closedir(d); 144 free((zvoid *)p); 145 return ZE_MEM; 146 } 147 strcat(strcpy(a, p), e); 148 if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */ 149 { 150 if (m == ZE_MISS) 151 zipwarn("name not matched: ", a); 152 else 153 ziperr(m, a); 154 } 155 free((zvoid *)a); 156 } 157 } 158 closedir(d); 159 } 160 free((zvoid *)p); 161 } /* (s.st_mode & S_IFDIR) == 0) */ 162 return ZE_OK; 163} 164 165char *ex2in(x, isdir, pdosflag) 166char *x; /* external file name */ 167int isdir; /* input: x is a directory */ 168int *pdosflag; /* output: force MSDOS file attributes? */ 169/* Convert the external file name to a zip file name, returning the malloc'ed 170 string or NULL if not enough memory. */ 171{ 172 char *n; /* internal file name (malloc'ed) */ 173 char *t; /* shortened name */ 174 175 /* Find starting point in name before doing malloc */ 176 t = (x[0] && x[1] == (char)':') ? x + 2 : x; 177 while (*t == (char)'/') 178 t++; 179 180 /* Make changes, if any, to the copied name (leave original intact) */ 181 _toslash(t); 182 183 if (!pathput) 184 t = last(t, '/'); 185 186 /* Malloc space for internal name and copy it */ 187 if ((n = malloc(strlen(t) + 1)) == NULL) 188 return NULL; 189 strcpy(n, t); 190 191 if (dosify) 192 msname(n); 193 /* Returned malloc'ed name */ 194 if (pdosflag) 195 *pdosflag = dosify; 196 return n; 197} 198 199 200char *in2ex(n) 201char *n; /* internal file name */ 202/* Convert the zip file name to an external file name, returning the malloc'ed 203 string or NULL if not enough memory. */ 204{ 205 char *x; /* external file name */ 206 if ((x = malloc(strlen(n) + 1 + PAD)) == NULL) 207 return NULL; 208 return strcpy(x, n); 209} 210 211void stamp(f, d) 212char *f; /* name of file to change */ 213ulg d; /* dos-style time to change it to */ 214/* Set last updated and accessed time of file f to the DOS time d. */ 215{ 216 ztimbuf u; /* argument for utime() */ 217 218 /* Convert DOS time to time_t format in u */ 219 u.actime = u.modtime = dos2unixtime(d); 220 221 /* Set updated and accessed times of f */ 222 utime(f, &u); 223} 224 225ulg filetime(f, a, n, t) 226char *f; /* name of file to get info on */ 227ulg *a; /* return value: file attributes */ 228long *n; /* return value: file size */ 229iztimes *t; /* return value: access, modific. and creation times */ 230/* If file *f does not exist, return 0. Else, return the file's last 231 modified date and time as an MSDOS date and time. The date and 232 time is returned in a long with the date most significant to allow 233 unsigned integer comparison of absolute times. Also, if a is not 234 a NULL pointer, store the file attributes there, with the high two 235 bytes being the Unix attributes, and the low byte being a mapping 236 of that to DOS attributes. If n is not NULL, store the file size 237 there. If t is not NULL, the file's access, modification and creation 238 times are stored there as UNIX time_t values. 239 If f is "-", use standard input as the file. If f is a device, return 240 a file size of -1 */ 241{ 242 struct stat s; /* results of stat() */ 243 /* convert FNMAX to malloc - 11/8/04 EG */ 244 char *name; 245 int len = strlen(f); 246 isstdin = !strcmp(f, "-"); 247 248 if ((name = malloc(len + 1)) == NULL) { 249 ZIPERR(ZE_MEM, "filetime"); 250 } 251 strcpy(name, f); 252 if (name[len - 1] == '/') 253 name[len - 1] = '\0'; 254 /* not all systems allow stat'ing a file with / appended */ 255 256 if (isstdin) { 257 if (fstat(fileno(stdin), &s) != 0) { 258 free(name); 259 error("fstat(stdin)"); 260 } 261 } else if (LSSTAT(name, &s) != 0) { 262 /* Accept about any file kind including directories 263 * (stored with trailing / with -r option) 264 */ 265 free(name); 266 return 0; 267 } 268 269 if (a != NULL) { 270 int atr = _dos_chmod(name, -1); 271 272 if (atr < 0) 273 atr = 0x20; 274 *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)atr); 275 } 276 free(name); 277 if (n != NULL) 278 *n = S_ISVOL(s.st_mode) ? -2L : S_ISREG(s.st_mode) ? s.st_size : -1L; 279 if (t != NULL) { 280 t->atime = s.st_atime; 281 t->mtime = s.st_mtime; 282 t->ctime = s.st_ctime; 283 } 284 285 return unix2dostime(&s.st_mtime); 286} 287 288int set_extra_field(z, z_utim) 289 struct zlist far *z; 290 iztimes *z_utim; 291 /* create extra field and change z->att if desired */ 292{ 293#ifdef USE_EF_UT_TIME 294 if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL) 295 return ZE_MEM; 296 297 z->extra[0] = 'U'; 298 z->extra[1] = 'T'; 299 z->extra[2] = EB_UT_LEN(1); /* length of data part of e.f. */ 300 z->extra[3] = 0; 301 z->extra[4] = EB_UT_FL_MTIME; 302 z->extra[5] = (char)(z_utim->mtime); 303 z->extra[6] = (char)(z_utim->mtime >> 8); 304 z->extra[7] = (char)(z_utim->mtime >> 16); 305 z->extra[8] = (char)(z_utim->mtime >> 24); 306 307 z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1)); 308 z->cextra = z->extra; 309 310 return ZE_OK; 311#else /* !USE_EF_UT_TIME */ 312 return (int)(z-z); 313#endif /* ?USE_EF_UT_TIME */ 314} 315 316int deletedir(d) 317char *d; /* directory to delete */ 318/* Delete the directory *d if it is empty, do nothing otherwise. 319 Return the result of rmdir(), delete(), or system(). 320 For VMS, d must be in format [x.y]z.dir;1 (not [x.y.z]). 321 */ 322{ 323 return rmdir(d); 324} 325 326void print_period(void) 327{ 328 fputc('.', stderr); 329} 330 331#endif /* !UTIL */ 332 333 334/******************************/ 335/* Function version_local() */ 336/******************************/ 337 338void version_local() 339{ 340 static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; 341#if 0 342 char buf[40]; 343#endif 344 345 printf(CompiledWith, 346 347#ifdef __GNUC__ 348 "gcc ", __VERSION__, 349#else 350# if 0 351 "cc ", (sprintf(buf, " version %d", _RELEASE), buf), 352# else 353 "unknown compiler", "", 354# endif 355#endif 356 357 "Human68k", 358#ifdef __MC68020__ 359 " (X68030)", 360#else 361 " (X680x0)", 362#endif 363 364#ifdef __DATE__ 365 " on ", __DATE__ 366#else 367 "", "" 368#endif 369 ); 370 371} /* end function version_local() */ 372