📄 os2zip.c
字号:
/* * @(#)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 1897 * Ported to OS/2 by Kai Uwe Rommel * December 1989, February 1990 * Change for HPFS support, October 1990 *//* 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 UTILextern int noisy;#ifndef S_IFMT#define S_IFMT 0xF000#endifstatic 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;#elsestatic HDIR hdir;static USHORT count;static FILEFINDBUF find;#endifDIR *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 beeing 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}long 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, long 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(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(char *name){ static char nbuf[CCHMAXPATH + 1]; char *comp, *next, *ea, sep; BOOL bFound = FALSE; nbuf[0] = 0; next = name; while (*next) { comp = next; while (*next != '\\' && *next != '/' && *next != 0) next++; sep = *next; *next = 0; ea = GetLongNameEA(name); strcat(nbuf, ea ? ea : comp); bFound = bFound || (ea != NULL); *next = sep; if (*next) { strcat(nbuf, "\\"); next++; } } return (nbuf[0] != 0) && bFound ? nbuf : NULL;}/* general EA code */typedef struct{ USHORT nID; USHORT nSize; ULONG lSize;}EFHEADER, *PEFHEADER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -