1 #include "SharedMemoryServer.h"
5 #include <machine/byte_order.h>
8 #include <security_utilities/crc.h>
9 #include <security_utilities/casts.h>
12 static const char* kPrefix
= "/private/var/db/mds/messages/se_";
14 SharedMemoryServer::SharedMemoryServer (const char* segmentName
, SegmentOffsetType segmentSize
) :
15 mSegmentName (segmentName
), mSegmentSize (segmentSize
)
18 mFileName
+= segmentName
;
20 // make the mds directory, just in case it doesn't exist
21 mkdir("/var/db/mds", 1777);
22 mkdir("/var/db/mds/messages", 0755);
25 // clean any old file away
26 unlink (mFileName
.c_str ());
29 mBackingFile
= open (mFileName
.c_str (), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
35 // set the segment size
36 ftruncate (mBackingFile
, segmentSize
);
39 mSegment
= (u_int8_t
*) mmap (NULL
, mSegmentSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, mBackingFile
, 0);
41 if (mSegment
== (u_int8_t
*) -1) // can't map the memory?
44 unlink (mFileName
.c_str());
47 mDataPtr
= mDataArea
= mSegment
+ sizeof(SegmentOffsetType
);
48 mDataMax
= mSegment
+ segmentSize
;;
50 SetProducerOffset (0);
55 SharedMemoryServer::~SharedMemoryServer ()
64 munmap (mSegment
, mSegmentSize
);
68 // mark the segment for deletion
69 unlink (mFileName
.c_str ());
74 const SegmentOffsetType
76 kCRCOffset
= kSegmentLength
+ sizeof(SegmentOffsetType
),
77 kDomainOffset
= kCRCOffset
+ sizeof(SegmentOffsetType
),
78 kEventTypeOffset
= kDomainOffset
+ sizeof(SegmentOffsetType
),
79 kHeaderLength
= kEventTypeOffset
+ sizeof(SegmentOffsetType
) - kCRCOffset
;
81 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain
, SegmentOffsetType event
, const void *message
, SegmentOffsetType messageLength
)
83 // backing file MUST be right size
84 ftruncate (mBackingFile
, mSegmentSize
);
86 // assemble the final message
87 ssize_t messageSize
= kHeaderLength
+ messageLength
;
88 u_int8_t finalMessage
[messageSize
];
89 SegmentOffsetType
*fm
= (SegmentOffsetType
*) finalMessage
;
90 fm
[0] = OSSwapHostToBigInt32(domain
);
91 fm
[1] = OSSwapHostToBigInt32(event
);
92 memcpy(&fm
[2], message
, messageLength
);
94 SegmentOffsetType crc
= CalculateCRC(finalMessage
, messageSize
);
97 WriteOffset(int_cast
<size_t, SegmentOffsetType
>(messageSize
));
103 WriteData (finalMessage
, int_cast
<size_t, SegmentOffsetType
>(messageSize
));
105 // write the data count
106 SetProducerOffset(int_cast
<size_t, SegmentOffsetType
>(mDataPtr
- mDataArea
));
111 const char* SharedMemoryServer::GetSegmentName ()
113 return mSegmentName
.c_str ();
118 size_t SharedMemoryServer::GetSegmentSize ()
124 void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount
)
126 *((SegmentOffsetType
*) mSegment
) = OSSwapHostToBigInt32 (producerCount
);
131 void SharedMemoryServer::WriteOffset(SegmentOffsetType offset
)
134 *((u_int32_t
*) buffer
) = OSSwapHostToBigInt32(offset
);
135 WriteData(buffer
, 4);
140 void SharedMemoryServer::WriteData(const void* data
, SegmentOffsetType length
)
142 // figure out where in the buffer we actually need to write the data
143 // figure out how many bytes we can write without overflowing the buffer
144 const u_int8_t
* dp
= (const u_int8_t
*) data
;
145 SegmentOffsetType bytesToEnd
= int_cast
<ptrdiff_t, SegmentOffsetType
>(mDataMax
- mDataPtr
);
147 // figure out how many bytes we can write
148 SegmentOffsetType bytesToWrite
= (length
<= bytesToEnd
) ? length
: bytesToEnd
;
150 // move the first part of the data, making sure to skip the producer pointer
151 memcpy (mDataPtr
, dp
, bytesToWrite
);
152 mDataPtr
+= bytesToWrite
;
155 // deduct the bytes just written
156 length
-= bytesToWrite
;
158 if (length
!= 0) // did we wrap around?
160 mDataPtr
= mDataArea
;
161 memcpy (mDataPtr
, dp
, length
);