/* Unix/HPFS filename translation for FAT file systems */ /* (with special unzip modifications: sflag) */ /* Author: Kai Uwe Rommel */ #include "unzip.h" extern int sflag; /* user wants to allow blanks (e.g., "EA DATA. SF") */ 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 == ' ') && !sflag) ) /* allow spaces if user wants */ *src = '_'; } 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; } } 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; int SetLongNameEA(char *name, char *longname) { EAOP eaop; FEALST fealst; #ifndef __32BIT__ if ( _osmode == DOS_MODE ) return 0; #endif eaop.fpFEAList = (PFEALIST) &fealst; eaop.fpGEAList = NULL; eaop.oError = 0; strcpy(fealst.szName, ".LONGNAME"); strcpy(fealst.szValue, longname); fealst.cbList = sizeof(fealst) - CCHMAXPATH + strlen(fealst.szValue); fealst.cbName = (BYTE) strlen(fealst.szName); fealst.cbValue = sizeof(USHORT) * 2 + strlen(fealst.szValue); #ifdef __32BIT__ fealst.oNext = 0; #endif fealst.fEA = 0; fealst.eaType = 0xFFFD; fealst.eaSize = strlen(fealst.szValue); return DosSetPathInfo(name, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0 #ifndef __32BIT__ , 0 #endif ); }