|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* @(#)MacOSStubs.c 4.0
23: *
24: * (c) 1997-1999 Apple Computer, Inc. All Rights Reserved
25: *
26: * MacOSStubs.c -- Contains routines called by MacOS code, that is not defined.
27: *
28: * HISTORY
29: * 9-9-99 Don Brady Don't use MNT_WAIT in C_FlushMDB.
30: * 9-Mar-1999 Don Brady Remove more obsolete routines, add ClearMemory(bzero).
31: * 20-Nov-1998 Don Brady Remove UFSToHFSStr and HFSToUFSStr routines (obsolete).
32: * 31-Aug-1998 Don Brady Move DST adjustments to GetTimeLocal (radar #2265075).
33: * 28-Jul-1998 Don Brady Add GetDiskBlocks routine (radar #2258148).
34: * 23-Jul-1998 Don Brady Use bdwrite instead of bwrite for default in RelBlock_glue (radar #2257225).
35: * 7-Jul-1998 Don Brady Remove character mappings from/to hfs (ufs_hfs and hfs_ufs tables).
36: * 22-Jun-1998 Pat Dirks Added the vice versa mappings in ufs_hfs and hfs_ufs to more
37: * thoroughly interchange ":" and "/" in name strings.
38: * 4-Jun-1998 Pat Dirks Changed to do all B*-Tree writes synchronously (FORCESYNCBTREEWRITES = 1)
39: * 4-jun-1998 Don Brady Use VPUT macro instead of vput.
40: * 6-may-1998 Don Brady Bump h_devvp refcount in GetInitializedVNode (radar #2232480).
41: * 27-apr-1998 Don Brady Change printf to kprintf.
42: * 23-Apr-1998 Pat Dirks Cleaned up GetBlock_glue to add brelse on I/O errors from bread.
43: * 23-apr-1998 Don Brady Add '/' to ':' mapping and vice versa to mapping tables.
44: * 21-apr-1998 Don Brady Clean up time/date conversion routines.
45: * 11-apr-1998 Don Brady Add RequireFileLock routine.
46: * 8-apr-1998 Don Brady C_FlushMDB now calls hfs_flushvolumeheader and hfs_flushMDB.
47: * 12-nov-1997 Scott Roberts
48: * Initially created file.
49: *
50: */
51: #include <sys/param.h>
52: #include <sys/systm.h>
53: #include <sys/kernel.h>
54: #include <sys/vnode.h>
55: #include <sys/buf.h>
56: #include <sys/malloc.h>
57: #include <sys/mount.h>
58: #include <dev/disk.h>
59: #include "hfs.h"
60: #include "hfs_dbg.h"
61:
62:
63: #include "hfscommon/headers/FileMgrInternal.h"
64:
65: extern int (**hfs_vnodeop_p)();
66:
67:
68: struct timezone gTimeZone = {8*60,1}; /*XXX need to dynamically set this global from HFS Util */
69:
70:
71: /*************************************************************************************/
72:
73: /*************************************************************************************/
74: /*
75: * The following two routines work in tandem: StoreBufferMapping stores
76: * successive buffer address -> buffer pointer mappings in a circular
77: * match list, advancing the list index forward each time, while LookupBufferMapping
78: * looks backwards through the list to look up a particular mapping (which is
79: * typically the entry currently pointed to by gBufferAddress).
80: *
81: */
82: static void StoreBufferMapping(caddr_t bufferAddress, struct buf *bp)
83: {
84: int i;
85:
86: DBG_ASSERT(gBufferListIndex >= 0);
87: DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
88:
89: simple_lock(&gBufferPtrListLock);
90:
91: /* We've got at most BUFFERPTRLISTSIZE tries at this... */
92: for (i = BUFFERPTRLISTSIZE; i > 0; --i) {
93: if (gBufferAddress[gBufferListIndex] == NULL) {
94: gBufferAddress[gBufferListIndex] = bufferAddress;
95: gBufferHeaderPtr[gBufferListIndex] = bp;
96: break;
97: }
98: gBufferListIndex = (gBufferListIndex + 1) % BUFFERPTRLISTSIZE;
99: };
100:
101: if (i == 0) {
102: panic("StoreBufferMapping: couldn't find an empty slot in buffer list.");
103: };
104:
105: DBG_ASSERT(gBufferListIndex >= 0);
106: DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
107:
108: simple_unlock(&gBufferPtrListLock);
109: }
110:
111:
112: /*static*/ OSErr LookupBufferMapping(caddr_t bufferAddress, struct buf **bpp, int *mappingIndexPtr)
113: {
114: OSErr err = E_NONE;
115: int i;
116: int listIndex = gBufferListIndex;
117: struct buf *bp = NULL;
118:
119: DBG_ASSERT(gBufferListIndex >= 0);
120: DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
121:
122: simple_lock(&gBufferPtrListLock);
123:
124: /* We've got at most BUFFERPTRLISTSIZE tries at this... */
125: for (i = BUFFERPTRLISTSIZE; i > 0; --i) {
126: if (gBufferAddress[listIndex] == bufferAddress) {
127: *mappingIndexPtr = listIndex;
128: bp = gBufferHeaderPtr[listIndex];
129: break;
130: };
131:
132: listIndex = (listIndex - 1);
133: if (listIndex < 0) {
134: listIndex = BUFFERPTRLISTSIZE - 1;
135: };
136: };
137:
138: if (bp == NULL) {
139: DEBUG_BREAK_MSG(("LookupBufferMapping: couldn't find buffer header for buffer in list.\n"));
140: err = -1;
141: };
142:
143: DBG_ASSERT(gBufferListIndex >= 0);
144: DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
145:
146: simple_unlock(&gBufferPtrListLock);
147:
148: *bpp = bp;
149: return err;
150: }
151:
152:
153: static void ReleaseMappingEntry(int entryIndex) {
154:
155: DBG_ASSERT(gBufferListIndex >= 0);
156: DBG_ASSERT(gBufferListIndex < BUFFERPTRLISTSIZE);
157:
158: simple_lock(&gBufferPtrListLock);
159: gBufferAddress[entryIndex] = NULL;
160: simple_unlock(&gBufferPtrListLock);
161: };
162: #if HFS_DIAGNOSTIC
163: #define DBG_GETBLOCK 0
164: #else
165: #define DBG_GETBLOCK 0
166: #endif
167:
168: OSErr GetBlock_glue (UInt16 options, UInt32 blockNum, Ptr *baddress, FileReference fileRefNum, ExtendedVCB * vcb)
169: {
170: int status;
171: struct buf *bp = NULL;
172: int readcount = 0;
173:
174: #if DBG_GETBLOCK
175: DBG_IO(("Getting block %ld with options %d and a refnum of %x\n", blockNum, options, fileRefNum ));
176: #endif
177:
178: if ((options & ~(gbReadMask | gbNoReadMask)) != 0) {
179: DEBUG_BREAK_MSG(("GetBlock_glue: options = 0x%04X.\n", options));
180: };
181:
182: *baddress = NULL;
183:
184: if (options & gbNoReadMask) {
185: if (fileRefNum == NULL) {
186: bp = getblk (VCBTOHFS(vcb)->hfs_devvp,
187: IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
188: IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
189: 0,
190: 0);
191: } else {
192: bp = getblk (fileRefNum,
193: IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
194: IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
195: 0,
196: 0);
197: };
198: status = E_NONE;
199: } else {
200: do {
201: if (fileRefNum == NULL) {
202: status = bread (VCBTOHFS(vcb)->hfs_devvp,
203: IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
204: IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
205: NOCRED,
206: &bp);
207: } else {
208: status = bread (fileRefNum,
209: IOBLKNOFORBLK(blockNum, VCBTOHFS(vcb)->hfs_phys_block_size),
210: IOBYTECCNTFORBLK(blockNum, kHFSBlockSize, VCBTOHFS(vcb)->hfs_phys_block_size),
211: NOCRED,
212: &bp);
213: };
214: if (status != E_NONE) {
215: if (bp) brelse(bp);
216: goto Error_Exit;
217: };
218:
219: if (bp == NULL) {
220: status = -1;
221: goto Error_Exit;
222: };
223:
224: ++readcount;
225:
226: if ((options & gbReadMask) && (bp->b_flags & B_CACHE)) {
227: /* Rats! The block was found in the cache just when we really wanted a
228: fresh copy off disk...
229: */
230: if (bp->b_flags & B_DIRTY) {
231: DEBUG_BREAK_MSG(("GetBlock_glue: forced read for dirty block!\n"))
232: };
233: bp->b_flags |= B_INVAL;
234: brelse(bp);
235:
236: /* Fall through and try again until we get a fresh copy from the disk... */
237: };
238: } while (((options & gbReadMask) != 0) && (readcount <= 1));
239: };
240:
241: *baddress = bp->b_data + IOBYTEOFFSETFORBLK(bp->b_blkno, VCBTOHFS(vcb)->hfs_phys_block_size);
242: StoreBufferMapping(*baddress, bp);
243:
244: Error_Exit: ;
245: return status;
246: }
247:
248: void MarkBlock_glue (Ptr address)
249: {
250: int err;
251: struct buf *bp = NULL;
252: int mappingEntry;
253:
254: if ((err = LookupBufferMapping(address, &bp, &mappingEntry))) {
255: panic("Failed to find buffer pointer for buffer in MarkBlock_glue.");
256: } else {
257: bp->b_flags |= B_DIRTY;
258: };
259: }
260:
261: OSErr RelBlock_glue (Ptr address, UInt16 options )
262: {
263: int err;
264: struct buf *bp;
265: int mappingEntry;
266:
267: if (options & ~(rbTrashMask | rbDirtyMask | rbWriteMask) == 0) {
268: DEBUG_BREAK_MSG(("RelBlock_glue: options = 0x%04X.\n", options));
269: };
270:
271: if ((err = LookupBufferMapping(address, &bp, &mappingEntry))) {
272: DEBUG_BREAK_MSG(("Failed to find buffer pointer for buffer in RelBlock_glue.\n"));
273: } else {
274: if (bp->b_flags & B_DIRTY) {
275: /* The buffer was previously marked dirty (using MarkBlock_glue):
276: now's the time to write it. */
277: options |= rbDirtyMask;
278: };
279: ReleaseMappingEntry(mappingEntry);
280: if (options & rbTrashMask) {
281: bp->b_flags |= B_INVAL;
282: brelse(bp);
283: } else {
284: if (options & (rbDirtyMask | rbWriteMask)) {
285: bp->b_flags |= B_DIRTY;
286: if (options & rbWriteMask) {
287: bwrite(bp);
288: } else {
289: bdwrite(bp);
290: }
291: } else {
292: brelse(bp);
293: };
294: };
295: err = E_NONE;
296: };
297: return err;
298: }
299:
300: /* */
301: /* Creates a new vnode to hold a psuedo file like an extents tree file */
302: /* */
303:
304: OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode )
305: {
306:
307: struct hfsnode *hp;
308: struct vnode *vp = NULL;
309: int rtn;
310:
311: DBG_ASSERT(hfsmp != NULL);
312: DBG_ASSERT(tmpvnode != NULL);
313:
314: /* Allocate a new hfsnode. */
315: /*
316: * Must do malloc() before getnewvnode(), since malloc() can block
317: * and could cause other part of the system to access v_data
318: * which has not been initialized yet
319: */
320: MALLOC(hp, struct hfsnode *, sizeof(struct hfsnode), M_HFSNODE, M_WAITOK);
321: if(hp == NULL) {
322: rtn = ENOMEM;
323: goto Err_Exit;
324: }
325: bzero((caddr_t)hp, sizeof(struct hfsnode));
326: lockinit(&hp->h_lock, PINOD, "hfsnode", 0, 0);
327:
328: MALLOC(hp->h_meta, struct hfsfilemeta *,
329: sizeof(struct hfsfilemeta), M_HFSFMETA, M_WAITOK);
330: /* Allocate a new vnode. */
331: if ((rtn = getnewvnode(VT_HFS, HFSTOVFS(hfsmp), hfs_vnodeop_p, &vp))) {
332: FREE(hp->h_meta, M_HFSFMETA);
333: FREE(hp, M_HFSNODE);
334: goto Err_Exit;
335: }
336:
337: /* Init the structure */
338: bzero(hp->h_meta, sizeof(struct hfsfilemeta));
339:
340: hp->h_vp = vp; /* Make HFSTOV work */
341: hp->h_meta->h_devvp = hfsmp->hfs_devvp;
342: hp->h_meta->h_dev = hfsmp->hfs_raw_dev;
343: hp->h_meta->h_usecount++;
344: hp->h_nodeflags |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
345: hp->h_valid = HFS_VNODE_MAGIC;
346:
347: vp->v_data = hp; /* Make VTOH work */
348: vp->v_type = VREG;
349:
350: *tmpvnode = vp;
351:
352: VREF(hp->h_meta->h_devvp);
353:
354: return noErr;
355:
356: Err_Exit:
357: if (vp)
358: {
359: VPUT(vp);
360: vp->v_type = VNON;
361: vgone(vp);
362: }
363:
364: *tmpvnode = NULL;
365:
366: return rtn;
367: }
368:
369: OSErr GetNewFCB(ExtendedVCB *vcb, FileReference* fRefPtr)
370: {
371: OSErr err;
372:
373: err = GetInitializedVNode( VCBTOHFS(vcb), fRefPtr );
374: panic("This node is not completely initialized in GetNewFCB!"); /* XXX SER */
375:
376: return( err );
377: }
378:
379:
380: OSErr CheckVolumeOffLine( ExtendedVCB *vcb )
381: {
382:
383: return( 0 );
384: }
385:
386:
387: OSErr C_FlushMDB( ExtendedVCB *volume)
388: {
389: short err;
390:
391: if (volume->vcbSigWord == kHFSPlusSigWord)
392: err = hfs_flushvolumeheader(VCBTOHFS(volume), 0);
393: else
394: err = hfs_flushMDB(VCBTOHFS(volume), 0);
395:
396: return err;
397: }
398:
399:
400: /*
401: * GetTimeUTC - get the GMT Mac OS time (in seconds since 1/1/1904)
402: *
403: * called by the Catalog Manager when creating/updating records
404: */
405: UInt32 GetTimeUTC(void)
406: {
407: return (time.tv_sec + MAC_GMT_FACTOR);
408: }
409:
410: /*
411: * GetTimeLocal - get the local Mac OS time (in seconds since 1/1/1904)
412: *
413: * called by the Catalog Manager when creating/updating records
414: */
415: UInt32 GetTimeLocal(Boolean forHFS)
416: {
417: UInt32 localTime;
418:
419: localTime = UTCToLocal(GetTimeUTC());
420:
421: if (forHFS && gTimeZone.tz_dsttime)
422: localTime += 3600;
423:
424: return localTime;
425: }
426:
427: /*
428: * LocalToUTC - convert from Mac OS local time to Mac OS GMT time
429: */
430: UInt32 LocalToUTC(UInt32 localTime)
431: {
432: UInt32 gtime = localTime;
433:
434: if (gtime != 0) {
435: gtime += (gTimeZone.tz_minuteswest * 60);
436: /*
437: * We no longer do DST adjustments here since we don't
438: * know if time supplied needs adjustment!
439: *
440: * if (gTimeZone.tz_dsttime)
441: * gtime -= 3600;
442: */
443: }
444: return (gtime);
445: }
446:
447: /*
448: * UTCToLocal - convert from Mac OS GMT time to Mac OS local time
449: */
450: UInt32 UTCToLocal(UInt32 utcTime)
451: {
452: UInt32 ltime = utcTime;
453:
454: if (ltime != 0) {
455: ltime -= (gTimeZone.tz_minuteswest * 60);
456: /*
457: * We no longer do DST adjustments here since we don't
458: * know if time supplied needs adjustment!
459: *
460: * if (gTimeZone.tz_dsttime)
461: * ltime += 3600;
462: */
463: }
464: return (ltime);
465: }
466:
467: /*
468: * to_bsd_time - convert from Mac OS time (seconds since 1/1/1904)
469: * to BSD time (seconds since 1/1/1970)
470: */
471: u_int32_t to_bsd_time(u_int32_t hfs_time)
472: {
473: u_int32_t gmt = hfs_time;
474:
475: if (gmt > MAC_GMT_FACTOR)
476: gmt -= MAC_GMT_FACTOR;
477: else
478: gmt = 0; /* don't let date go negative! */
479:
480: return gmt;
481: }
482:
483: /*
484: * to_hfs_time - convert from BSD time (seconds since 1/1/1970)
485: * to Mac OS time (seconds since 1/1/1904)
486: */
487: u_int32_t to_hfs_time(u_int32_t bsd_time)
488: {
489: u_int32_t hfs_time = bsd_time;
490:
491: /* don't adjust zero - treat as uninitialzed */
492: if (hfs_time != 0)
493: hfs_time += MAC_GMT_FACTOR;
494:
495: return (hfs_time);
496: }
497:
498:
499: void BlockMoveData (const void *srcPtr, void *destPtr, Size byteCount)
500: {
501: bcopy(srcPtr, destPtr, byteCount);
502: }
503:
504:
505: Ptr NewPtrSysClear (Size byteCount)
506: {
507: Ptr tmptr;
508: MALLOC (tmptr, Ptr, byteCount, M_TEMP, M_WAITOK);
509: if (tmptr)
510: bzero(tmptr, byteCount);
511: return tmptr;
512: }
513:
514:
515: void DisposePtr (Ptr p)
516: {
517: FREE (p, M_TEMP);
518: }
519:
520:
521: void DebugStr (ConstStr255Param debuggerMsg)
522: {
523: kprintf ("*** Mac OS Debugging Message: %s\n", &debuggerMsg[1]);
524: DEBUG_BREAK;
525: }
526:
527: OSErr MemError (void)
528: {
529: return 0;
530: }
531:
532:
533: void ClearMemory( void* start, UInt32 length )
534: {
535: bzero(start, (size_t)length);
536: }
537:
538:
539: /*
540: * RequireFileLock
541: *
542: * Check to see if a vnode is locked in the current context
543: * This is to be used for debugging purposes only!!
544: */
545: #if HFS_DIAGNOSTIC
546: void RequireFileLock(FileReference vp, int shareable)
547: {
548: struct lock__bsd__ *lkp;
549: int locked = false;
550: pid_t pid;
551: void * self;
552:
553: pid = current_proc()->p_pid;
554: self = (void *) current_thread();
555: lkp = &VTOH(vp)->h_lock;
556:
557: simple_lock(&lkp->lk_interlock);
558:
559: if (shareable && (lkp->lk_sharecount > 0) && (lkp->lk_lockholder == LK_NOPROC))
560: locked = true;
561: else if ((lkp->lk_exclusivecount > 0) && (lkp->lk_lockholder == pid) && (lkp->lk_lockthread == self))
562: locked = true;
563:
564: simple_unlock(&lkp->lk_interlock);
565:
566: if (!locked) {
567: DBG_VFS((" # context... self=0x%0X, pid=0x%0X, proc=0x%0X\n", (int)self, pid, (int)current_proc()));
568: DBG_VFS((" # lock state... thread=0x%0X, holder=0x%0X, ex=%d, sh=%d\n", (int)lkp->lk_lockthread, lkp->lk_lockholder, lkp->lk_exclusivecount, lkp->lk_sharecount));
569:
570: switch (H_FILEID(VTOH(vp))) {
571: case 3:
572: DEBUG_BREAK_MSG((" #\n # RequireFileLock: extent btree vnode not locked! v: 0x%08X\n #\n", (u_int)vp));
573: break;
574:
575: case 4:
576: DEBUG_BREAK_MSG((" #\n # RequireFileLock: catalog btree vnode not locked! v: 0x%08X\n #\n", (u_int)vp));
577: break;
578:
579: default:
580: DEBUG_BREAK_MSG((" #\n # RequireFileLock: file (%d) not locked! v: 0x%08X\n #\n", H_FILEID(VTOH(vp)), (u_int)vp));
581: break;
582: }
583: }
584: }
585: #endif
586:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.