DOSNAMES.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:11k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /* */
  3. /*    dosnames.c */
  4. /*      DOS-C */
  5. /* */
  6. /*    Generic parsing functions for file name specifications */
  7. /* */
  8. /* Copyright (c) 1994 */
  9. /* Pasquale J. Villani */
  10. /* All Rights Reserved */
  11. /* */
  12. /* This file is part of DOS-C. */
  13. /* */
  14. /* DOS-C is free software; you can redistribute it and/or */
  15. /* modify it under the terms of the GNU General Public License */
  16. /* as published by the Free Software Foundation; either version */
  17. /* 2, or (at your option) any later version. */
  18. /* */
  19. /* DOS-C is distributed in the hope that it will be useful, but */
  20. /* WITHOUT ANY WARRANTY; without even the implied warranty of */
  21. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See */
  22. /* the GNU General Public License for more details. */
  23. /* */
  24. /* You should have received a copy of the GNU General Public */
  25. /* License along with DOS-C; see the file COPYING.  If not, */
  26. /* write to the Free Software Foundation, 675 Mass Ave, */
  27. /* Cambridge, MA 02139, USA. */
  28. /* */
  29. /****************************************************************/
  30. #include "../../hdr/portab.h"
  31. /* $Logfile:   C:/dos-c/src/fs/dosnames.c_v  $ */
  32. #ifdef VERSION_STRINGS
  33. static BYTE *dosnamesRcsId = "$Header:   C:/dos-c/src/fs/dosnames.c_v   1.8   22 Jan 1998  4:09:00   patv  $";
  34. #endif
  35. /* $Log:   C:/dos-c/src/fs/dosnames.c_v  $
  36.  * 
  37.  *    Rev 1.8   22 Jan 1998  4:09:00   patv
  38.  * Fixed pointer problems affecting SDA
  39.  * 
  40.  *    Rev 1.7   04 Jan 1998 23:14:38   patv
  41.  * Changed Log for strip utility
  42.  * 
  43.  *    Rev 1.6   03 Jan 1998  8:36:04   patv
  44.  * Converted data area to SDA format
  45.  * 
  46.  *    Rev 1.5   16 Jan 1997 12:46:36   patv
  47.  * pre-Release 0.92 feature additions
  48.  * 
  49.  *    Rev 1.4   29 May 1996 21:15:12   patv
  50.  * bug fixes for v0.91a
  51.  * 
  52.  *    Rev 1.3   19 Feb 1996  3:20:08   patv
  53.  * Added NLS, int2f and config.sys processing
  54.  * 
  55.  *    Rev 1.2   01 Sep 1995 17:48:44   patv
  56.  * First GPL release.
  57.  * 
  58.  *    Rev 1.1   30 Jul 1995 20:50:26   patv
  59.  * Eliminated version strings in ipl
  60.  * 
  61.  *    Rev 1.0   02 Jul 1995  8:05:56   patv
  62.  * Initial revision.
  63.  *
  64.  */ 
  65. /* $EndLog$ */
  66. #include "globals.h"
  67. #define PathSep(c) ((c)=='/'||(c)=='\')
  68. #define DriveChar(c) (((c)>='A'&&(c)<='Z')||((c)>='a'&&(c)<='z'))
  69. static BOOL bFileChar(UCOUNT uChar);
  70. VOID XlateLcase (BYTE *szFname, COUNT nChars);
  71. VOID DosTrimPath (BYTE FAR *lpszPathNamep);
  72. static BOOL bFileChar(UCOUNT uChar)
  73. {
  74. BYTE *pszValChar = "."/\[]:|<>+=;,", *pszPtr;
  75. /* Null is not a valid character */
  76. if(NULL == uChar)
  77. return FALSE;
  78. /* Loop through invalid character set */
  79. for (pszPtr = pszValChar; *pszPtr != NULL; pszPtr++)
  80. if(uChar == *pszPtr)
  81. return FALSE;
  82. /* Not in excluded set, it's ok. */
  83. return TRUE;
  84. }
  85. /* Should be converted to a portable version after v1.0 is released. */
  86. VOID
  87. XlateLcase (BYTE *szFname, COUNT nChars)
  88. {
  89. while(nChars--)
  90. {
  91. if(*szFname >= 'a' && *szFname <= 'z')
  92. *szFname -= ('a' - 'A');
  93. ++szFname;
  94. }
  95. }
  96. VOID
  97. SpacePad(BYTE *szString, COUNT nChars)
  98. {
  99. REG COUNT i;
  100. for(i = strlen(szString); i < nChars; i++)
  101. szString[i] = ' ';
  102. }
  103. COUNT
  104. ParseDosName(BYTE FAR *lpszFileName,
  105.      COUNT *pnDrive,
  106.      BYTE *pszDir,
  107.      BYTE *pszFile,
  108.      BYTE *pszExt)
  109. {
  110. COUNT nDirCnt, nFileCnt, nExtCnt;
  111. BYTE FAR *lpszLclDir, FAR *lpszLclFile, FAR *lpszLclExt;
  112. /* Initialize the users data fields */
  113. if(pszDir)
  114. *pszDir = '';
  115. if(pszFile)
  116. *pszFile = '';
  117. if(pszExt)
  118. *pszExt = '';
  119. lpszLclFile = lpszLclExt = lpszLclDir = 0;
  120. nDirCnt = nFileCnt = nExtCnt = 0;
  121. /* Start by cheking for a drive specifier ... */
  122. if(DriveChar(*lpszFileName) && ':' == lpszFileName[1])
  123. {
  124. /* found a drive, fetch it and bump pointer past drive */
  125. /* NB: this code assumes ASCII */
  126. if(pnDrive)
  127. {
  128. *pnDrive = *lpszFileName - 'A';
  129. if(*pnDrive > 26)
  130. *pnDrive -= ('a' - 'A');
  131. }
  132. lpszFileName += 2;
  133. }
  134. else
  135. {
  136. if(pnDrive)
  137. {
  138. *pnDrive = -1;
  139. }
  140. }
  141. if(!pszDir && !pszFile && !pszExt)
  142. return SUCCESS;
  143. /* Now see how long a directory component we have.  We've */
  144. /* initialized the count before and moved the passed in pointer */
  145. /* past the optional drive component.  Now, we initialize the */
  146. /* directory count variable to a one if and only if we see a */
  147. /* leading root drive specifier because we can't be certain */
  148. /* that what follows is a directory until we see at least a */
  149. /* single path seperator.  So we count to the end and work */
  150. /* backwards to the last seperator subtracting one for each */
  151. /* character until we see one (seperator). */
  152. lpszLclDir = lpszFileName;
  153. while(bFileChar(*lpszFileName)
  154.    || PathSep(*lpszFileName)
  155.    || '.' == *lpszFileName)
  156. {
  157. ++nDirCnt;
  158. ++lpszFileName;
  159. }
  160. if(nDirCnt > 1)
  161. {
  162. while(lpszFileName >lpszLclDir)
  163. {
  164. BYTE cChar = *--lpszFileName;
  165. if(PathSep(cChar))
  166. break;
  167. --nDirCnt;
  168. }
  169. /* Once we've moved the pointer back, we want to bump */
  170. /* it past the seperator. */
  171. if(PathSep(*lpszFileName))
  172. ++lpszFileName;
  173. }
  174. /* Parse out the file name portion. */
  175. lpszLclFile = lpszFileName;
  176. while(bFileChar(*lpszFileName) && '.' != *lpszFileName)
  177. {
  178. ++nFileCnt;
  179. ++lpszFileName;
  180. }
  181. /* Now we have pointers set to the directory portion and the */
  182. /* file portion.  Now determine the existance of an extension. */
  183. lpszLclExt = lpszFileName;
  184. if('.' == *lpszFileName)
  185. {
  186. lpszLclExt = ++lpszFileName;
  187. while(bFileChar(*lpszFileName))
  188. {
  189. ++nExtCnt;
  190. ++lpszFileName;
  191. }
  192. }
  193. /* Fix lengths to maximums allowed by MS-DOS. */
  194. if(nDirCnt > PARSE_MAX)
  195. nDirCnt = PARSE_MAX;
  196. if(nFileCnt > FNAME_SIZE)
  197. nFileCnt = FNAME_SIZE;
  198. if(nExtCnt > FEXT_SIZE)
  199. nExtCnt = FEXT_SIZE;
  200. /* Finally copy whatever the user wants extracted to the user's */
  201. /* buffers. */
  202. if(pszDir)
  203. {
  204. fbcopy(lpszLclDir, (BYTE FAR *)pszDir, nDirCnt);
  205. pszDir[nDirCnt] = '';
  206. }
  207. if(pszFile)
  208. {
  209. fbcopy(lpszLclFile, (BYTE FAR *)pszFile, nFileCnt);
  210. pszFile[nFileCnt] = '';
  211. }
  212. if(pszExt)
  213. {
  214. fbcopy(lpszLclExt, (BYTE FAR *)pszExt, nExtCnt);
  215. pszExt[nExtCnt] = '';
  216. }
  217. /* Clean up before leaving */
  218. if(pszDir)
  219. DosTrimPath(pszDir);
  220. return SUCCESS;
  221. }
  222. COUNT
  223. ParseDosPath(BYTE FAR *lpszFileName,
  224.      COUNT *pnDrive,
  225.      BYTE *pszDir,
  226.      BYTE *pszCurPath)
  227. {
  228. COUNT nDirCnt, nPathCnt;
  229. BYTE FAR *lpszLclDir, *pszBase = pszDir;
  230. /* Initialize the users data fields */
  231. *pszDir = '';
  232. lpszLclDir = 0;
  233. nDirCnt = nPathCnt = 0;
  234. /* Start by cheking for a drive specifier ... */
  235. if(DriveChar(*lpszFileName) && ':' == lpszFileName[1])
  236. {
  237. /* found a drive, fetch it and bump pointer past drive */
  238. /* NB: this code assumes ASCII */
  239. if(pnDrive)
  240. {
  241. *pnDrive = *lpszFileName - 'A';
  242. if(*pnDrive > 26)
  243. *pnDrive -= ('a' - 'A');
  244. }
  245. lpszFileName += 2;
  246. }
  247. else
  248. {
  249. if(pnDrive)
  250. {
  251. *pnDrive = -1;
  252. }
  253. }
  254. lpszLclDir = lpszFileName;
  255. if(!PathSep(*lpszLclDir))
  256. {
  257. strncpy(pszDir, pszCurPath, PARSE_MAX);
  258. nPathCnt = strlen(pszCurPath);
  259. if(!PathSep(pszDir[nPathCnt - 1]) && nPathCnt < PARSE_MAX)
  260. pszDir[nPathCnt++] = '\';
  261. if(nPathCnt > PARSE_MAX)
  262. nPathCnt = PARSE_MAX;
  263. pszDir += nPathCnt;
  264. }
  265. /* Now see how long a directory component we have.   */
  266. while(bFileChar(*lpszFileName)
  267.    || PathSep(*lpszFileName)
  268.    || '.' == *lpszFileName)
  269. {
  270. ++nDirCnt;
  271. ++lpszFileName;
  272. }
  273. /* Fix lengths to maximums allowed by MS-DOS. */
  274. if((nDirCnt + nPathCnt)> PARSE_MAX)
  275. nDirCnt = PARSE_MAX - nPathCnt;
  276. /* Finally copy whatever the user wants extracted to the user's */
  277. /* buffers. */
  278. if(pszDir)
  279. {
  280. fbcopy(lpszLclDir, (BYTE FAR *)pszDir, nDirCnt);
  281. pszDir[nDirCnt] = '';
  282. }
  283. /* Clean up before leaving */
  284. DosTrimPath((BYTE FAR *)pszBase);
  285. /* Before returning to the user, eliminate any useless */
  286. /* trailing "\." since the path prior to this is sufficient. */
  287. nPathCnt = strlen(pszBase);
  288. if(2 == nPathCnt)   /* Special case, root */
  289. {
  290. if(!strcmp(pszBase, "\."))
  291. pszBase[1] = '';
  292. }
  293. else if(2 < nPathCnt)
  294. {
  295. if(!strcmp(&pszBase[nPathCnt - 2], "\."))
  296. pszBase[nPathCnt - 2] = '';
  297. }
  298. return SUCCESS;
  299. }
  300. BOOL
  301. IsDevice (BYTE *pszFileName)
  302. {
  303. REG struct dhdr FAR *dhp = (struct dhdr FAR *)&nul_dev;
  304. BYTE szName[FNAME_SIZE];
  305. /* break up the name first */
  306. ParseDosName((BYTE FAR *)pszFileName,
  307.  (COUNT *)0, TempBuffer, szName, (BYTE *)0);
  308. SpacePad(szName, FNAME_SIZE);
  309. /* Test 1 - does it start with a dev or /dev */
  310. if((strcmp(szName, "/dev") == 0)
  311.  || (strcmp(szName, "\dev") == 0))
  312. return TRUE;
  313. /* Test 2 - is it on the device chain? */
  314. for(; -1l != (LONG)dhp; dhp = dhp -> dh_next)
  315. {
  316. COUNT nIdx;
  317. /* Skip if not char device */
  318. if(!(dhp -> dh_attr & ATTR_CHAR))
  319. continue;
  320. /* now compare */
  321. for(nIdx = 0; nIdx < FNAME_SIZE; ++nIdx)
  322. {
  323. if(dhp -> dh_name[nIdx] != szName[nIdx])
  324. break;
  325. }
  326. if(nIdx >= FNAME_SIZE)
  327. return TRUE;
  328. }
  329. return FALSE;
  330. }
  331. VOID
  332. DosTrimPath (BYTE FAR *lpszPathNamep)
  333. {
  334. BYTE FAR *lpszLast, FAR *lpszNext, FAR *lpszRoot = (BYTE FAR *)0;
  335. COUNT nChars, flDotDot;
  336. /* First, convert all '/' to ''.  Look for root as we scan */
  337. if(*lpszPathNamep == '\')
  338. lpszRoot = lpszPathNamep;
  339. for(lpszNext = lpszPathNamep; *lpszNext; ++lpszNext)
  340. {
  341. if(*lpszNext == '/')
  342. *lpszNext = '\';
  343. if(!lpszRoot &&
  344.  *lpszNext == ':' && *(lpszNext + 1) == '\')
  345. lpszRoot = lpszNext + 1;
  346. }
  347. for(lpszLast = lpszNext = lpszPathNamep, nChars = 0;
  348.   *lpszNext != '' && nChars < NAMEMAX; )
  349. {
  350. /* Initialize flag for loop. */
  351. flDotDot = FALSE;
  352. /* If we are at a path seperator, check for extra path */
  353. /* seperator, '.' and '..' to reduce. */
  354. if(*lpszNext == '\')
  355. {
  356. /* If it's '', just move everything down one. */
  357. if(*(lpszNext + 1) == '\')
  358. fstrncpy(lpszNext, lpszNext + 1, NAMEMAX);
  359. /* also check for '.' and '..' and move down */
  360. /* as appropriate. */
  361. else if(*(lpszNext + 1) == '.')
  362. {
  363. if(*(lpszNext + 2) == '.'
  364.  && !(*(lpszNext + 3)))
  365. {
  366. /* At the end, just truncate */
  367. /* and exit. */
  368. if(lpszLast == lpszRoot)
  369. *(lpszLast + 1) = '';
  370. else
  371. *lpszLast = '';
  372. return;
  373. }
  374. if(*(lpszNext + 2) == '.'
  375.  && *(lpszNext + 3) == '\')
  376. {
  377. fstrncpy(lpszLast, lpszNext + 3, NAMEMAX);
  378. /* bump back to the last */
  379. /* seperator. */
  380. lpszNext = lpszLast;
  381. /* set lpszLast to the last one */
  382. if(lpszLast <= lpszPathNamep)
  383. continue;
  384. do
  385. {
  386. --lpszLast;
  387. }
  388. while(lpszLast != lpszPathNamep
  389.  && *lpszLast != '\');
  390. flDotDot = TRUE;
  391. }
  392. /* Note: we skip strange stuff that */
  393. /* starts with '.' */
  394. else if(*(lpszNext + 2) == '\')
  395. {
  396. fstrncpy(lpszNext, lpszNext + 2, NAMEMAX);
  397. }
  398. /* If we're at the end of a string, */
  399. /* just exit. */
  400. else if(*(lpszNext + 2) == NULL)
  401. return;
  402. }
  403. else
  404. {
  405. /* No '.' or '' so mark it and bump */
  406. /* past */
  407. lpszLast = lpszNext++;
  408. continue;
  409. }
  410. /* Done.  Now set last to next to mark this */
  411. /* instance of path seperator. */
  412. if(!flDotDot)
  413. lpszLast = lpszNext;
  414. }
  415. else
  416. /* For all other cases, bump lpszNext for the */
  417. /* next check */
  418. ++lpszNext;
  419. }
  420. }