ncbi_os_mac.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_os_mac.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:08:33  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_os_mac.cpp,v 1000.1 2004/06/01 19:08:33 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Jim Luther, Joshua Juran, Vlad Lebedev
  35.  *
  36.  * File Description:
  37.  *   Mac specifics
  38.  *
  39.  */
  40. /*
  41.  * NOTICE: Portions of this file have been taken and modified from
  42.  * original sources provided as part of Apple's "MoreFiles" package
  43.  * that carries the following copyright notice:
  44.  *
  45.  *    You may incorporate this sample code into your applications without
  46.  *    restriction, though the sample code has been provided "AS IS" and the
  47.  *    responsibility for its operation is 100% yours.  However, what you are
  48.  *    not permitted to do is to redistribute the source as "DSC Sample Code"
  49.  *    after having made changes. If you're going to re-distribute the source,
  50.  *    we require that you make it clear in the source that the code was
  51.  *    descended from Apple Sample Code, but that you've made changes.
  52.  */
  53. #include <ncbi_pch.hpp>
  54. #include <TextUtils.h>
  55. #include <corelib/ncbi_os_mac.hpp>
  56. extern bool g_Mac_SpecialEnvironment = false;
  57. BEGIN_NCBI_SCOPE
  58. /////////////////////////////////////////////////////////////////////////////
  59. //   COSErrException_Mac
  60. //
  61. static string s_OSErr_ComposeMessage(const OSErr& os_err, const string& what)
  62. {
  63.     string message;
  64.     if ( !what.empty() ) {
  65.         message = what + ": ";
  66.     }
  67.     message += os_err;
  68.     return message;
  69. }
  70. COSErrException_Mac::COSErrException_Mac(const OSErr&  os_err,
  71.                                          const string& what) THROWS_NONE
  72.     : exception(), m_OSErr(os_err)
  73. {
  74.     return;
  75. }
  76. COSErrException_Mac::~COSErrException_Mac(void) THROWS_NONE
  77. {
  78.     return;
  79. }
  80. static OSErr GetVolumeInfoNoName(ConstStr255Param pathname,
  81. short vRefNum,
  82. HParmBlkPtr pb)
  83. {
  84. Str255 tempPathname;
  85. OSErr error;
  86. /* Make sure pb parameter is not NULL */ 
  87. if ( pb != NULL )
  88. {
  89. pb->volumeParam.ioVRefNum = vRefNum;
  90. if ( pathname == NULL )
  91. {
  92. pb->volumeParam.ioNamePtr = NULL;
  93. pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
  94. }
  95. else
  96. {
  97. BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */
  98. pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */
  99. pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */
  100. }
  101. error = PBHGetVInfoSync(pb);
  102. pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */
  103. }
  104. else
  105. {
  106. error = paramErr;
  107. }
  108. return ( error );
  109. }
  110. static OSErr GetCatInfoNoName(short vRefNum,
  111.    long dirID,
  112.    ConstStr255Param name,
  113.    CInfoPBPtr pb)
  114. {
  115. Str31 tempName;
  116. OSErr error;
  117. /* Protection against File Sharing problem */
  118. if ( (name == NULL) || (name[0] == 0) )
  119. {
  120. tempName[0] = 0;
  121. pb->dirInfo.ioNamePtr = tempName;
  122. pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */
  123. }
  124. else
  125. {
  126. pb->dirInfo.ioNamePtr = (StringPtr)name;
  127. pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
  128. }
  129. pb->dirInfo.ioVRefNum = vRefNum;
  130. pb->dirInfo.ioDrDirID = dirID;
  131. error = PBGetCatInfoSync(pb);
  132. pb->dirInfo.ioNamePtr = NULL;
  133. return ( error );
  134. }
  135. static OSErr DetermineVRefNum(ConstStr255Param pathname,
  136.  short vRefNum,
  137.  short *realVRefNum)
  138. {
  139. HParamBlockRec pb;
  140. OSErr error;
  141. error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
  142. if ( error == noErr )
  143. {
  144. *realVRefNum = pb.volumeParam.ioVRefNum;
  145. }
  146. return ( error );
  147. }
  148. static OSErr GetDirectoryID(short vRefNum,
  149.    long dirID,
  150.    ConstStr255Param name,
  151.    long *theDirID,
  152.    Boolean *isDirectory)
  153. {
  154. CInfoPBRec pb;
  155. OSErr error;
  156. error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
  157. if ( error == noErr )
  158. {
  159. *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0;
  160. if ( *isDirectory )
  161. {
  162. *theDirID = pb.dirInfo.ioDrDirID;
  163. }
  164. else
  165. {
  166. *theDirID = pb.hFileInfo.ioFlParID;
  167. }
  168. }
  169. return ( error );
  170. }
  171. extern OSErr FSpGetDirectoryID(const FSSpec *spec,
  172.   long *theDirID,
  173.   Boolean *isDirectory)
  174. {
  175. return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,
  176.  theDirID, isDirectory) );
  177. }
  178. static OSErr CheckObjectLock(short vRefNum,
  179. long dirID,
  180. ConstStr255Param name)
  181. {
  182. CInfoPBRec pb;
  183. OSErr error;
  184. error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
  185. if ( error == noErr )
  186. {
  187. /* check locked bit */
  188. if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribLockedMask) != 0 )
  189. {
  190. error = fLckdErr;
  191. }
  192. }
  193. return ( error );
  194. }
  195. /*****************************************************************************/
  196. extern OSErr FSpCheckObjectLock(const FSSpec *spec)
  197. {
  198. return ( CheckObjectLock(spec->vRefNum, spec->parID, spec->name) );
  199. }
  200. static OSErr GetFileSize(short vRefNum,
  201. long dirID,
  202. ConstStr255Param fileName,
  203. long *dataSize,
  204. long *rsrcSize)
  205. {
  206. HParamBlockRec pb;
  207. OSErr error;
  208. pb.fileParam.ioNamePtr = (StringPtr)fileName;
  209. pb.fileParam.ioVRefNum = vRefNum;
  210. pb.fileParam.ioFVersNum = 0;
  211. pb.fileParam.ioDirID = dirID;
  212. pb.fileParam.ioFDirIndex = 0;
  213. error = PBHGetFInfoSync(&pb);
  214. if ( error == noErr )
  215. {
  216. *dataSize = pb.fileParam.ioFlLgLen;
  217. *rsrcSize = pb.fileParam.ioFlRLgLen;
  218. }
  219. return ( error );
  220. }
  221. extern OSErr FSpGetFileSize(const FSSpec *spec,
  222.    long *dataSize,
  223.    long *rsrcSize)
  224. {
  225. return ( GetFileSize(spec->vRefNum, spec->parID, spec->name, dataSize, rsrcSize) );
  226. }
  227. extern OSErr GetDirItems(short vRefNum,
  228. long dirID,
  229. ConstStr255Param name,
  230. Boolean getFiles,
  231. Boolean getDirectories,
  232. FSSpecPtr items,
  233. short reqItemCount,
  234. short *actItemCount,
  235. short *itemIndex) /* start with 1, then use what's returned */
  236. {
  237. CInfoPBRec pb;
  238. OSErr error;
  239. long theDirID;
  240. Boolean isDirectory;
  241. FSSpec *endItemsArray;
  242. if ( *itemIndex > 0 )
  243. {
  244. /* NOTE: If I could be sure that the caller passed a real vRefNum and real directory */
  245. /* to this routine, I could rip out calls to DetermineVRefNum and GetDirectoryID and this */
  246. /* routine would be much faster because of the overhead of DetermineVRefNum and */
  247. /* GetDirectoryID and because GetDirectoryID blows away the directory index hint the Macintosh */
  248. /* file system keeps for indexed calls. I can't be sure, so for maximum throughput, */
  249. /* pass a big array of FSSpecs so you can get the directory's contents with few calls */
  250. /* to this routine. */
  251. /* get the real volume reference number */
  252. error = DetermineVRefNum(name, vRefNum, &pb.hFileInfo.ioVRefNum);
  253. if ( error == noErr )
  254. {
  255. /* and the real directory ID of this directory (and make sure it IS a directory) */
  256. error = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
  257. if ( error == noErr )
  258. {
  259. if ( isDirectory )
  260. {
  261. *actItemCount = 0;
  262. endItemsArray = items + reqItemCount;
  263. while ( (items < endItemsArray) && (error == noErr) )
  264. {
  265. pb.hFileInfo.ioNamePtr = (StringPtr) &items->name;
  266. pb.hFileInfo.ioDirID = theDirID;
  267. pb.hFileInfo.ioFDirIndex = *itemIndex;
  268. error = PBGetCatInfoSync(&pb);
  269. if ( error == noErr )
  270. {
  271. items->parID = pb.hFileInfo.ioFlParID; /* return item's parID */
  272. items->vRefNum = pb.hFileInfo.ioVRefNum; /* return item's vRefNum */
  273. ++*itemIndex; /* prepare to get next item in directory */
  274. if ( (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
  275. {
  276. if ( getDirectories )
  277. {
  278. ++*actItemCount; /* keep this item */
  279. ++items; /* point to next item */
  280. }
  281. }
  282. else
  283. {
  284. if ( getFiles )
  285. {
  286. ++*actItemCount; /* keep this item */
  287. ++items; /* point to next item */
  288. }
  289. }
  290. }
  291. }
  292. }
  293. else
  294. {
  295. /* it wasn't a directory */
  296. error = dirNFErr;
  297. }
  298. }
  299. }
  300. }
  301. else
  302. {
  303. /* bad itemIndex */
  304. error = paramErr;
  305. }
  306. return ( error );
  307. }
  308. static OSErr FSpGetFullPath(const FSSpec *spec,
  309.    short *fullPathLength,
  310.    Handle *fullPath)
  311. {
  312. OSErr result;
  313. OSErr realResult;
  314. FSSpec tempSpec;
  315. CInfoPBRec pb;
  316. *fullPathLength = 0;
  317. *fullPath = NULL;
  318. /* Default to noErr */
  319. realResult = result = noErr;
  320. /* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
  321. if ( spec->name[0] == 0 )
  322. {
  323. result = FSMakeFSSpec(spec->vRefNum, spec->parID, spec->name, &tempSpec);
  324. }
  325. else
  326. {
  327. /* Make a copy of the input FSSpec that can be modified */
  328. BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
  329. }
  330. if ( result == noErr )
  331. {
  332. if ( tempSpec.parID == fsRtParID )
  333. {
  334. /* The object is a volume */
  335. /* Add a colon to make it a full pathname */
  336. ++tempSpec.name[0];
  337. tempSpec.name[tempSpec.name[0]] = ':';
  338. /* We're done */
  339. result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  340. }
  341. else
  342. {
  343. /* The object isn't a volume */
  344. /* Is the object a file or a directory? */
  345. pb.dirInfo.ioNamePtr = tempSpec.name;
  346. pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  347. pb.dirInfo.ioDrDirID = tempSpec.parID;
  348. pb.dirInfo.ioFDirIndex = 0;
  349. result = PBGetCatInfoSync(&pb);
  350. // Allow file/directory name at end of path to not exist.
  351. realResult = result;
  352. if ( (result == noErr) || (result == fnfErr) )
  353. {
  354. /* if the object is a directory, append a colon so full pathname ends with colon */
  355. if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
  356. {
  357. ++tempSpec.name[0];
  358. tempSpec.name[tempSpec.name[0]] = ':';
  359. }
  360. /* Put the object name in first */
  361. result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  362. if ( result == noErr )
  363. {
  364. /* Get the ancestor directory names */
  365. pb.dirInfo.ioNamePtr = tempSpec.name;
  366. pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  367. pb.dirInfo.ioDrParID = tempSpec.parID;
  368. do /* loop until we have an error or find the root directory */
  369. {
  370. pb.dirInfo.ioFDirIndex = -1;
  371. pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  372. result = PBGetCatInfoSync(&pb);
  373. if ( result == noErr )
  374. {
  375. /* Append colon to directory name */
  376. ++tempSpec.name[0];
  377. tempSpec.name[tempSpec.name[0]] = ':';
  378. /* Add directory name to beginning of fullPath */
  379. (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
  380. result = MemError();
  381. }
  382. } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
  383. }
  384. }
  385. }
  386. }
  387. if ( result == noErr )
  388. {
  389. /* Return the length */
  390. *fullPathLength = GetHandleSize(*fullPath);
  391. result = realResult; // return realResult in case it was fnfErr
  392. }
  393. else
  394. {
  395. /* Dispose of the handle and return NULL and zero length */
  396. if ( *fullPath != NULL )
  397. {
  398. DisposeHandle(*fullPath);
  399. }
  400. *fullPath = NULL;
  401. *fullPathLength = 0;
  402. }
  403. return ( result );
  404. }
  405. extern OSErr MacPathname2FSSpec(const char *inPathname, FSSpec *outFSS)
  406. {
  407. OSErr err;
  408. size_t len;
  409. char *p;
  410. short vRefNum;
  411. long dirID;
  412. FSSpec fss;
  413. if (inPathname == NULL || outFSS == NULL) {
  414. return paramErr;
  415. }
  416. err = HGetVol(NULL, &vRefNum, &dirID);  // default volume and directory
  417. if (err != noErr) return err;
  418. len = strlen(inPathname);
  419. p = strchr(inPathname, ':');
  420. if (p == inPathname  &&  len == 1) {
  421. err = FSMakeFSSpec(vRefNum, dirID, "p", outFSS);
  422. return err;
  423. }
  424. if (p == NULL) {
  425. // Partial pathname -- filename only
  426. Str31 filename;
  427. assert(len <= 31);
  428. Pstrcpy(filename, inPathname);
  429. err = FSMakeFSSpec(vRefNum, dirID, filename, outFSS);
  430. } else {
  431. Str31 name;
  432. int nameLen;
  433. if (inPathname[0] == ':') {
  434. // Relative pathname including directory path
  435. } else {
  436. // Absolute pathname
  437. //Str31 volName;  // We would use Str28 if it was defined -- 27, plus 1 for ':'.
  438. nameLen = p - inPathname;
  439. assert(nameLen <= 27);
  440. name[0] = nameLen + 1;
  441. memcpy(name + 1, inPathname, nameLen + 1);  // Copy the volume name and the colon.
  442. err = DetermineVRefNum(name, 0, &vRefNum);
  443. if (err != noErr) return err;
  444. dirID = 2;
  445. }
  446. // vRefNum and dirID now specify the directory in which we should descend
  447. // the path pointed to by p (pointing to the first colon).
  448. p++;
  449. while (p != NULL && *p != '') {
  450. char *q = strchr(p, ':');
  451. if (q != NULL) {
  452. Boolean isDir;
  453. nameLen = q - p;
  454. assert(nameLen <= 31);
  455. name[0] = nameLen;
  456. memcpy(name + 1, p, nameLen);
  457. err = FSMakeFSSpec(vRefNum, dirID, name, &fss);
  458. if (err != noErr) return err;
  459. if (q[1] == '') {
  460. p = NULL;
  461. *outFSS = fss;
  462. } else {
  463. err = FSpGetDirectoryID(&fss, &dirID, &isDir);
  464. assert(isDir == true);
  465. if (err != noErr) return err;
  466. p = q + 1;
  467. }
  468. } else {
  469. q = strchr(p, '');  // go to end of string
  470. nameLen = q - p;
  471. assert(nameLen > 0);
  472. assert(nameLen <= 31);
  473. Pstrcpy(name, p);
  474. p = NULL;
  475. err = FSMakeFSSpec(vRefNum, dirID, name, outFSS);
  476. }
  477. }
  478. }
  479. return err;
  480. }
  481. extern OSErr MacFSSpec2FullPathname(const FSSpec *inFSS, char **outPathname)
  482. {
  483. OSErr err;
  484. Handle h;
  485. short fullPathLength;
  486. static char *fullPath = NULL;
  487. if (fullPath != NULL) {
  488. delete [] fullPath;
  489. fullPath = NULL;
  490. }
  491. err = FSpGetFullPath(inFSS, &fullPathLength, &h);
  492. if (err != noErr) return err;
  493. assert(fullPathLength >= 2);  // An absolute pathname must be at least two chars long
  494. fullPath = new char [fullPathLength + 1];
  495. if (fullPath == NULL) {
  496. err = memFullErr;
  497. } else {
  498. memmove(fullPath, *h, fullPathLength);
  499. fullPath[fullPathLength] = '';
  500. }
  501. DisposeHandle(h);
  502. *outPathname = fullPath;
  503. return err;
  504. }
  505. END_NCBI_SCOPE
  506. /* --------------------------------------------------------------------------
  507.  * $Log: ncbi_os_mac.cpp,v $
  508.  * Revision 1000.1  2004/06/01 19:08:33  gouriano
  509.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  510.  *
  511.  * Revision 1.8  2004/05/14 13:59:26  gorelenk
  512.  * Added include of ncbi_pch.hpp
  513.  *
  514.  * Revision 1.7  2003/05/23 20:34:14  lavr
  515.  * Show permitting Apple's notice about changes in original "MoreFiles" code
  516.  *
  517.  * Revision 1.6  2003/05/23 20:22:59  ucko
  518.  * Correct author list; include Jim Luther, who wrote the MoreFiles code.
  519.  *
  520.  * Revision 1.4  2003/02/27 22:03:59  lebedev
  521.  * COSErrException_Mac changed from runtime_error to exception
  522.  *
  523.  * Revision 1.3  2001/12/18 21:40:39  juran
  524.  * Copy in MoreFiles fucntions that we need.
  525.  *
  526.  * Revision 1.2  2001/12/03 22:00:55  juran
  527.  * Add g_Mac_SpecialEnvironment global.
  528.  *
  529.  * Revision 1.1  2001/11/19 18:11:08  juran
  530.  * Implements Mac OS-specific header.
  531.  * Inital check-in.
  532.  *
  533.  * ==========================================================================
  534.  */