1/* 2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8*/ 9/* 10 * routines common to TANDEM (ZIP and UNZIP) 11 */ 12 13#include "zip.h" /* This sets up ZIP / UNZIP define */ 14 15#include <tal.h> 16#include "$system.zsysdefs.zsysc" nolist 17#include <cextdecs> nolist 18#include "tannsk.h" 19 20static time_t gmt_to_time_t (long long *); 21 22int isatty (fnum) 23int fnum; 24{ 25 return 1; 26} 27 28/********************/ 29/* Function in2ex() */ 30/********************/ 31 32#ifdef UNZIP 33char *in2ex(__G__ n) 34 __GDEF 35#else 36char *in2ex(n) 37#endif 38 char *n; /* internal file name */ 39/* Convert the zip file name to an external file name, returning the malloc'ed 40 string or NULL if not enough memory. */ 41{ 42 char *x; /* external file name buffer */ 43 char *y; /* pointer to external buffer */ 44 char *max; /* pointer to max end of next file part */ 45 char *t; /* pointer to internal - start of substring */ 46 char *p; /* pointer to internal - TANDEM delimiter */ 47 char *e; /* pointer to internal - DOS extension delimiter */ 48 char *z; /* pointer to internal - end of substring */ 49 int len; /* length of substring to copy to external name */ 50 int allow_dollar; /* $ symbol allowed as next character */ 51 52 if ((x = malloc(strlen(n) + 4)) == NULL) /* + 4 for safety */ 53 return NULL; 54 55 *x = '\0'; 56 57 /* Junk pathname as requested */ 58#ifdef UNZIP 59 if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL) 60 ++t; 61 else 62 t = n; 63#endif /* UNZIP */ 64#ifdef ZIP 65 if (!pathput) 66 t = last(n, INTERNAL_DELIMITER); 67 else 68 t = n; 69#endif /* ZIP */ 70 71 allow_dollar = TRUE; 72 73 while (*t != '\0') { /* File part could be sys, vol, subvol or file */ 74 if (*t == INTERNAL_DELIMITER) { /* System, Volume or Subvol Name */ 75 t++; 76 if (*t == INTERNAL_DELIMITER) { /* System */ 77 strcat(x, TANDEM_NODE_STR); 78 t++; 79 } 80 else { 81 strcat(x, TANDEM_DELIMITER_STR); 82 allow_dollar = FALSE; 83 } 84 } 85 /* Work out where end of current external string is */ 86 y = x + strlen(x); 87 88 /* Work out substring to copy and externalise */ 89 p = strchr(t, INTERNAL_DELIMITER); 90 e = strchr(t, DOS_EXTENSION); 91 if (p != NULL) { 92 if (e > p) 93 e = NULL; 94 } 95 96 z = e; 97 if (z == NULL) 98 z = p; 99 if (z == NULL) 100 z = t + strlen(t); 101 102 /* can't have Tandem name longer than 8 characters */ 103 max = y + MAXFILEPARTLEN; 104 105 /* Allow $ symbol as first character in some cases */ 106 if (*t == '$') { 107 if (allow_dollar) 108 *y++ = *t++; 109 else; 110 *t++; 111 } 112 113 /* Make sure first real character is alpha */ 114 if (! isalpha(*t) ) 115 *y++ = 'A'; 116 117 /* Characters left to process */ 118 len = z - t; 119 120 while ( len > 0 ) { 121 if ( isalnum(*t) ) { 122 *y++ = toupper(*t++); 123 if (y >= max) 124 break; 125 } 126 else 127 t++; 128 len--; 129 } 130 *y = '\0'; 131 t = p; 132 133 if (p == NULL) { 134 /* Last part of filename, store pseudo extension if available */ 135 if (e != NULL) { 136 strcat(x, TANDEM_EXTENSION_STR); 137 y = x + strlen(x); 138 139 /* no restriction on extension length as its virtual */ 140 z = e + 1; 141 while ( *z != '\0' ) { 142 *y++ = toupper(*z++); 143 } 144 *y = '\0'; 145 } 146 break; 147 } 148 } 149 150 return x; 151} 152 153void zexit(status) 154 int status; 155{ 156 /* Exit(>0) creates saveabend files */ 157 terminate_program (0,0,(short)status,,,); 158} 159 160/************************/ 161/* Function zputc() */ 162/************************/ 163 164#ifdef putc 165# undef putc 166#endif 167 168int zputc(ch, fptr) 169 int ch; 170 FILE *fptr; 171{ 172 int err; 173 err = putc(ch,fptr); 174 fflush(fptr); 175 return err; 176} 177#define putc zputc 178 179#ifdef LICENSED 180_tal _priv short FILE_CHANGELABEL_ ( 181 short, /* IN */ 182 short, /* IN */ 183 const short _far * /* IN */ 184 ); 185 186_c _callable int changelabel OF((short, const short *, const short *)); 187 188_c _callable int changelabel(fnum, modtime, actime) 189 short fnum; 190 const short *modtime; 191 const short *actime; 192{ 193 int err; 194 195 err = FILE_CHANGELABEL_(fnum, 16, modtime); 196 if (!err) 197 err = FILE_CHANGELABEL_(fnum, 17, actime); 198 return err; 199} 200 201int islicensed(void) 202{ 203 #define plist_items 1 204 #define plist_size 10 205 206 short myphandle[ZSYS_VAL_PHANDLE_WLEN]; 207 short licensetag[plist_items] = {37}; 208 short licensed[plist_size]; 209 short maxlen = plist_size; 210 short items = plist_items; 211 short resultlen[1], err; 212 213 err = PROCESSHANDLE_NULLIT_(myphandle); 214 215 if (!err) 216 err = PROCESS_GETINFO_(myphandle); 217 218 if (!err) 219 err = PROCESS_GETINFOLIST_(/*cpu*/, 220 /*pin*/, 221 /*nodename*/, 222 /*nodenamelen*/, 223 myphandle, 224 licensetag, 225 items, 226 licensed, 227 maxlen, 228 resultlen 229 ); 230 231 if (err != 0) 232 return 0; 233 else 234 return licensed[0]; 235} 236#endif /* LICENSED */ 237 238int utime(file, time) 239 const char *file; 240 const ztimbuf *time; 241{ 242#ifdef LICENSED 243 int result, err; 244 union timestamp_ov { 245 long long fulltime; 246 short wordtime[4]; 247 }; 248 union timestamp_ov lasttime, opentime; 249 struct tm *modt, *opent; 250 short datetime[8], errormask[1]; 251 short len, fnum, access, exclus, options; 252 char fname[FILENAME_MAX + 1]; 253 short extension; 254 char ext[EXTENSION_MAX + 1]; 255 256 if (islicensed() ) { 257 /* Attempt to update file label */ 258 modt = gmtime( &time->modtime ); 259 260 datetime[0] = modt->tm_year + 1900; 261 datetime[1] = modt->tm_mon + 1; 262 datetime[2] = modt->tm_mday; 263 datetime[3] = modt->tm_hour; 264 datetime[4] = modt->tm_min; 265 datetime[5] = modt->tm_sec; 266 datetime[6] = datetime[7] = 0; 267 errormask[0] = 0; 268 lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask); 269 270 opent = gmtime( &time->actime ); 271 272 datetime[0] = opent->tm_year + 1900; 273 datetime[1] = opent->tm_mon + 1; 274 datetime[2] = opent->tm_mday; 275 datetime[3] = opent->tm_hour; 276 datetime[4] = opent->tm_min; 277 datetime[5] = opent->tm_sec; 278 datetime[6] = datetime[7] = 0; 279 errormask[0] = 0; 280 opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask); 281 282 /* Remove any (pseudo) file extension */ 283 extension = parsename (file,fname,ext); 284 len = strlen(fname); 285 286 access = NSK_WRONLY; 287 exclus = NSK_SHARED; 288 options = NSK_NOUPDATEOPENTIME; 289 290 extension = parsename (file,fname,ext); 291 len = strlen(fname); 292 293 err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,); 294 result = changelabel(fnum,lasttime.wordtime,opentime.wordtime); 295 err = FILE_CLOSE_(fnum); 296 return result; 297 } 298 return -1; 299#else /* !LICENSED */ 300 return 0; /* "no error", to suppress annoying failure messages */ 301#endif /* ?LICENSED */ 302} 303 304/* TANDEM version of chmod() function */ 305 306int chmod(file, unix_sec) 307 const char *file; 308 mode_t unix_sec; 309{ 310 FILE *stream; 311 struct nsk_sec_type { 312 unsigned progid : 1; 313 unsigned clear : 1; 314 unsigned null : 2; 315 unsigned read : 3; 316 unsigned write : 3; 317 unsigned execute: 3; 318 unsigned purge : 3; 319 }; 320 union nsk_sec_ov { 321 struct nsk_sec_type bit_ov; 322 short int_ov; 323 }; 324 union nsk_sec_ov nsk_sec; 325 short fnum, err, nsk_sec_int; 326 short len, access, exclus, extension, options; 327 char fname[FILENAME_MAX + 1]; 328 char ext[EXTENSION_MAX + 1]; 329 330 nsk_sec.bit_ov.progid = 0; 331 nsk_sec.bit_ov.clear = 0; 332 nsk_sec.bit_ov.null = 0; 333 334 /* 4="N", 5="C", 6="U", 7="-" */ 335 336 if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4; 337 else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5; 338 else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6; 339 else nsk_sec.bit_ov.read = 7; 340 341 if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4; 342 else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5; 343 else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6; 344 else nsk_sec.bit_ov.write = 7; 345 346 if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4; 347 else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5; 348 else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6; 349 else nsk_sec.bit_ov.execute = 7; 350 351 nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write; 352 353 nsk_sec_int = nsk_sec.int_ov; 354 355 access = NSK_RDONLY; 356 exclus = NSK_SHARED; 357 options = NSK_NOUPDATEOPENTIME; 358 359 extension = parsename (file,fname,ext); 360 len = strlen(fname); 361 362 err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,); 363 err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE); 364 err = FILE_CLOSE_(fnum); 365 366 return (err != 0 ? -1 : 0); 367} 368 369/* TANDEM version of chown() function */ 370 371int chown(file, uid, gid) 372 const char *file; 373 uid_t uid; 374 gid_t gid; 375{ 376 FILE *stream; 377 struct nsk_own_type { 378 unsigned group : 8; 379 unsigned user : 8; 380 }; 381 union nsk_own_ov { 382 struct nsk_own_type bit_ov; 383 short int_ov; 384 }; 385 union nsk_own_ov nsk_own; 386 short fnum, err, nsk_own_int; 387 short len, access, exclus, extension, options; 388 char fname[FILENAME_MAX + 1]; 389 char ext[EXTENSION_MAX + 1]; 390 391 nsk_own.bit_ov.group = gid; 392 nsk_own.bit_ov.user = uid; 393 394 nsk_own_int = nsk_own.int_ov; 395 396 access = NSK_RDONLY; 397 exclus = NSK_SHARED; 398 options = NSK_NOUPDATEOPENTIME; 399 400 extension = parsename (file,fname,ext); 401 len = strlen(fname); 402 403 err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,); 404 err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE); 405 err = FILE_CLOSE_(fnum); 406 return (err != 0 ? -1 : 0); 407} 408 409/* TANDEM version of getch() - non-echo character reading */ 410int zgetch(void) 411{ 412 char ch; 413 short f, err, count, fnum, rlen; 414 415 rlen = 1; 416 f = (short)fileno(stdin); 417 fnum = fdtogfn (f); 418 #define ECHO_MODE 20 419 err = (SETMODE(fnum, ECHO_MODE, 0) != CCE); 420 err = (READX(fnum, &ch, rlen, (short *) &count) != CCE); 421 err = (SETMODE(fnum, ECHO_MODE, 1) != CCE); 422 423 if (err) 424 if (err != 1) 425 return EOF; 426 else 427 ch = 'q'; 428 else 429 if (count == 0) 430 ch = '\r'; 431 432 return (int)ch; 433} 434 435short parsename(srce, fname, ext) 436 const char *srce; 437 char *fname; 438 char *ext; 439{ 440 /* As a way of supporting DOS extensions from Tandem we look for a space 441 separated extension string after the Guardian filename 442 e.g. ZIP ZIPFILE "$DATA4.TESTING.INVOICE TXT" 443 */ 444 445 char *fstart; 446 char *fptr; 447 short extension = 0; 448 449 *fname = *ext = '\0'; /* set to null string */ 450 451 fstart = (char *) srce; 452 453 if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) { 454 extension = 1; 455 456 fptr++; 457 strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr))); 458 459 fptr = strchr(fstart, TANDEM_EXTENSION); /* End of filename */ 460 strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart))); 461 } 462 else { 463 /* just copy string */ 464 strncat(fname, srce, _min(FILENAME_MAX, strlen(srce))); 465 } 466 467 return extension; 468} 469 470static time_t gmt_to_time_t (gmt) 471 long long *gmt; 472{ 473 #define GMT_TO_LCT 0 474 #define GMT_TO_LST 1 475 476 struct tm temp_tm; 477 short date_time[8]; 478 long julian_dayno; 479 long long lct, lst, itime; 480 short err[1], type; 481 482 type = GMT_TO_LCT; 483 lct = CONVERTTIMESTAMP(*gmt, type,, err); 484 485 if (!err[0]) { 486 type = GMT_TO_LST; 487 lst = CONVERTTIMESTAMP(*gmt, type,, err); 488 } 489 490 itime = (err[0] ? *gmt : lct); 491 /* If we have no DST in force then make sure we give it a value, 492 else mktime screws up if we set the isdst flag to -1 */ 493 temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1)); 494 495 julian_dayno = INTERPRETTIMESTAMP(itime, date_time); 496 497 temp_tm.tm_sec = date_time[5]; 498 temp_tm.tm_min = date_time[4]; 499 temp_tm.tm_hour = date_time[3]; 500 temp_tm.tm_mday = date_time[2]; 501 temp_tm.tm_mon = date_time[1] - 1; /* C's so sad */ 502 temp_tm.tm_year = date_time[0] - 1900; /* it's almost funny */ 503 504 return (mktime(&temp_tm)); 505} 506 507/* TANDEM version of stat() function */ 508int stat(n, s) 509 const char *n; 510 struct stat *s; 511{ 512 #define ilist_items 26 513 #define klist_items 4 514 #define slist_items 3 515 #define ulist_items 1 516 #define flist_size 100 517 518 short err, i, extension; 519 char fname[FILENAME_MAX + 1]; 520 short fnamelen; 521 char ext[EXTENSION_MAX + 1]; 522 523 /* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */ 524 short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44, 525 50, 51, 52, 61, 63, 66, 67, 70, 72, 73, 526 74, 75, 76, 77, 78, 79 }; 527 short ilen[ilist_items] ={ 4, 4, 4, 2, 1, 2, 1, 1, 1, 1, 528 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 529 1, 1, 1, 1, 1, 1 }; 530 short ioff[ilist_items]; 531 532 /* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */ 533 short klist[klist_items]={45, 46, 68, 69 }; 534 short klen[klist_items] ={ 1, 1, 1, 1 }; 535 short koff[klist_items]; 536 537 /* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */ 538 short slist[slist_items]={43, 80, 90 }; 539 short slen[slist_items] ={ 1, 1, 1 }; 540 short soff[slist_items]; 541 542 /* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */ 543 short ulist[ulist_items]={65 }; 544 short ulen[ulist_items] ={ 1 }; 545 short uoff[ulist_items]; 546 547 short flist[flist_size]; 548 short extra[2]; 549 short *rlen=&extra[0]; 550 short *err_item=&extra[1]; 551 unsigned short *fowner; 552 unsigned short *fprogid; 553 char *fsec; 554 555 nsk_stat_ov *nsk_ov; 556 nsk_file_attrs *nsk_attr; 557 558 short end, count, kind, level, options, searchid; 559 short info[5]; 560 561 /* Initialise stat structure */ 562 s->st_dev = _S_GUARDIANOBJECT; 563 s->st_ino = 0; 564 s->st_nlink = 0; 565 s->st_rdev = 0; 566 s->st_uid = s->st_gid = 0; 567 s->st_size = 0; 568 s->st_atime = s->st_ctime = s->st_mtime = 0; 569 s->st_reserved[0] = 0; 570 s->st_reserved[1] = 0; 571 s->st_reserved[2] = 0; 572 nsk_ov = (nsk_stat_ov *)&s->st_reserved[0]; 573 nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region; 574 575 /* Check to see if name contains a (pseudo) file extension */ 576 extension = parsename (n,fname,ext); 577 578 fnamelen = strlen(fname); 579 580 options = 3; /* Allow Subvols and Templates */ 581 err = FILENAME_SCAN_( fname, 582 fnamelen, 583 &count, 584 &kind, 585 &level, 586 options 587 ); 588 589 /* allow kind == 2 (DEFINE names) */ 590 if (err != 0) return -1; 591 592 if (kind == 1 || (kind == 0 && level < 2)) { 593 /* Pattern, Subvol Name or One part Filename - lets see if it exists */ 594 err = FILENAME_FINDSTART_ ( &searchid, 595 fname, 596 fnamelen, 597 , 598 DISK_DEVICE 599 ); 600 601 if (err != 0) { 602 end = FILENAME_FINDFINISH_ ( searchid ); 603 return -1; 604 } 605 606 err = FILENAME_FINDNEXT_ ( searchid, 607 fname, 608 FILENAME_MAX, 609 &fnamelen, 610 info 611 ); 612 end = FILENAME_FINDFINISH_ ( searchid ); 613 614 if (err != 0) 615 return -1; /* Non existing template, subvol or file */ 616 617 if (kind == 1 || info[2] == -1) { 618 s->st_mode = S_IFDIR; /* Its an existing template or directory */ 619 return 0; 620 } 621 622 /* Must be a real file so drop to code below to get info on it */ 623 } 624 625 err = FILE_GETINFOLISTBYNAME_( fname, 626 fnamelen, 627 ilist, 628 ilist_items, 629 flist, 630 flist_size, 631 rlen, 632 err_item 633 ); 634 if (err != 0) return -1; 635 636 ioff[0] = 0; 637 638 /* Build up table of offets into result list */ 639 for (i=1; i < ilist_items; i++) 640 ioff[i] = ioff[i-1] + ilen[i-1]; 641 642 /* Set up main stat fields */ 643 644 /* Setup timestamps */ 645 s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]); 646 s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]); 647 nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]); 648 649 s->st_size = *(off_t *)&flist[ioff[3]]; 650 651 fowner = (unsigned short *)&flist[ioff[4]]; 652 s->st_uid = *fowner & 0x00ff; 653 s->st_gid = *fowner >> 8; 654 655 /* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */ 656 fsec = (char *)&flist[ioff[5]]; 657 fprogid = (unsigned short *)&flist[ioff[6]]; 658 659 s->st_mode = S_IFREG | /* Regular File */ 660 /* Parse Read Flag */ 661 ((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) | 662 ((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) | 663 ((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) | 664 /* Parse Write Flag */ 665 ((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) | 666 ((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) | 667 ((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) | 668 /* Parse Execute Flag */ 669 ((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) | 670 ((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) | 671 ((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) | 672 /* Parse Progid */ 673 (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ; 674 675 /* Set up NSK additional stat fields */ 676 nsk_attr->progid = (unsigned) flist[ioff[6]]; 677 nsk_attr->filetype = (unsigned) flist[ioff[7]]; 678 nsk_attr->filecode = (unsigned) flist[ioff[8]]; 679 nsk_attr->block = (unsigned short) flist[ioff[9]]; 680 nsk_attr->priext = (unsigned short) flist[ioff[10]]; 681 nsk_attr->secext = (unsigned short) flist[ioff[11]]; 682 nsk_attr->maxext = (unsigned short) flist[ioff[12]]; 683 nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]]; 684 nsk_attr->licensed = (unsigned) flist[ioff[14]]; 685 nsk_attr->flags.audited = (unsigned) flist[ioff[15]]; 686 nsk_attr->flags.acompress = (unsigned) flist[ioff[16]]; 687 nsk_attr->flags.refresheof = (unsigned) flist[ioff[17]]; 688 nsk_attr->flags.buffered = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0); 689 nsk_attr->flags.verified = (unsigned) flist[ioff[19]]; 690 nsk_attr->flags.serial = (unsigned) flist[ioff[20]]; 691 nsk_attr->flags.crashopen = (unsigned) flist[ioff[22]]; 692 nsk_attr->flags.rollforward = (unsigned) flist[ioff[23]]; 693 nsk_attr->flags.broken = (unsigned) flist[ioff[24]]; 694 nsk_attr->flags.corrupt = (unsigned) flist[ioff[25]]; 695 nsk_attr->fileopen = (unsigned) flist[ioff[21]]; 696 697 698 if (nsk_attr->filetype == NSK_UNSTRUCTURED) { 699 /* extra info for Unstructured files */ 700 err = FILE_GETINFOLISTBYNAME_( fname, 701 fnamelen, 702 ulist, 703 ulist_items, 704 flist, 705 flist_size, 706 rlen, 707 err_item 708 ); 709 if (err != 0) return -1; 710 711 uoff[0] = 0; 712 713 /* Build up table of offets into result list */ 714 for (i=1; i < ulist_items; i++) 715 uoff[i] = uoff[i-1] + ulen[i-1]; 716 } 717 else { 718 /* extra info for Structured files */ 719 err = FILE_GETINFOLISTBYNAME_( fname, 720 fnamelen, 721 slist, 722 slist_items, 723 flist, 724 flist_size, 725 rlen, 726 err_item 727 ); 728 if (err != 0) return -1; 729 730 soff[0] = 0; 731 732 /* Build up table of offets into result list */ 733 for (i=1; i < slist_items; i++) 734 soff[i] = soff[i-1] + slen[i-1]; 735 736 nsk_attr->reclen = (unsigned) flist[soff[0]]; 737 nsk_attr->flags.secpart = (unsigned) flist[soff[1]]; 738 nsk_attr->flags.primpart = (unsigned) 739 ( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 ); 740 741 if (nsk_attr->filetype == NSK_KEYSEQUENCED) { 742 /* extra info for Key Sequenced files */ 743 err = FILE_GETINFOLISTBYNAME_( fname, 744 fnamelen, 745 klist, 746 klist_items, 747 flist, 748 flist_size, 749 rlen, 750 err_item 751 ); 752 if (err != 0) return -1; 753 754 koff[0] = 0; 755 756 /* Build up table of offets into result list */ 757 for (i=1; i < klist_items; i++) 758 koff[i] = koff[i-1] + klen[i-1]; 759 760 nsk_attr->keyoff = (unsigned) flist[koff[0]]; 761 nsk_attr->keylen = (unsigned) flist[koff[1]]; 762 nsk_attr->flags.dcompress = (unsigned) flist[koff[2]]; 763 nsk_attr->flags.icompress = (unsigned) flist[koff[3]]; 764 } 765 } 766 767 return 0; 768} 769 770#ifndef SFX 771/* TANDEM Directory processing */ 772 773DIR *opendir(const char *dirname) 774{ 775 short i, resolve; 776 char sname[FILENAME_MAX + 1]; 777 short snamelen; 778 char fname[FILENAME_MAX + 1]; 779 short fnamelen; 780 char *p; 781 short searchid, err, end; 782 struct dirent *entry; 783 DIR *dirp; 784 char ext[EXTENSION_MAX + 1]; 785 short extension; 786 787 extension = parsename(dirname, sname, ext); 788 snamelen = strlen(sname); 789 790 /* First we work out how detailed the template is... 791 * e.g. If the template is DAVES*.* we want the search result 792 * in the same format 793 */ 794 795 p = sname; 796 i = 0; 797 while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){ 798 i++; 799 p++; 800 }; 801 resolve = 2 - i; 802 803 /* Attempt to start a filename template */ 804 err = FILENAME_FINDSTART_ ( &searchid, 805 sname, 806 snamelen, 807 resolve, 808 DISK_DEVICE 809 ); 810 if (err != 0) { 811 end = FILENAME_FINDFINISH_(searchid); 812 return NULL; 813 } 814 815 /* Create DIR structure */ 816 if ((dirp = malloc(sizeof(DIR))) == NULL ) { 817 end = FILENAME_FINDFINISH_(searchid); 818 return NULL; 819 } 820 dirp->D_list = dirp->D_curpos = NULL; 821 strcpy(dirp->D_path, dirname); 822 823 while ((err = FILENAME_FINDNEXT_(searchid, 824 fname, 825 FILENAME_MAX, 826 &fnamelen 827 ) 828 ) == 0 ){ 829 /* Create space for entry */ 830 if ((entry = malloc (sizeof(struct dirent))) == NULL) { 831 end = FILENAME_FINDFINISH_(searchid); 832 return NULL; 833 } 834 835 /* Link to last entry */ 836 if (dirp->D_curpos == NULL) 837 dirp->D_list = dirp->D_curpos = entry; /* First name */ 838 else { 839 dirp->D_curpos->d_next = entry; /* Link */ 840 dirp->D_curpos = entry; 841 }; 842 /* Add directory entry */ 843 *dirp->D_curpos->d_name = '\0'; 844 strncat(dirp->D_curpos->d_name,fname,fnamelen); 845 if (extension) { 846 strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR); 847 strcat(dirp->D_curpos->d_name,ext); 848 }; 849 dirp->D_curpos->d_next = NULL; 850 }; 851 852 end = FILENAME_FINDFINISH_(searchid); 853 854 if (err == 1) { /* Should return EOF at end of search */ 855 dirp->D_curpos = dirp->D_list; /* Set current pos to start */ 856 return dirp; 857 } 858 else 859 return NULL; 860} 861 862struct dirent *readdir(DIR *dirp) 863{ 864 struct dirent *cur; 865 866 cur = dirp->D_curpos; 867 dirp->D_curpos = dirp->D_curpos->d_next; 868 return cur; 869} 870 871void rewinddir(DIR *dirp) 872{ 873 dirp->D_curpos = dirp->D_list; 874} 875 876int closedir(DIR *dirp) 877{ 878 struct dirent *node; 879 880 while (dirp->D_list != NULL) { 881 node = dirp->D_list; 882 dirp->D_list = dirp->D_list->d_next; 883 free( node ); 884 } 885 free( dirp ); 886 return 0; 887} 888 889#endif /* !SFX */ 890