CDFILE.CPP 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. ** Command & Conquer(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: F:\projects\c&c\vcs\code\cdfile.cpv 2.18 16 Oct 1995 16:48:10 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Westwood Library *
  24. * *
  25. * File Name : CDFILE.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : October 18, 1994 *
  30. * *
  31. * Last Update : October 18, 1994 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
  36. * CDFileClass::Open -- Opens the file object -- with path search. *
  37. * CDFileClass::Open -- Opens the file wherever it can be found. *
  38. * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
  39. * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
  40. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  41. #include "function.h"
  42. //#include "cdfile.h"
  43. /*
  44. ** Pointer to the first search path record.
  45. */
  46. CDFileClass::SearchDriveType * CDFileClass::First = 0;
  47. int CDFileClass::CurrentCDDrive = 0;
  48. int CDFileClass::LastCDDrive = 0;
  49. char CDFileClass::RawPath[512];
  50. int __cdecl Is_Disk_Inserted(int disk)
  51. {
  52. struct find_t fb;
  53. char scan[] = "?:\\*.*";
  54. scan[0] = 'A' + disk;
  55. return(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);
  56. }
  57. CDFileClass::CDFileClass(char const *filename) :
  58. IsDisabled(false)
  59. {
  60. Set_Name(filename);
  61. memset (RawPath, 0, sizeof(RawPath));
  62. }
  63. CDFileClass::CDFileClass(void) :
  64. IsDisabled(false)
  65. {
  66. }
  67. /***********************************************************************************************
  68. * CDFileClass::Open -- Opens the file object -- with path search. *
  69. * *
  70. * This will open the file object, but since the file object could have been constructed *
  71. * with a pathname, this routine will try to find the file first. For files opened for *
  72. * writing, then use the existing filename without performing a path search. *
  73. * *
  74. * INPUT: rights -- The access rights to use when opening the file *
  75. * *
  76. * OUTPUT: bool; Was the open successful? *
  77. * *
  78. * WARNINGS: none *
  79. * *
  80. * HISTORY: *
  81. * 10/18/1994 JLB : Created. *
  82. *=============================================================================================*/
  83. int CDFileClass::Open(int rights)
  84. {
  85. return(RawFileClass::Open(rights));
  86. }
  87. /***********************************************************************************************
  88. * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added *
  89. * *
  90. * *
  91. * *
  92. * INPUT: Nothing *
  93. * *
  94. * OUTPUT: Nothing *
  95. * *
  96. * WARNINGS: None *
  97. * *
  98. * HISTORY: *
  99. * 5/22/96 9:01AM ST : Created *
  100. *=============================================================================================*/
  101. void CDFileClass::Refresh_Search_Drives (void)
  102. {
  103. Clear_Search_Drives();
  104. Set_Search_Drives(RawPath);
  105. }
  106. /***********************************************************************************************
  107. * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
  108. * *
  109. * This routine sets up a list of search paths to use when accessing files. The path list *
  110. * is scanned if the file could not be found in the current directory. This is the primary *
  111. * method of supporting CD-ROM drives, but is also useful for scanning network and other *
  112. * directories. The pathlist as passed to this routine is of the same format as the path *
  113. * list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*
  114. * *
  115. * If a path entry begins with "?:" then the question mark will be replaced with the first *
  116. * CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path *
  117. * entry will be ignored. By using this feature, you can always pass the CD-ROM path *
  118. * specification to this routine and it will not break if the CD-ROM is not loaded (as in *
  119. * the case during development). *
  120. * *
  121. * Here is an example path specification: *
  122. * *
  123. * Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA"); *
  124. * *
  125. * In this example, the current directory will be searched first, followed by a the *
  126. * subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM *
  127. * will be searched in a directory called "\DATA". If not found or the CD-ROM is not *
  128. * present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a *
  129. * network?). If all of these searches fail, the file system will default to the current *
  130. * directory and let the normal file error system take over. *
  131. * *
  132. * INPUT: pathlist -- Pointer to string of path specifications (separated by semicolons) *
  133. * that will be used to search for files. *
  134. * *
  135. * OUTPUT: none *
  136. * *
  137. * WARNINGS: none *
  138. * *
  139. * HISTORY: *
  140. * 10/18/1994 JLB : Created. *
  141. * 05/21/1996 ST : Modified to recognise multiple CD drives *
  142. *=============================================================================================*/
  143. int CDFileClass::Set_Search_Drives(char * pathlist)
  144. {
  145. int found = FALSE;
  146. int empty = FALSE;
  147. /*
  148. ** If there is no pathlist to add, then just return.
  149. */
  150. if (!pathlist) return(0);
  151. /*
  152. ** Save the path as it was passed in so we can parse it again later.
  153. ** Check for the case where RawPath was passed in.
  154. */
  155. if (pathlist != RawPath){
  156. strcat (RawPath, ";");
  157. strcat (RawPath, pathlist);
  158. }
  159. char const * ptr = strtok(pathlist, ";");
  160. while (ptr) {
  161. if (strlen(ptr)){
  162. char path[PATH_MAX]; // Working path buffer.
  163. /*
  164. ** Fixup the path to be legal. Legal is defined as all that is necessary to
  165. ** create a pathname is to append the actual filename submitted to the
  166. ** file system. This means that it must have either a trailing ':' or '\'
  167. ** character.
  168. */
  169. strcpy(path, ptr);
  170. switch (path[strlen(path)-1]) {
  171. case ':':
  172. case '\\':
  173. break;
  174. default:
  175. strcat(path, "\\");
  176. break;
  177. }
  178. /*
  179. ** If there is a drive letter specified, and this drive letter is '?', then it should
  180. ** be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then
  181. ** merely ignore this path entry.
  182. */
  183. if (strncmp(path, "?:", 2) == 0) {
  184. if (CurrentCDDrive){
  185. found = TRUE;
  186. /*
  187. ** If the drive has a C&C CD in it then add it to the path
  188. */
  189. if (Get_CD_Index(CurrentCDDrive, 2*60) >= 0){
  190. path[0] = CurrentCDDrive + 'A';
  191. Add_Search_Drive(path);
  192. }
  193. }
  194. /*
  195. ** Find the next path string and resubmit.
  196. */
  197. ptr = strtok(NULL, ";");
  198. continue;
  199. }
  200. found = TRUE;
  201. Add_Search_Drive(path);
  202. }
  203. /*
  204. ** Find the next path string and resubmit.
  205. */
  206. ptr = strtok(NULL, ";");
  207. }
  208. if (!found) return(1);
  209. if (empty) return(2);
  210. return(0);
  211. }
  212. /***********************************************************************************************
  213. * CDFC::Set_CD_Drive -- sets the current CD drive letter *
  214. * *
  215. * *
  216. * *
  217. * INPUT: Nothing *
  218. * *
  219. * OUTPUT: Nothing *
  220. * *
  221. * WARNINGS: None *
  222. * *
  223. * HISTORY: *
  224. * 5/22/96 9:39AM ST : Created *
  225. *=============================================================================================*/
  226. void CDFileClass::Set_CD_Drive (int drive)
  227. {
  228. LastCDDrive = CurrentCDDrive;
  229. CurrentCDDrive = drive;
  230. }
  231. /***********************************************************************************************
  232. * CDFC::Add_Search_Drive -- Add a new path to the search path list *
  233. * *
  234. * *
  235. * *
  236. * INPUT: path *
  237. * *
  238. * OUTPUT: Nothing *
  239. * *
  240. * WARNINGS: None *
  241. * *
  242. * HISTORY: *
  243. * 5/22/96 10:12AM ST : Created *
  244. *=============================================================================================*/
  245. void CDFileClass::Add_Search_Drive(char *path)
  246. {
  247. SearchDriveType *srch; // Working pointer to path object.
  248. /*
  249. ** Allocate a record structure.
  250. */
  251. srch = new SearchDriveType;
  252. /*
  253. ** Attach the path to this structure.
  254. */
  255. srch->Path = strdup(path);
  256. srch->Next = NULL;
  257. /*
  258. ** Attach this path record to the end of the path chain.
  259. */
  260. if (!First) {
  261. First = srch;
  262. } else {
  263. SearchDriveType * chain = First;
  264. while (chain->Next) {
  265. chain = (SearchDriveType *)chain->Next;
  266. }
  267. chain->Next = srch;
  268. }
  269. }
  270. /***********************************************************************************************
  271. * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
  272. * *
  273. * Use this routine to clear out any previous path(s) set with Set_Search_Drives() *
  274. * function. *
  275. * *
  276. * INPUT: none *
  277. * *
  278. * OUTPUT: none *
  279. * *
  280. * WARNINGS: none *
  281. * *
  282. * HISTORY: *
  283. * 10/18/1994 JLB : Created. *
  284. *=============================================================================================*/
  285. void CDFileClass::Clear_Search_Drives(void)
  286. {
  287. SearchDriveType * chain; // Working pointer to path chain.
  288. chain = First;
  289. while (chain) {
  290. SearchDriveType *next;
  291. next = (SearchDriveType *)chain->Next;
  292. if (chain->Path) {
  293. free((char *)chain->Path);
  294. }
  295. delete chain;
  296. chain = next;
  297. }
  298. First = 0;
  299. }
  300. /***********************************************************************************************
  301. * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
  302. * *
  303. * This routine will scan all the directories specified in the path list and if the file *
  304. * was found in one of the directories, it will set the filename to a composite of the *
  305. * correct directory and the filename. It is used to allow path searching when searching *
  306. * for files. Typical use is to support CD-ROM drives. This routine examines the current *
  307. * directory first before scanning through the path list. If after scanning the entire *
  308. * path list, the file still could not be found, then the file object's name is set with *
  309. * just the raw filename as passed to this routine. *
  310. * *
  311. * INPUT: filename -- Pointer to the filename to set as the name of this file object. *
  312. * *
  313. * OUTPUT: Returns a pointer to the final and complete filename of this file object. This *
  314. * may have a path attached to the file. *
  315. * *
  316. * WARNINGS: none *
  317. * *
  318. * HISTORY: *
  319. * 10/18/1994 JLB : Created. *
  320. *=============================================================================================*/
  321. char const * CDFileClass::Set_Name(char const *filename)
  322. {
  323. /*
  324. ** Try to find the file in the current directory first. If it can be found, then
  325. ** just return with the normal file name setting process. Do the same if there is
  326. ** no multi-drive search path.
  327. */
  328. RawFileClass::Set_Name(filename);
  329. if (IsDisabled || !First || RawFileClass::Is_Available()) {
  330. return(File_Name());
  331. }
  332. /*
  333. ** Attempt to find the file first. Check the current directory. If not found there, then
  334. ** search all the path specifications available. If it still can't be found, then just
  335. ** fall into the normal raw file filename setting system.
  336. */
  337. SearchDriveType * srch = First;
  338. while (srch) {
  339. char path[_MAX_PATH];
  340. /*
  341. ** Build a pathname to search for.
  342. */
  343. strcpy(path, srch->Path);
  344. strcat(path, filename);
  345. /*
  346. ** Check to see if the file could be found. The low level Is_Available logic will
  347. ** prompt if necessary when the CD-ROM drive has been removed. In all other cases,
  348. ** it will return false and the search process will continue.
  349. */
  350. RawFileClass::Set_Name(path);
  351. if (RawFileClass::Is_Available()) {
  352. return(File_Name());
  353. }
  354. /*
  355. ** It wasn't found, so try the next path entry.
  356. */
  357. srch = (SearchDriveType *)srch->Next;
  358. }
  359. /*
  360. ** At this point, all path searching has failed. Just set the file name to the
  361. ** plain text passed to this routine and be done with it.
  362. */
  363. RawFileClass::Set_Name(filename);
  364. return(File_Name());
  365. }
  366. /***********************************************************************************************
  367. * CDFileClass::Open -- Opens the file wherever it can be found. *
  368. * *
  369. * This routine is similar to the RawFileClass open except that if the file is being *
  370. * opened only for READ access, it will search all specified directories looking for the *
  371. * file. If after a complete search the file still couldn't be found, then it is opened *
  372. * using the normal RawFileClass system -- resulting in normal error procedures. *
  373. * *
  374. * INPUT: filename -- Pointer to the override filename to supply for this file object. It *
  375. * would be the base filename (sans any directory specification). *
  376. * *
  377. * rights -- The access rights to use when opening the file. *
  378. * *
  379. * OUTPUT: bool; Was the file opened successfully? If so then the filename may be different *
  380. * than requested. The location of the file can be determined by examining the *
  381. * filename of this file object. The filename will contain the complete *
  382. * pathname used to open the file. *
  383. * *
  384. * WARNINGS: none *
  385. * *
  386. * HISTORY: *
  387. * 10/18/1994 JLB : Created. *
  388. *=============================================================================================*/
  389. int CDFileClass::Open(char const *filename, int rights)
  390. {
  391. Close();
  392. /*
  393. ** Verify that there is a filename associated with this file object. If not, then this is a
  394. ** big error condition.
  395. */
  396. if (!filename) {
  397. Error(ENOENT, false);
  398. }
  399. /*
  400. ** If writing is requested, then multiple drive searching is not performed.
  401. */
  402. if (IsDisabled || rights == WRITE) {
  403. return(RawFileClass::Open(filename, rights));
  404. }
  405. /*
  406. ** Perform normal multiple drive searching for the filename and open
  407. ** using the normal procedure.
  408. */
  409. Set_Name(filename);
  410. return(RawFileClass::Open(rights));
  411. }
  412. #ifdef NEVER
  413. /* Get the drive letters if the CD's online */
  414. WORD __cdecl GetCDDrive(VOID)
  415. {
  416. _ES = FP_SEG(&cdDrive[0]);
  417. _BX = FP_OFF(&cdDrive[0]);
  418. _AX = 0x150d;
  419. geninterrupt(0x2F);
  420. return((WORD)(*cdDrive));
  421. }
  422. #endif
  423. int Get_CD_Drive(void)
  424. {
  425. #ifdef NEVER
  426. for (int index = 0; index < 26; index++) {
  427. union REGS regs;
  428. regs.w.ax = 0x150B;
  429. regs.w.bx = 0;
  430. regs.w.cx = index;
  431. int386(0x2F, &regs, &regs);
  432. if (regs.w.bx == 0xADAD) {
  433. return(index);
  434. }
  435. }
  436. return(0);
  437. #else
  438. // GetCDClass temp;
  439. // return(temp.GetCDDrive());
  440. return (0);
  441. #endif
  442. }