1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- /*
- * @(#)dir.c 1.4 87/11/06 Public Domain.
- *
- * A public domain implementation of BSD directory routines for
- * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
- * August 1987
- *
- * Ported to OS/2 by Kai Uwe Rommel
- * Addition of other OS/2 file system specific code
- * Placed into the public domain
- */
- /* does also contain EA access code for use in ZIP */
- #ifdef OS2
- #if defined(__EMX__) && !defined(__32BIT__)
- # define __32BIT__
- #endif
- #include "zip.h"
- #include <stdlib.h>
- #include <time.h>
- #include <ctype.h>
- #ifndef __BORLANDC__
- #include <malloc.h>
- #endif
- #define INCL_NOPM
- #define INCL_DOSNLS
- #define INCL_DOSERRORS
- #include <os2.h>
- #include "os2zip.h"
- #include "os2acl.h"
- #ifndef max
- #define max(a, b) ((a) < (b) ? (b) : (a))
- #endif
- #ifdef __32BIT__
- #define DosFindFirst(p1, p2, p3, p4, p5, p6) \
- DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
- #else
- #define DosQueryCurrentDisk DosQCurDisk
- #define DosQueryFSAttach(p1, p2, p3, p4, p5) \
- DosQFSAttach(p1, p2, p3, p4, p5, 0)
- #define DosQueryFSInfo(d, l, b, s) \
- DosQFSInfo(d, l, b, s)
- #define DosQueryPathInfo(p1, p2, p3, p4) \
- DosQPathInfo(p1, p2, p3, p4, 0)
- #define DosSetPathInfo(p1, p2, p3, p4, p5) \
- DosSetPathInfo(p1, p2, p3, p4, p5, 0)
- #define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
- DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
- #define DosFindFirst(p1, p2, p3, p4, p5, p6) \
- DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
- #define DosMapCase DosCaseMap
- #endif
- #ifndef UTIL
- extern int noisy;
- #ifndef S_IFMT
- #define S_IFMT 0xF000
- #endif
- static int attributes = _A_DIR | _A_HIDDEN | _A_SYSTEM;
- static char *getdirent(char *);
- static void free_dircontents(struct _dircontents *);
- #ifdef __32BIT__
- static HDIR hdir;
- static ULONG count;
- static FILEFINDBUF3 find;
- #else
- static HDIR hdir;
- static USHORT count;
- static FILEFINDBUF find;
- #endif
- DIR *opendir(const char *name)
- {
- struct stat statb;
- DIR *dirp;
- char c;
- char *s;
- struct _dircontents *dp;
- char nbuf[MAXPATHLEN + 1];
- int len;
- attributes = hidden_files ? (_A_DIR | _A_HIDDEN | _A_SYSTEM) : _A_DIR;
- strcpy(nbuf, name);
- if ((len = strlen(nbuf)) == 0)
- return NULL;
- if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1))
- {
- nbuf[len - 1] = 0;
- --len;
- if (nbuf[len - 1] == ':')
- {
- strcpy(nbuf+len, "\\.");
- len += 2;
- }
- }
- else
- if (nbuf[len - 1] == ':')
- {
- strcpy(nbuf+len, ".");
- ++len;
- }
- #ifndef __BORLANDC__
- /* when will we ever see a Borland compiler that can properly stat !!! */
- if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
- return NULL;
- #endif
- if ((dirp = malloc(sizeof(DIR))) == NULL)
- return NULL;
- if (nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.'))
- strcpy(nbuf+len-1, "*.*");
- else
- if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1))
- strcpy(nbuf+len, "*");
- else
- strcpy(nbuf+len, "\\*");
- /* len is no longer correct (but no longer needed) */
- dirp -> dd_loc = 0;
- dirp -> dd_contents = dirp -> dd_cp = NULL;
- if ((s = getdirent(nbuf)) == NULL)
- return dirp;
- do
- {
- if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
- ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) )
- {
- if (dp)
- free(dp);
- free_dircontents(dirp -> dd_contents);
- return NULL;
- }
- if (dirp -> dd_contents)
- {
- dirp -> dd_cp -> _d_next = dp;
- dirp -> dd_cp = dirp -> dd_cp -> _d_next;
- }
- else
- dirp -> dd_contents = dirp -> dd_cp = dp;
- strcpy(dp -> _d_entry, s);
- dp -> _d_next = NULL;
- dp -> _d_size = find.cbFile;
- dp -> _d_mode = find.attrFile;
- dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
- dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
- }
- while ((s = getdirent(NULL)) != NULL);
- dirp -> dd_cp = dirp -> dd_contents;
- return dirp;
- }
- void closedir(DIR * dirp)
- {
- free_dircontents(dirp -> dd_contents);
- free(dirp);
- }
- struct dirent *readdir(DIR * dirp)
- {
- static struct dirent dp;
- if (dirp -> dd_cp == NULL)
- return NULL;
- dp.d_namlen = dp.d_reclen =
- strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
- dp.d_ino = 0;
- dp.d_size = dirp -> dd_cp -> _d_size;
- dp.d_mode = dirp -> dd_cp -> _d_mode;
- dp.d_time = dirp -> dd_cp -> _d_time;
- dp.d_date = dirp -> dd_cp -> _d_date;
- dirp -> dd_cp = dirp -> dd_cp -> _d_next;
- dirp -> dd_loc++;
- return &dp;
- }
- void seekdir(DIR * dirp, long off)
- {
- long i = off;
- struct _dircontents *dp;
- if (off >= 0)
- {
- for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
- dirp -> dd_loc = off - (i + 1);
- dirp -> dd_cp = dp;
- }
- }
- long telldir(DIR * dirp)
- {
- return dirp -> dd_loc;
- }
- static void free_dircontents(struct _dircontents * dp)
- {
- struct _dircontents *odp;
- while (dp)
- {
- if (dp -> _d_entry)
- free(dp -> _d_entry);
- dp = (odp = dp) -> _d_next;
- free(odp);
- }
- }
- static char *getdirent(char *dir)
- {
- int done;
- static int lower;
- if (dir != NULL)
- { /* get first entry */
- hdir = HDIR_SYSTEM;
- count = 1;
- done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
- lower = IsFileSystemFAT(dir);
- }
- else /* get next entry */
- done = DosFindNext(hdir, &find, sizeof(find), &count);
- if (done == 0)
- {
- if (lower)
- StringLower(find.achName);
- return find.achName;
- }
- else
- {
- DosFindClose(hdir);
- return NULL;
- }
- }
- /* FAT / HPFS detection */
- int IsFileSystemFAT(char *dir)
- {
- static USHORT nLastDrive = -1, nResult;
- ULONG lMap;
- BYTE bData[64];
- char bName[3];
- #ifdef __32BIT__
- ULONG nDrive, cbData;
- PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
- #else
- USHORT nDrive, cbData;
- PFSQBUFFER pData = (PFSQBUFFER) bData;
- #endif
- /* We separate FAT and HPFS+other file systems here.
- at the moment I consider other systems to be similar to HPFS,
- i.e. support long file names and being case sensitive */
- if (isalpha(dir[0]) && (dir[1] == ':'))
- nDrive = to_up(dir[0]) - '@';
- else
- DosQueryCurrentDisk(&nDrive, &lMap);
- if (nDrive == nLastDrive)
- return nResult;
- bName[0] = (char) (nDrive + '@');
- bName[1] = ':';
- bName[2] = 0;
- nLastDrive = nDrive;
- cbData = sizeof(bData);
- if (!DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData))
- nResult = !strcmp((char *) pData -> szFSDName + pData -> cbName, "FAT");
- else
- nResult = FALSE;
- /* End of this ugly code */
- return nResult;
- }
- /* access mode bits and time stamp */
- int GetFileMode(char *name)
- {
- #ifdef __32BIT__
- FILESTATUS3 fs;
- return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;
- #else
- USHORT mode;
- return DosQFileMode(name, &mode, 0L) ? -1 : mode;
- #endif
- }
- ulg GetFileTime(char *name)
- {
- #ifdef __32BIT__
- FILESTATUS3 fs;
- #else
- FILESTATUS fs;
- #endif
- USHORT nDate, nTime;
- DATETIME dtCurrent;
- if (strcmp(name, "-") == 0)
- {
- DosGetDateTime(&dtCurrent);
- fs.fdateLastWrite.day = dtCurrent.day;
- fs.fdateLastWrite.month = dtCurrent.month;
- fs.fdateLastWrite.year = dtCurrent.year - 1980;
- fs.ftimeLastWrite.hours = dtCurrent.hours;
- fs.ftimeLastWrite.minutes = dtCurrent.minutes;
- fs.ftimeLastWrite.twosecs = dtCurrent.seconds / 2;
- }
- else
- if (DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)))
- return -1;
- nDate = * (USHORT *) &fs.fdateLastWrite;
- nTime = * (USHORT *) &fs.ftimeLastWrite;
- return ((ULONG) nDate) << 16 | nTime;
- }
- void SetFileTime(char *path, ulg stamp)
- {
- FILESTATUS fs;
- USHORT fd, ft;
- if (DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))
- return;
- fd = (USHORT) (stamp >> 16);
- ft = (USHORT) stamp;
- fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
- fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
- DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
- }
- /* read volume label */
- char *getVolumeLabel(int drive, unsigned long *vtime, unsigned long *vmode,
- time_t *utim)
- {
- static FSINFO fi;
- if (DosQueryFSInfo(drive ? drive - 'A' + 1 : 0,
- FSIL_VOLSER, (PBYTE) &fi, sizeof(fi)))
- return NULL;
- time(utim);
- *vtime = unix2dostime(utim);
- *vmode = _A_VOLID | _A_ARCHIVE;
- return (fi.vol.cch > 0) ? fi.vol.szVolLabel : NULL;
- }
- /* FAT / HPFS name conversion stuff */
- int IsFileNameValid(char *name)
- {
- HFILE hf;
- #ifdef __32BIT__
- ULONG uAction;
- #else
- USHORT uAction;
- #endif
- switch(DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
- OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))
- {
- case ERROR_INVALID_NAME:
- case ERROR_FILENAME_EXCED_RANGE:
- return FALSE;
- case NO_ERROR:
- DosClose(hf);
- default:
- return TRUE;
- }
- }
- void ChangeNameForFAT(char *name)
- {
- char *src, *dst, *next, *ptr, *dot, *start;
- static char invalid[] = ":;,=+\"[]<>| \t";
- if (isalpha(name[0]) && (name[1] == ':'))
- start = name + 2;
- else
- start = name;
- src = dst = start;
- if ((*src == '/') || (*src == '\\'))
- src++, dst++;
- while (*src)
- {
- for (next = src; *next && (*next != '/') && (*next != '\\'); next++);
- for (ptr = src, dot = NULL; ptr < next; ptr++)
- if (*ptr == '.')
- {
- dot = ptr; /* remember last dot */
- *ptr = '_';
- }
- if (dot == NULL)
- for (ptr = src; ptr < next; ptr++)
- if (*ptr == '_')
- dot = ptr; /* remember last _ as if it were a dot */
- if (dot && (dot > src) &&
- ((next - dot <= 4) ||
- ((next - src > 8) && (dot - src > 3))))
- {
- if (dot)
- *dot = '.';
- for (ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++)
- *dst++ = *ptr;
- for (ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++)
- *dst++ = *ptr;
- }
- else
- {
- if (dot && (next - src == 1))
- *dot = '.'; /* special case: "." as a path component */
- for (ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++)
- *dst++ = *ptr;
- }
- *dst++ = *next; /* either '/' or 0 */
- if (*next)
- {
- src = next + 1;
- if (*src == 0) /* handle trailing '/' on dirs ! */
- *dst = 0;
- }
- else
- break;
- }
- for (src = start; *src != 0; ++src)
- if ((strchr(invalid, *src) != NULL) || (*src == ' '))
- *src = '_';
- }
- /* .LONGNAME EA code */
- typedef struct
- {
- ULONG cbList; /* length of value + 22 */
- #ifdef __32BIT__
- ULONG oNext;
- #endif
- BYTE fEA; /* 0 */
- BYTE cbName; /* length of ".LONGNAME" = 9 */
- USHORT cbValue; /* length of value + 4 */
- BYTE szName[10]; /* ".LONGNAME" */
- USHORT eaType; /* 0xFFFD for length-preceded ASCII */
- USHORT eaSize; /* length of value */
- BYTE szValue[CCHMAXPATH];
- }
- FEALST;
- typedef struct
- {
- ULONG cbList;
- #ifdef __32BIT__
- ULONG oNext;
- #endif
- BYTE cbName;
- BYTE szName[10]; /* ".LONGNAME" */
- }
- GEALST;
- char *GetLongNameEA(const char *name)
- {
- EAOP eaop;
- GEALST gealst;
- static FEALST fealst;
- char *ptr;
- eaop.fpGEAList = (PGEALIST) &gealst;
- eaop.fpFEAList = (PFEALIST) &fealst;
- eaop.oError = 0;
- strcpy((char *) gealst.szName, ".LONGNAME");
- gealst.cbName = (BYTE) strlen((char *) gealst.szName);
- #ifdef __32BIT__
- gealst.oNext = 0;
- #endif
- gealst.cbList = sizeof(gealst);
- fealst.cbList = sizeof(fealst);
- if (DosQueryPathInfo(name, FIL_QUERYEASFROMLIST,
- (PBYTE) &eaop, sizeof(eaop)))
- return NULL;
- if (fealst.cbValue > 4 && fealst.eaType == 0xFFFD)
- {
- fealst.szValue[fealst.eaSize] = 0;
- for (ptr = fealst.szValue; *ptr; ptr++)
- if (*ptr == '/' || *ptr == '\\')
- *ptr = '!';
- return (char *) fealst.szValue;
- }
- return NULL;
- }
- char *GetLongPathEA(const char *name)
- {
- static char nbuf[CCHMAXPATH + 1];
- char tempbuf[CCHMAXPATH + 1];
- char *comp, *next, *ea, sep;
- BOOL bFound = FALSE;
- nbuf[0] = 0;
- strncpy(tempbuf, name, CCHMAXPATH);
- tempbuf[CCHMAXPATH] = '\0';
- next = tempbuf;
- while (*next)
- {
- comp = next;
- while (*next != '\\' && *next != '/' && *next != 0)
- next++;
- sep = *next;
- *next = 0;
- ea = GetLongNameEA(tempbuf);
- strcat(nbuf, ea ? ea : comp);
- bFound = bFound || (ea != NULL);
- if (sep)
- {
- strcat(nbuf, "\\");
- *next++ = sep;
- }
- }
- return (nbuf[0] != 0) && bFound ? nbuf : NULL;
- }
- /* general EA code */
- typedef struct
- {
- USHORT nID;
- USHORT nSize;
- ULONG lSize;
- }
- EFHEADER, *PEFHEADER;
- #ifdef __32BIT__
- /* Perhaps due to bugs in the current OS/2 2.0 kernel, the success or
- failure of the DosEnumAttribute() and DosQueryPathInfo() system calls
- depends on the area where the return buffers are allocated. This
- differs for the various compilers, for some alloca() works, for some
- malloc() works, for some, both work. We'll have to live with that. */
- /* The use of malloc() is not very convenient, because it requires
- backtracking (i.e. free()) at error returns. We do that for system
- calls that may fail, but not for malloc() calls, because they are VERY
- unlikely to fail. If ever, we just leave some memory allocated
- over the usually short lifetime of a zip process ... */
- #ifdef __GNUC__
- #define alloc(x) alloca(x)
- #define unalloc(x)
- #else
- #define alloc(x) malloc(x)
- #define unalloc(x) free(x)
- #endif
- void GetEAs(char *path, char **bufptr, size_t *size,
- char **cbufptr, size_t *csize)
- {
- FILESTATUS4 fs;
- PDENA2 pDENA, pFound;
- EAOP2 eaop;
- PGEA2 pGEA;
- PGEA2LIST pGEAlist;
- PFEA2LIST pFEAlist;
- PEFHEADER pEAblock;
- ULONG ulAttributes, ulMemoryBlock;
- ULONG nLength;
- ULONG nBlock;
- char szName[CCHMAXPATH];
- *size = *csize = 0;
- strcpy(szName, path);
- nLength = strlen(szName);
- if (szName[nLength - 1] == '/')
- szName[nLength - 1] = 0;
- if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs)))
- return;
- nBlock = max(fs.cbList, 65535);
- if ((pDENA = alloc((size_t) nBlock)) == NULL)
- return;
- ulAttributes = -1;
- if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, nBlock,
- &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
- || ulAttributes == 0
- || (pGEAlist = alloc((size_t) nBlock)) == NULL)
- {
- unalloc(pDENA);
- return;
- }
- pGEA = pGEAlist -> list;
- memset(pGEAlist, 0, nBlock);
- pFound = pDENA;
- while (ulAttributes--)
- {
- if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
- {
- pGEA -> cbName = pFound -> cbName;
- strcpy(pGEA -> szName, pFound -> szName);
- nLength = sizeof(GEA2) + strlen(pGEA -> szName);
- nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
- pGEA -> oNextEntryOffset = ulAttributes ? nLength : 0;
- pGEA = (PGEA2) ((PCH) pGEA + nLength);
- }
- pFound = (PDENA2) ((PCH) pFound + pFound -> oNextEntryOffset);
- }
- if (pGEA == pGEAlist -> list) /* no attributes to save */
- {
- unalloc(pDENA);
- unalloc(pGEAlist);
- return;
- }
- pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
- pFEAlist = (PVOID) pDENA; /* reuse buffer */
- pFEAlist -> cbList = nBlock;
- eaop.fpGEA2List = pGEAlist;
- eaop.fpFEA2List = pFEAlist;
- eaop.oError = 0;
- if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
- (PBYTE) &eaop, sizeof(eaop)))
- {
- unalloc(pDENA);
- unalloc(pGEAlist);
- return;
- }
- /* The maximum compressed size is (in case of STORE type) the
- uncompressed size plus the size of the compression type field
- plus the size of the CRC field + 2*5 deflate overhead bytes
- for uncompressable data.
- (5 bytes per 32Kb block, max compressed size = 2 blocks) */
- ulAttributes = pFEAlist -> cbList;
- ulMemoryBlock = ulAttributes +
- sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
- pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER) + ulMemoryBlock);
- if (pEAblock == NULL)
- {
- unalloc(pDENA);
- unalloc(pGEAlist);
- return;
- }
- *bufptr = (char *) pEAblock;
- *size = sizeof(EFHEADER);
- pEAblock -> nID = EF_OS2EA;
- pEAblock -> nSize = sizeof(pEAblock -> lSize);
- pEAblock -> lSize = ulAttributes; /* uncompressed size */
- nLength = memcompress((char *) (pEAblock + 1), ulMemoryBlock,
- (char *) pFEAlist, ulAttributes);
- *size += nLength;
- pEAblock -> nSize += nLength;
- if ((pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER))) == NULL)
- {
- unalloc(pDENA);
- unalloc(pGEAlist);
- return;
- }
- *cbufptr = (char *) pEAblock;
- *csize = sizeof(EFHEADER);
- pEAblock -> nID = EF_OS2EA;
- pEAblock -> nSize = sizeof(pEAblock -> lSize);
- pEAblock -> lSize = ulAttributes;
- if (noisy)
- printf(" (%ld bytes EA's)", ulAttributes);
- unalloc(pDENA);
- unalloc(pGEAlist);
- }
- #else /* !__32BIT__ */
- typedef struct
- {
- ULONG oNextEntryOffset;
- BYTE fEA;
- BYTE cbName;
- USHORT cbValue;
- CHAR szName[1];
- }
- FEA2, *PFEA2;
- typedef struct
- {
- ULONG cbList;
- FEA2 list[1];
- }
- FEA2LIST, *PFEA2LIST;
- void GetEAs(char *path, char **bufptr, size_t *size,
- char **cbufptr, size_t *csize)
- {
- FILESTATUS2 fs;
- PDENA1 pDENA, pFound;
- EAOP eaop;
- PGEALIST pGEAlist;
- PGEA pGEA;
- PFEALIST pFEAlist;
- PFEA pFEA;
- PFEA2LIST pFEA2list;
- PFEA2 pFEA2;
- EFHEADER *pEAblock;
- ULONG ulAttributes;
- USHORT nLength, nMaxSize;
- char szName[CCHMAXPATH];
- *size = *csize = 0;
- strcpy(szName, path);
- nLength = strlen(szName);
- if (szName[nLength - 1] == '/')
- szName[nLength - 1] = 0;
- if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs))
- || fs.cbList <= 2 * sizeof(ULONG))
- return;
- ulAttributes = -1;
- nMaxSize = (USHORT) min(fs.cbList * 2, 65520L);
- if ((pDENA = malloc((size_t) nMaxSize)) == NULL)
- return;
- if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, fs.cbList,
- &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
- || ulAttributes == 0
- || (pGEAlist = malloc(nMaxSize)) == NULL)
- {
- free(pDENA);
- return;
- }
- pGEA = pGEAlist -> list;
- pFound = pDENA;
- while (ulAttributes--)
- {
- nLength = strlen(pFound -> szName);
- if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
- {
- pGEA -> cbName = pFound -> cbName;
- strcpy(pGEA -> szName, pFound -> szName);
- pGEA++;
- pGEA = (PGEA) (((PCH) pGEA) + nLength);
- }
- pFound++;
- pFound = (PDENA1) (((PCH) pFound) + nLength);
- }
- if (pGEA == pGEAlist -> list)
- {
- free(pDENA);
- free(pGEAlist);
- return;
- }
- pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
- pFEAlist = (PFEALIST) pDENA; /* reuse buffer */
- pFEAlist -> cbList = fs.cbList;
- pFEA = pFEAlist -> list;
- eaop.fpGEAList = pGEAlist;
- eaop.fpFEAList = pFEAlist;
- eaop.oError = 0;
- if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
- (PBYTE) &eaop, sizeof(eaop)))
- {
- free(pDENA);
- free(pGEAlist);
- return;
- }
- /* now convert into new OS/2 2.0 32-bit format */
- pFEA2list = (PFEA2LIST) pGEAlist; /* reuse buffer */
- pFEA2 = pFEA2list -> list;
- while ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList)
- {
- nLength = sizeof(FEA) + pFEA -> cbName + 1 + pFEA -> cbValue;
- memcpy((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), pFEA, nLength);
- memset((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset) + nLength, 0, 3);
- pFEA = (PFEA) ((PCH) pFEA + nLength);
- nLength = sizeof(FEA2) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
- nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
- /* rounded up to 4-byte boundary */
- pFEA2 -> oNextEntryOffset =
- ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList) ? nLength : 0;
- pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength);
- }
- pFEA2list -> cbList = (PCH) pFEA2 - (PCH) pFEA2list;
- ulAttributes = pFEA2list -> cbList;
- pEAblock = (PEFHEADER) pDENA; /* reuse buffer */
- *bufptr = (char *) pEAblock;
- *size = sizeof(EFHEADER);
- pEAblock -> nID = EF_OS2EA;
- pEAblock -> nSize = sizeof(pEAblock -> lSize);
- pEAblock -> lSize = ulAttributes; /* uncompressed size */
- nLength = (USHORT) memcompress((char *) (pEAblock + 1),
- nMaxSize - sizeof(EFHEADER), (char *) pFEA2list, ulAttributes);
- *size += nLength;
- pEAblock -> nSize += nLength;
- pEAblock = (PEFHEADER) pGEAlist;
- *cbufptr = (char *) pEAblock;
- *csize = sizeof(EFHEADER);
- pEAblock -> nID = EF_OS2EA;
- pEAblock -> nSize = sizeof(pEAblock -> lSize);
- pEAblock -> lSize = ulAttributes;
- if (noisy)
- printf(" (%ld bytes EA's)", ulAttributes);
- }
- #endif /* __32BIT__ */
- void GetACL(char *path, char **bufptr, size_t *size,
- char **cbufptr, size_t *csize)
- {
- static char *buffer;
- char *cbuffer;
- long bytes, cbytes;
- PEFHEADER pACLblock;
- if (buffer == NULL) /* avoid frequent allocation (for every file) */
- if ((buffer = malloc(ACL_BUFFERSIZE)) == NULL)
- return;
- if (acl_get(NULL, path, buffer))
- return; /* this will be the most likely case */
- bytes = strlen(buffer);
- /* The maximum compressed size is (in case of STORE type) the
- uncompressed size plus the size of the compression type field
- plus the size of the CRC field + 2*5 deflate overhead bytes
- for uncompressable data.
- (5 bytes per 32Kb block, max compressed size = 2 blocks) */
- cbytes = bytes + sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
- if ((*bufptr = realloc(*bufptr, *size + sizeof(EFHEADER) + cbytes)) == NULL)
- return;
- pACLblock = (PEFHEADER) (*bufptr + *size);
- cbuffer = (char *) (pACLblock + 1);
- cbytes = memcompress(cbuffer, cbytes, buffer, bytes);
- *size += sizeof(EFHEADER) + cbytes;
- pACLblock -> nID = EF_ACL;
- pACLblock -> nSize = sizeof(pACLblock -> lSize) + cbytes;
- pACLblock -> lSize = bytes; /* uncompressed size */
- if ((*cbufptr = realloc(*cbufptr, *csize + sizeof(EFHEADER))) == NULL)
- return;
- pACLblock = (PEFHEADER) (*cbufptr + *csize);
- *csize += sizeof(EFHEADER);
- pACLblock -> nID = EF_ACL;
- pACLblock -> nSize = sizeof(pACLblock -> lSize);
- pACLblock -> lSize = bytes;
- if (noisy)
- printf(" (%ld bytes ACL)", bytes);
- }
- #ifdef USE_EF_UT_TIME
- int GetExtraTime(struct zlist far *z, iztimes *z_utim)
- {
- int eb_c_size = EB_HEADSIZE + EB_UT_LEN(1);
- int eb_l_size = eb_c_size;
- char *eb_c_ptr;
- char *eb_l_ptr;
- unsigned long ultime;
- #ifdef IZ_CHECK_TZ
- if (!zp_tz_is_valid) return ZE_OK; /* skip silently no correct tz info */
- #endif
- eb_c_ptr = realloc(z->cextra, (z->cext + eb_c_size));
- if (eb_c_ptr == NULL)
- return ZE_MEM;
- z->cextra = eb_c_ptr;
- eb_c_ptr += z->cext;
- z->cext += eb_c_size;
- eb_c_ptr[0] = 'U';
- eb_c_ptr[1] = 'T';
- eb_c_ptr[2] = EB_UT_LEN(1); /* length of data part of e.f. */
- eb_c_ptr[3] = 0;
- eb_c_ptr[4] = EB_UT_FL_MTIME;
- ultime = (unsigned long) z_utim->mtime;
- eb_c_ptr[5] = (char)(ultime);
- eb_c_ptr[6] = (char)(ultime >> 8);
- eb_c_ptr[7] = (char)(ultime >> 16);
- eb_c_ptr[8] = (char)(ultime >> 24);
- if (z_utim->mtime != z_utim->atime || z_utim->mtime != z_utim->ctime)
- {
- eb_c_ptr[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
- eb_l_size = EB_HEADSIZE + EB_UT_LEN(3); /* only on HPFS they can differ */
- /* so only then it makes sense to store all three time stamps */
- }
- eb_l_ptr = realloc(z->extra, (z->ext + eb_l_size));
- if (eb_l_ptr == NULL)
- return ZE_MEM;
- z->extra = eb_l_ptr;
- eb_l_ptr += z->ext;
- z->ext += eb_l_size;
- memcpy(eb_l_ptr, eb_c_ptr, eb_c_size);
- if (eb_l_size > eb_c_size)
- {
- eb_l_ptr[2] = EB_UT_LEN(3);
- ultime = (unsigned long) z_utim->atime;
- eb_l_ptr[9] = (char)(ultime);
- eb_l_ptr[10] = (char)(ultime >> 8);
- eb_l_ptr[11] = (char)(ultime >> 16);
- eb_l_ptr[12] = (char)(ultime >> 24);
- ultime = (unsigned long) z_utim->ctime;
- eb_l_ptr[13] = (char)(ultime);
- eb_l_ptr[14] = (char)(ultime >> 8);
- eb_l_ptr[15] = (char)(ultime >> 16);
- eb_l_ptr[16] = (char)(ultime >> 24);
- }
- return ZE_OK;
- }
- #endif /* USE_EF_UT_TIME */
- int set_extra_field(struct zlist far *z, iztimes *z_utim)
- {
- /* store EA data in local header, and size only in central headers */
- GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
- /* store ACL data in local header, and size only in central headers */
- GetACL(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
- #ifdef USE_EF_UT_TIME
- /* store extended time stamps in both headers */
- return GetExtraTime(z, z_utim);
- #else /* !USE_EF_UT_TIME */
- return ZE_OK;
- #endif /* ?USE_EF_UT_TIME */
- }
- #endif /* !UTIL */
- /* Initialize the table of uppercase characters including handling of
- country dependent characters. */
- void init_upper()
- {
- COUNTRYCODE cc;
- unsigned nCnt, nU;
- for (nCnt = 0; nCnt < sizeof(upper); nCnt++)
- upper[nCnt] = lower[nCnt] = (unsigned char) nCnt;
- cc.country = cc.codepage = 0;
- DosMapCase(sizeof(upper), &cc, (PCHAR) upper);
- for (nCnt = 0; nCnt < 256; nCnt++)
- {
- nU = upper[nCnt];
- if (nU != nCnt && lower[nU] == (unsigned char) nU)
- lower[nU] = (unsigned char) nCnt;
- }
- for (nCnt = 'A'; nCnt <= 'Z'; nCnt++)
- lower[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
- }
- char *StringLower(char *szArg)
- {
- unsigned char *szPtr;
- for (szPtr = (unsigned char *) szArg; *szPtr; szPtr++)
- *szPtr = lower[*szPtr];
- return szArg;
- }
- #if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
- void DebugMalloc(void)
- {
- _dump_allocated(0); /* print out debug malloc memory statistics */
- }
- #endif
- /******************************/
- /* Function version_local() */
- /******************************/
- void version_local()
- {
- static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
- #if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)
- char buf[80];
- #endif
- printf(CompiledWith,
- #ifdef __GNUC__
- # ifdef __EMX__ /* __EMX__ is defined as "1" only (sigh) */
- "emx+gcc ", __VERSION__,
- # else
- "gcc/2 ", __VERSION__,
- # endif
- #elif defined(__IBMC__)
- "IBM ",
- # if (__IBMC__ < 200)
- (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf),
- # elif (__IBMC__ < 300)
- (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
- # else
- (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
- # endif
- #elif defined(__WATCOMC__)
- "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
- #elif defined(__TURBOC__)
- # ifdef __BORLANDC__
- "Borland C++",
- # if (__BORLANDC__ < 0x0460)
- " 1.0",
- # elif (__BORLANDC__ == 0x0460)
- " 1.5",
- # else
- " 2.0",
- # endif
- # else
- "Turbo C",
- # if (__TURBOC__ >= 661)
- "++ 1.0 or later",
- # elif (__TURBOC__ == 661)
- " 3.0?",
- # elif (__TURBOC__ == 397)
- " 2.0",
- # else
- " 1.0 or 1.5?",
- # endif
- # endif
- #elif defined(MSC)
- "Microsoft C ",
- # ifdef _MSC_VER
- (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
- # else
- "5.1 or earlier",
- # endif
- #else
- "unknown compiler", "",
- #endif /* __GNUC__ */
- "OS/2",
- /* GRR: does IBM C/2 identify itself as IBM rather than Microsoft? */
- #if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))
- # if defined(M_I86HM) || defined(__HUGE__)
- " (16-bit, huge)",
- # elif defined(M_I86LM) || defined(__LARGE__)
- " (16-bit, large)",
- # elif defined(M_I86MM) || defined(__MEDIUM__)
- " (16-bit, medium)",
- # elif defined(M_I86CM) || defined(__COMPACT__)
- " (16-bit, compact)",
- # elif defined(M_I86SM) || defined(__SMALL__)
- " (16-bit, small)",
- # elif defined(M_I86TM) || defined(__TINY__)
- " (16-bit, tiny)",
- # else
- " (16-bit)",
- # endif
- #else
- " 2.x/3.x (32-bit)",
- #endif
- #ifdef __DATE__
- " on ", __DATE__
- #else
- "", ""
- #endif
- );
- /* temporary debugging code for Borland compilers only */
- #ifdef __TURBOC__
- printf("\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__, __TURBOC__);
- #ifdef __BORLANDC__
- printf("\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__);
- #else
- printf("\tdebug(__BORLANDC__ not defined)\n");
- #endif
- #ifdef __TCPLUSPLUS__
- printf("\t(__TCPLUSPLUS__ = 0x%04x)\n", __TCPLUSPLUS__);
- #else
- printf("\tdebug(__TCPLUSPLUS__ not defined)\n");
- #endif
- #ifdef __BCPLUSPLUS__
- printf("\t(__BCPLUSPLUS__ = 0x%04x)\n\n", __BCPLUSPLUS__);
- #else
- printf("\tdebug(__BCPLUSPLUS__ not defined)\n\n");
- #endif
- #endif /* __TURBOC__ */
- } /* end function version_local() */
- #endif /* OS2 */
|