theos.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
  3. See the accompanying file LICENSE, version 1999-Oct-05 or later
  4. (the contents of which are also included in zip.h) for terms of use.
  5. If, for some reason, both of these files are missing, the Info-ZIP license
  6. also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
  7. */
  8. /*---------------------------------------------------------------------------
  9. theos.c (zip)
  10. Contribution by Jean-Michel Dubois. 20-Jun-1995, 20-Dec-98
  11. THEOS specific extra informations
  12. ---------------------------------------------------------------------------*/
  13. #include <stdio.h>
  14. #ifndef UTIL
  15. #include "zip.h"
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include <time.h>
  19. #include <sc.h>
  20. #include <direct.h>
  21. #include <sys/utime.h>
  22. #define opendir(a) _opendir(a)
  23. extern struct dirent* _opendir(char* fname);
  24. #define PAD 0
  25. #define RET_ERROR 1
  26. #define RET_SUCCESS 0
  27. #define RET_EOF 0
  28. extern char *label;
  29. local ulg label_time = 0;
  30. local ulg label_mode = 0;
  31. local time_t label_utim = 0;
  32. /* match from Phase One Systems */
  33. int match(char *s, char *p) /*S Returns non-zero if string matches
  34. the literal mask */
  35. {
  36. int matched, k;
  37. if (!(*p))
  38. return 1;
  39. for(;;) {
  40. if ( (!(*s)) && (!(*p)) )
  41. return(1);
  42. else if ( !(*p) )
  43. return(0);
  44. else if (*p == '*') {
  45. if (!*(p+1))
  46. return(1);
  47. k=0;
  48. do {
  49. matched = match(s+k,p+1);
  50. k++;
  51. } while ( (!matched) && *(s+k));
  52. return(matched);
  53. } else if (*p == '@') {
  54. if (!((*s >= 'a' && *s <= 'z')
  55. ||(*s >= 'A' && *s <= 'Z')))
  56. return(0);
  57. } else if (*p == '#') {
  58. if (*s < '0' || *s > '9')
  59. return(0);
  60. } else if (*p != '?') {
  61. if (tolower(*s) != tolower(*p))
  62. return(0);
  63. }
  64. s++; p++;
  65. }
  66. }
  67. local char *readd(d)
  68. DIR *d; /* directory stream to read from */
  69. /* Return a pointer to the next name in the directory stream d, or NULL if
  70. no more entries or an error occurs. */
  71. {
  72. struct dirent *e;
  73. e = readdir(d);
  74. return e == NULL ? (char *) NULL : e->d_name;
  75. }
  76. /* check if file is a member of a library */
  77. int ismember(char* path)
  78. {
  79. char* p;
  80. if ((p = strrchr(path, '/')) == NULL)
  81. p = path;
  82. return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));
  83. }
  84. /* extract library name from a file name */
  85. char* libname(char* path)
  86. {
  87. char* p;
  88. static char lib[FILENAME_MAX];
  89. char drive[3];
  90. strcpy(lib, path);
  91. if (p = strrchr(lib, ':')) {
  92. strncpy(drive, p, 2);
  93. drive[2] = '\0';
  94. *p = '\0' ;
  95. } else
  96. drive[0] = '\0';
  97. if ((p = strrchr(lib, '/')) == NULL)
  98. p = lib;
  99. p = strchr(p, '.');
  100. p = strchr(p + 1, '.');
  101. *p = 0;
  102. strcat(lib, drive);
  103. return lib;
  104. }
  105. int procname(n, caseflag)
  106. char *n; /* name to process */
  107. int caseflag; /* true to force case-sensitive match */
  108. /* Process a name or sh expression to operate on (or exclude). Return
  109. an error code in the ZE_ class. */
  110. {
  111. char *a; /* path and name for recursion */
  112. DIR *d; /* directory stream from opendir() */
  113. char *e; /* pointer to name from readd() */
  114. int m; /* matched flag */
  115. char *p; /* path for recursion */
  116. struct stat s; /* result of stat() */
  117. struct zlist *z; /* steps through zfiles list */
  118. struct flist *f; /* steps through files list */
  119. char* path; /* full name */
  120. char drive[3]; /* drive name */
  121. int recursion; /* save recurse flag */
  122. if (strcmp(n, "-") == 0) /* if compressing stdin */
  123. return newname(n, 0, caseflag);
  124. else if (LSSTAT(n, &s)) {
  125. /* Not a file or directory--search for shell expression in zip file */
  126. p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */
  127. m = 1;
  128. for (z = zfiles; z != NULL; z = z->nxt) {
  129. if (match(z->iname, p))
  130. {
  131. z->mark = pcount ? filter(z->zname, caseflag) : 1;
  132. if (verbose)
  133. fprintf(mesg, "zip diagnostic: %scluding %s\n",
  134. z->mark ? "in" : "ex", z->name);
  135. m = 0;
  136. }
  137. }
  138. free((zvoid *)p);
  139. return m ? ZE_MISS : ZE_OK;
  140. }
  141. /* Live name--use if file, recurse if directory or library */
  142. if (S_ISREG(s.st_mode)) {
  143. if ((path = malloc(strlen(n) + 2)) == NULL)
  144. return ZE_MEM;
  145. strcpy(path, n);
  146. /* if member name, include library name before any member name */
  147. if (ismember(path)) {
  148. strcpy(path, libname(path));
  149. /* mask recursion flag to avoid endless loop recursion
  150. * if -r is used with member names
  151. */
  152. recursion = recurse;
  153. recurse = FALSE;
  154. if ((m = procname(path, caseflag)) != ZE_OK) /* recurse on name */
  155. {
  156. if (m == ZE_MISS)
  157. zipwarn("name not matched: ", path);
  158. else
  159. ziperr(m, a);
  160. }
  161. /* restore recursion flag */
  162. recurse = recursion;
  163. }
  164. strcpy(path, n);
  165. if ((p = strchr(path, ':')) != NULL) {
  166. p[2] = '\0';
  167. strcpy(drive, p);
  168. } else
  169. drive[0] = '\0';
  170. /* remove trailing dot in flat file name */
  171. p = strend(path) - 1;
  172. if (*p == '.')
  173. *p = '\0';
  174. strcat(path, drive);
  175. /* add or remove name of file */
  176. if ((m = newname(path, 0, caseflag)) != ZE_OK) {
  177. free(path);
  178. return m;
  179. }
  180. free(path);
  181. } else if (S_ISLIB(s.st_mode)) {
  182. if ((path = malloc(strlen(n) + 2)) == NULL)
  183. return ZE_MEM;
  184. strcpy(path, n);
  185. if ((p = strchr(path, ':')) != NULL) {
  186. p[2] = '\0';
  187. strcpy(drive, p);
  188. } else
  189. drive[0] = '\0';
  190. /* add a trailing dot in flat file name... */
  191. p = strend(path) - 1;
  192. if (*p != '/')
  193. strcat(path, "/");
  194. p = strend(path);
  195. /* ... then add drive name */
  196. strcpy(p, drive);
  197. /* don't include the library name twice... or more */
  198. for (f = found; f != NULL; f = f->nxt) {
  199. if (! stricmp(path, f->name)) {
  200. free(path);
  201. return ZE_OK;
  202. }
  203. }
  204. /* add or remove name of library */
  205. if ((m = newname(path, 0, caseflag)) != ZE_OK) {
  206. free(path);
  207. return m;
  208. }
  209. /* recurse into library if required */
  210. strcpy(p - 1, ".*");
  211. strcat(p, drive);
  212. if (recurse && diropen(path) == 0)
  213. {
  214. while ((e = dirread()) != NULL) {
  215. if (strcmp(e, ".") && strcmp(e, ".."))
  216. {
  217. if (*drive == '\0')
  218. *strchr(e, ':') = '\0';
  219. if ((a = malloc(strlen(e) + 1)) == NULL)
  220. {
  221. dirclose();
  222. free((zvoid *)p);
  223. return ZE_MEM;
  224. }
  225. strcpy(a, e);
  226. if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
  227. {
  228. if (m == ZE_MISS)
  229. zipwarn("name not matched: ", a);
  230. else
  231. ziperr(m, a);
  232. }
  233. free((zvoid *)a);
  234. }
  235. }
  236. dirclose();
  237. }
  238. free(path);
  239. } else {
  240. /* Add trailing / to the directory name */
  241. if ((p = malloc(strlen(n)+2)) == NULL)
  242. return ZE_MEM;
  243. if (strcmp(n, ".") == 0) {
  244. *p = '\0'; /* avoid "./" prefix and do not create zip entry */
  245. } else {
  246. strcpy(p, n);
  247. a = p + strlen(p);
  248. if (a[-1] != '/')
  249. strcpy(a, "/");
  250. if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
  251. free((zvoid *)p);
  252. return m;
  253. }
  254. }
  255. /* recurse into directory */
  256. if (recurse && (d = opendir(n)) != NULL)
  257. {
  258. while ((e = readd(d)) != NULL) {
  259. if (strcmp(e, ".") && strcmp(e, ".."))
  260. {
  261. if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
  262. {
  263. closedir(d);
  264. free((zvoid *)p);
  265. return ZE_MEM;
  266. }
  267. strcat(strcpy(a, p), e);
  268. if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
  269. {
  270. if (m == ZE_MISS)
  271. zipwarn("name not matched: ", a);
  272. else
  273. ziperr(m, a);
  274. }
  275. free((zvoid *)a);
  276. }
  277. }
  278. closedir(d);
  279. }
  280. free((zvoid *)p);
  281. }
  282. return ZE_OK;
  283. }
  284. char *ex2in(x, isdir, pdosflag)
  285. char *x; /* external file name */
  286. int isdir; /* input: x is a directory */
  287. int *pdosflag; /* output: force MSDOS file attributes? */
  288. /* Convert the external file name to a zip file name, returning the malloc'ed
  289. string or NULL if not enough memory. */
  290. {
  291. char *n; /* internal file name (malloc'ed) */
  292. char *t; /* shortened name */
  293. char *p;
  294. int dosflag;
  295. dosflag = dosify; /* default for non-DOS and non-OS/2 */
  296. /* Find starting point in name before doing malloc */
  297. for (t = x; *t == '/'; t++)
  298. ;
  299. /* Make changes, if any, to the copied name (leave original intact) */
  300. if (!pathput)
  301. t = last(t, '/');
  302. /* Malloc space for internal name and copy it */
  303. if ((n = malloc(strlen(t) + 1)) == NULL)
  304. return NULL;
  305. strcpy(n, t);
  306. if (p = strchr(n, ':'))
  307. *p = '\0';
  308. for (p = n; *p = tolower(*p); p++);
  309. if (isdir == 42) return n; /* avoid warning on unused variable */
  310. if (dosify)
  311. msname(n);
  312. /* Returned malloc'ed name */
  313. if (pdosflag)
  314. *pdosflag = dosflag;
  315. return n;
  316. }
  317. char *in2ex(n)
  318. char *n; /* internal file name */
  319. /* Convert the zip file name to an external file name, returning the malloc'ed
  320. string or NULL if not enough memory. */
  321. {
  322. char *x; /* external file name */
  323. if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
  324. return NULL;
  325. strcpy(x, n);
  326. return x;
  327. }
  328. /*
  329. * XXX use ztimbuf in both POSIX and non POSIX cases ?
  330. */
  331. void stamp(f, d)
  332. char *f; /* name of file to change */
  333. ulg d; /* dos-style time to change it to */
  334. /* Set last updated and accessed time of file f to the DOS time d. */
  335. {
  336. struct utimbuf u; /* argument for utime() const ?? */
  337. /* Convert DOS time to time_t format in u */
  338. u.actime = u.modtime = dos2unixtime(d);
  339. utime(f, &u);
  340. }
  341. ulg filetime(f, a, n, t)
  342. char *f; /* name of file to get info on */
  343. ulg *a; /* return value: file attributes */
  344. long *n; /* return value: file size */
  345. iztimes *t; /* return value: access, modific. and creation times */
  346. /* If file *f does not exist, return 0. Else, return the file's last
  347. modified date and time as an MSDOS date and time. The date and
  348. time is returned in a long with the date most significant to allow
  349. unsigned integer comparison of absolute times. Also, if a is not
  350. a NULL pointer, store the file attributes there, with the high two
  351. bytes being the Unix attributes, and the low byte being a mapping
  352. of that to DOS attributes. Bits 8 to 15 contains native THEOS protection
  353. code. If n is not NULL, store the file size there. If t is not NULL,
  354. the file's access, modification and creation times are stored there as
  355. UNIX time_t values. If f is "-", use standard input as the file. If f is
  356. a device, return a file size of -1 */
  357. {
  358. struct stat s; /* results of stat() */
  359. /* from FNMAX to malloc - 11/8/04 EG */
  360. char *name;
  361. int len = strlen(f);
  362. if (f == label) {
  363. if (a != NULL)
  364. *a = label_mode;
  365. if (n != NULL)
  366. *n = -2L; /* convention for a label name */
  367. if (t != NULL)
  368. t->atime = t->mtime = t->ctime = label_utim;
  369. return label_time;
  370. }
  371. if ((name = malloc(len + 1)) == NULL) {
  372. ZIPERR(ZE_MEM, "filetime");
  373. }
  374. strcpy(name, f);
  375. if (name[len - 1] == '/' || name[len - 1] == '.')
  376. name[len - 1] = '\0';
  377. /* not all systems allow stat'ing a file with / appended */
  378. if (strcmp(f, "-") == 0) {
  379. if (fstat(fileno(stdin), &s) != 0) {
  380. free(name);
  381. error("fstat(stdin)");
  382. }
  383. } else if (LSSTAT(name, &s) != 0) {
  384. /* Accept about any file kind including directories
  385. * (stored with trailing / with -r option)
  386. */
  387. free(name);
  388. return 0;
  389. }
  390. free(name);
  391. if (a != NULL) {
  392. *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
  393. if ((s.st_mode & S_IFMT) == S_IFDIR
  394. || (s.st_mode & S_IFMT) == S_IFLIB) {
  395. *a |= MSDOS_DIR_ATTR;
  396. }
  397. /* Map Theos' hidden attribute to DOS's hidden attribute */
  398. if (!(st.st_protect & 0x80))
  399. *a |= MSDOS_HIDDEN_ATTR;
  400. *a |= ((ulg) s.st_protect) << 8;
  401. }
  402. if (n != NULL)
  403. *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
  404. if (t != NULL) {
  405. t->atime = s.st_atime;
  406. t->mtime = s.st_mtime;
  407. t->ctime = t->mtime; /* best guess, (s.st_ctime: last status change!!) */
  408. }
  409. return unix2dostime(&s.st_mtime);
  410. }
  411. /*
  412. * Get file THEOS attributes and store them into extent fields.
  413. * On error leave z intact.
  414. */
  415. /*
  416. * Extra record format
  417. * ===================
  418. * signature (2 bytes) = 'T','h'
  419. * size (2 bytes)
  420. * flags (1 byte)
  421. * filesize (4 bytes)
  422. * keylen (2 bytes)
  423. * reclen (2 bytes)
  424. * filegrow (1 byte)
  425. * reserved (4 bytes)
  426. */
  427. #define EB_L_THSIZE 4
  428. #define EB_L_TH_SIZE 14
  429. int set_extra_field(z, z_utim)
  430. struct zlist *z;
  431. iztimes *z_utim;
  432. /* store full data in local header but just modification time stamp info
  433. in central header */
  434. {
  435. char *extra = NULL;
  436. char *p;
  437. char c;
  438. struct stat st;
  439. int status;
  440. if (status = stat(z->name, &st)) {
  441. p = &z->name[strlen(z->name) - 1];
  442. if (*p == '/' || *p == '.') {
  443. c = *p;
  444. *p = '\0';
  445. status = stat(z->name, &st);
  446. *p = c;
  447. }
  448. #ifdef DEBUG
  449. fprintf(stderr, "set_extra_field: stat for file %s:\n status = %d\n",
  450. z->name, status);
  451. #endif
  452. if (status)
  453. return RET_ERROR;
  454. }
  455. if ((extra = malloc(EB_L_TH_SIZE)) == NULL ) {
  456. fprintf(stderr, "set_extra_field: Insufficient memory.\n" );
  457. return RET_ERROR;
  458. }
  459. extra[0] = 'T';
  460. extra[1] = 'h';
  461. extra[2] = EB_L_TH_SIZE;
  462. extra[3] = EB_L_TH_SIZE >> 8;
  463. extra[4] = 0;
  464. extra[5] = st.st_size;
  465. extra[6] = st.st_size >> 8;
  466. extra[7] = st.st_size >> 16;
  467. extra[8] = st.st_size >> 24;
  468. extra[9] = st.st_org;
  469. extra[10] = st.st_rlen;
  470. extra[11] = st.st_rlen >> 8;
  471. extra[12] = st.st_klen;
  472. extra[13] = st.st_klen >> 8;
  473. extra[14] = st.st_grow;
  474. extra[15] = st.st_protect;
  475. extra[16] = 0;
  476. extra[17] = 0;
  477. z->ext = z->cext = EB_L_TH_SIZE + EB_HEADSIZE;
  478. z->extra = z->cextra = extra;
  479. return RET_SUCCESS;
  480. }
  481. #endif
  482. /******************************/
  483. /* Function version_local() */
  484. /******************************/
  485. void version_local()
  486. {
  487. printf("Compiled with THEOS C 5.28 for THEOS 4.x on %s %s.\n\n",
  488. __DATE__, __TIME__);
  489. }