/****************************************************************/ /* */ /* dosnames.c */ /* DOS-C */ /* */ /* Generic parsing functions for file name specifications */ /* */ /* Copyright (c) 1994 */ /* Pasquale J. Villani */ /* All Rights Reserved */ /* */ /* This file is part of DOS-C. */ /* */ /* DOS-C is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version */ /* 2, or (at your option) any later version. */ /* */ /* DOS-C is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public */ /* License along with DOS-C; see the file COPYING. If not, */ /* write to the Free Software Foundation, 675 Mass Ave, */ /* Cambridge, MA 02139, USA. */ /* */ /****************************************************************/ #include "../../hdr/portab.h" /* $Logfile: C:/dos-c/src/fs/dosnames.c_v $ */ #ifndef IPL static BYTE *dosnamesRcsId = "$Header: C:/dos-c/src/fs/dosnames.c_v 1.2 01 Sep 1995 17:48:44 patv $"; #endif /* * $Log: C:/dos-c/src/fs/dosnames.c_v $ * * Rev 1.2 01 Sep 1995 17:48:44 patv * First GPL release. * * Rev 1.1 30 Jul 1995 20:50:26 patv * Eliminated version strings in ipl * * Rev 1.0 02 Jul 1995 8:05:56 patv * Initial revision. * */ #include "globals.h" static BOOL bFileChar(UCOUNT uChar); static BOOL bFileChar(UCOUNT uChar) { /* Null is not a valid character */ if(NULL == uChar) return FALSE; /* Upper and lower case are valid */ if((uChar >= 'A' && uChar <= 'Z') || (uChar >= 'a' && uChar <= 'z')) return TRUE; /* Numbers are valid */ if(uChar >= '0' && uChar <= '9') return TRUE; return !(uChar == '/' || uChar == '\\' || uChar == ':' || uChar == '.'); } COUNT DosNames(BYTE FAR *lpszFileName, struct dosnames FAR *lpDosname) { enum STATE { SEARCH = -1, START = 0, DRIVE_FOUND, NETWORK_FOUND, DIR_FOUND, FILE_FOUND, EXT_FOUND, SKIP, TERMINATE } nState, nOldState; COUNT Idx; BYTE FAR *lpszPath; BYTE FAR *lpszWork; REG struct dpb *pDpb; /* Initialize the structure */ lpDosname -> dn_drive = default_drive; *lpDosname -> dn_network = *lpDosname -> dn_path = *lpDosname -> dn_name = '\0'; lpszPath = lpDosname -> dn_path; nState = nOldState = START; while(*lpszFileName != NULL) { COUNT nCharCount; switch(nState) { case START: switch(*lpszFileName) { case '\\': if(*(lpszFileName + 1) == '\\') { nOldState = nState; nState = NETWORK_FOUND; lpszFileName += 2; } else { nOldState = nState; nState = DIR_FOUND; } break; case '/': nOldState = nState; nState = DIR_FOUND; lpszFileName += 1; break; default: /* See if a drive was specified. */ if(bFileChar(*lpszFileName) && *(lpszFileName + 1) == ':') { nOldState = nState; nState = DRIVE_FOUND; } /* Otherwise assume it to be a file */ /* name. */ else { nOldState = nState; nState = FILE_FOUND; } break; } break; case DRIVE_FOUND: lpDosname -> dn_drive = *lpszFileName - 'A'; if(lpDosname -> dn_drive > 26) lpDosname -> dn_drive -= ('a' - 'A'); lpszFileName += 2; nOldState = nState; nState = SEARCH; break; case NETWORK_FOUND: for(lpszWork = lpDosname -> dn_network, nCharCount = 0; nCharCount < NAMEMAX && !(*lpszFileName == '\\' || *lpszFileName == '/' ); ++nCharCount) { *lpszWork++ = *lpszFileName++; *lpszWork = '\0'; } nOldState = nState; nState = SEARCH; break; case DIR_FOUND: *lpszPath++ = '\\'; ++lpszFileName; nOldState = nState; if(bFileChar(*lpszFileName)) nState = FILE_FOUND; else nState = TERMINATE; break; case FILE_FOUND: for(nCharCount = 0; nCharCount < FNAME_SIZE && bFileChar(*lpszFileName); ++nCharCount) { *lpszPath++ = *lpszFileName++; *lpszPath = '\0'; } nOldState = nState; if(nCharCount >= FNAME_SIZE && bFileChar(*lpszFileName)) nState = SKIP; else nState = *lpszFileName == '.' ? EXT_FOUND : SEARCH; break; case EXT_FOUND: *lpszPath++ = *lpszFileName++; for(nCharCount = 0; nCharCount < FEXT_SIZE && bFileChar(*lpszFileName); ++nCharCount) { *lpszPath++ = *lpszFileName++; *lpszPath = '\0'; } nOldState = nState; if(nCharCount >= FEXT_SIZE && bFileChar(*lpszFileName)) nState = SKIP; else nState = SEARCH; break; case SKIP: while(bFileChar(*lpszFileName)) ++lpszFileName; switch(nOldState) { case FILE_FOUND: nOldState = nState; nState = *lpszFileName == '.' ? EXT_FOUND : SEARCH; break; default: nOldState = nState; nState = SEARCH; break; } break; case SEARCH: switch(*lpszFileName) { case '\\': nOldState = nState; nState = DIR_FOUND; break; default: nOldState = nState; if(bFileChar(*lpszFileName)) nState = FILE_FOUND; else nState = TERMINATE; break; } break; case TERMINATE: default: return DE_INVLDFMT; } } /* Now that we got the path, let's seperate the file name from */ /* the dir name. */ /* Get the length of the string, we'll use it later */ for(Idx = 0, lpszPath = lpDosname -> dn_path; *lpszPath != '\0'; Idx++, lpszPath++) /* Do nothing */ ; /* Now backtrack */ for( ; Idx > 0; --lpszPath, --Idx) { if(*lpszPath == '/' || *lpszPath == '\\') break; } /* Special case -- root dir */ if(Idx == 0 && *lpDosname -> dn_path == '\\') { fstrncpy(lpDosname -> dn_name, (lpDosname -> dn_path + 1), FNAME_SIZE + FEXT_SIZE + 1); *(lpDosname -> dn_path + 1) = NULL; return SUCCESS; } /* We're at 0, so we have just a name */ else if(Idx == 0) { fstrncpy(lpDosname -> dn_name, lpDosname -> dn_path, FNAME_SIZE + FEXT_SIZE + 1); *lpDosname -> dn_path = NULL; return SUCCESS; } /* Otherwise, we have both a file name and directory */ else { fstrncpy(lpDosname -> dn_name, (BYTE FAR *)&lpDosname -> dn_path[Idx + 1], FNAME_SIZE + FEXT_SIZE + 1); lpDosname -> dn_path[Idx] = NULL; return SUCCESS; } } BOOL IsDevice (BYTE *pszFileName) { struct dosnames Dosname; COUNT nLen = min(strlen(pszFileName),8); REG struct dhdr FAR *dhp = (struct dhdr FAR *)&nul_dev; /* break up the name first */ DosNames((BYTE FAR *)pszFileName, (struct dosnames FAR *)&Dosname); /* Test 1 - does it start with a \dev or /dev */ if((fstrcmp(Dosname.dn_name, (BYTE FAR *)"/dev") == 0) || (fstrcmp(Dosname.dn_name, (BYTE FAR *)"\\dev") == 0)) return TRUE; /* Test 2 - is it on the device chain? */ for(; -1l != (LONG)dhp; dhp = dhp -> dh_next) { BYTE cBuffer[8]; COUNT nIdx; /* Skip if block device */ if(!(dhp -> dh_attr & ATTR_CHAR)) continue; /* copy to cBuffer and space fill */ for(nIdx = 0; Dosname.dn_name[nIdx] != '.' && nIdx < nLen; ++nIdx) cBuffer[nIdx] = Dosname.dn_name[nIdx]; for(; nIdx > 8; ++nIdx) cBuffer[nIdx] = ' '; /* now compare */ if(fstrncmp((BYTE FAR *)cBuffer, dhp -> dh_name, 8) == 0) return TRUE; } return FALSE; }