2 * Copyright (c) 2004-2006,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
29 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/mount.h>
35 #include <security_utilities/cfutilities.h>
38 #include <CommonCrypto/CommonDigest.h>
42 ModuleNexus
<CSSMInitializer
> CSSMInitializer::mInstance
;
44 CSSMInitializer::CSSMInitializer () : mModule (gGuidAppleCSP
), mCSP (mModule
)
50 CSSMInitializer::~CSSMInitializer ()
56 CssmClient::CSP
* CSSMInitializer::GetCSP ()
58 return &mInstance().mCSP
;
63 //========================== MANIFEST ITEM LIST ==========================
67 ManifestItemList::ManifestItemList ()
73 ManifestItemList::~ManifestItemList ()
75 // throw away all of the items in the list
76 iterator it
= begin ();
85 // return the path portion of a URL after checking to see if we support its scheme
86 void ManifestItemList::DecodeURL (CFURLRef url
, char *pathBuffer
, CFIndex maxBufLen
)
88 // get the scheme from the url and check to make sure it is a "file" scheme
89 CFRef
<CFStringRef
> scheme (CFURLCopyScheme (url
));
90 if (CFStringCompare (scheme
, CFSTR("file"), 0) != 0)
92 // we only support file URL's
93 MacOSError::throwMe (errSecManifestNotSupported
);
96 // convert the url into a "real" path name
97 if (!CFURLGetFileSystemRepresentation (url
, false, (UInt8
*) pathBuffer
, maxBufLen
))
99 MacOSError::throwMe (errSecManifestNotEqual
);
105 void ManifestItemList::AddFileSystemObject (char* path
, StringSet
& exceptions
, bool isRoot
, bool hasAppleDoubleResourceFork
)
107 // see if our path is in the exception list. If it is, do nothing else
108 StringSet::iterator it
= exceptions
.find (path
);
109 if (it
!= exceptions
.end ())
111 secinfo ("manifest", "Did not add %s to the manifest.", path
);
115 // now that we have the path, do a stat and see what we have
116 struct stat nodeStat
;
117 int result
= lstat (path
, &nodeStat
);
118 UnixError::check (result
);
120 FileSystemEntryItem
* mItem
;
122 bool includeUserAndGroup
= true;
124 switch (nodeStat
.st_mode
& S_IFMT
)
126 case S_IFDIR
: // are we a directory?
128 ManifestDirectoryItem
* dirItem
= new ManifestDirectoryItem ();
129 dirItem
->SetPath (path
, exceptions
, isRoot
);
136 ManifestFileItem
* fileItem
= new ManifestFileItem ();
137 fileItem
->SetPath (path
);
138 fileItem
->ComputeRepresentations (nodeStat
, hasAppleDoubleResourceFork
);
145 ManifestSymLinkItem
* symItem
= new ManifestSymLinkItem ();
146 symItem
->SetPath (path
);
147 symItem
->ComputeRepresentation ();
149 nodeStat
.st_mode
= S_IFLNK
;
150 includeUserAndGroup
= false;
156 ManifestOtherItem
* otherItem
= new ManifestOtherItem ();
157 otherItem
->SetPath (path
);
163 if (includeUserAndGroup
) // should we set the info?
165 mItem
->SetUID (nodeStat
.st_uid
);
166 mItem
->SetGID (nodeStat
.st_gid
);
169 mItem
->SetMode (nodeStat
.st_mode
);
176 void ManifestItemList::AddDataObject (CFDataRef object
)
178 // reconstruct the pointer
180 CC_SHA1_CTX digestContext
;
182 CC_SHA1_Init (&digestContext
);
184 const UInt8
* data
= CFDataGetBytePtr (object
);
185 CFIndex length
= CFDataGetLength (object
);
187 CC_SHA1_Update (&digestContext
, data
, (CC_LONG
)length
);
188 CC_SHA1_Final (digest
, &digestContext
);
190 ManifestDataBlobItem
* db
= new ManifestDataBlobItem ();
192 db
->SetDigest (&digest
);
193 db
->SetLength (length
);
200 void ManifestItemList::ConvertToStringSet (const char* path
, CFArrayRef exceptionList
, StringSet
&exceptions
)
202 if (exceptionList
!= NULL
)
204 std::string prefix
= path
;
206 // put us in canonical form
207 if (prefix
[prefix
.length () - 1] != '/')
212 // enumerate the list
213 CFIndex max
= CFArrayGetCount (exceptionList
);
216 for (n
= 0; n
< max
; ++n
)
218 CFTypeRef dataRef
= CFArrayGetValueAtIndex (exceptionList
, n
);
219 if (CFGetTypeID (dataRef
) != CFStringGetTypeID ())
221 MacOSError::throwMe (errSecManifestInvalidException
);
224 // always prepend the prefix -- the spec says that all items in the exception list are relative to the root
225 std::string s
= prefix
+ cfString (CFStringRef (dataRef
));
226 secinfo ("manifest", "Uncanonicalized path is %s", s
.c_str ());
228 // canonicalize the path and insert if successful.
229 char realPath
[PATH_MAX
];
230 if (realpath (s
.c_str (), realPath
) != NULL
)
232 secinfo ("manifest", "Inserted path %s as an exception", realPath
);
233 exceptions
.insert (realPath
);
241 void ManifestItemList::AddObject (CFTypeRef object
, CFArrayRef exceptionList
)
243 // get the type of the object
244 CFTypeID objectID
= CFGetTypeID (object
);
246 if (objectID
== CFDataGetTypeID ())
248 AddDataObject ((CFDataRef
) object
);
250 else if (objectID
== CFURLGetTypeID ())
252 StringSet exceptions
;
254 // get the path from the URL
255 char path
[PATH_MAX
];
256 DecodeURL ((CFURLRef
) object
, path
, sizeof (path
));
259 char realPath
[PATH_MAX
];
260 if (realpath (path
, realPath
) == NULL
)
262 UnixError::throwMe ();
265 ConvertToStringSet (realPath
, exceptionList
, exceptions
);
267 AddFileSystemObject (realPath
, exceptions
, true, false);
271 MacOSError::throwMe (errSecManifestNotEqual
);
277 void RootItemList::Compare (RootItemList
& item
, bool compareOwnerAndGroup
)
279 // the number of items in the list has to be the same
280 unsigned numItems
= (unsigned)size ();
282 if (numItems
!= item
.size ())
284 MacOSError::throwMe (errSecManifestNotEqual
);
287 // for a root item list, items in the manifest MUST have the same creation order
290 for (i
= 0; i
< numItems
; ++i
)
292 ManifestItem
* item1
= (*this)[i
];
293 ManifestItem
* item2
= item
[i
];
295 if (item1
->GetItemType () != item2
->GetItemType ())
297 MacOSError::throwMe (errSecManifestNotEqual
);
300 item1
->Compare (item2
, compareOwnerAndGroup
);
306 class CompareManifestFileItems
309 bool operator () (ManifestItem
*a
, ManifestItem
*b
);
314 bool CompareManifestFileItems::operator () (ManifestItem
*a
, ManifestItem
*b
)
316 FileSystemEntryItem
*aa
= static_cast<FileSystemEntryItem
*>(a
);
317 FileSystemEntryItem
*bb
= static_cast<FileSystemEntryItem
*>(b
);
319 return strcmp (aa
->GetName (), bb
->GetName ()) < 0;
324 void FileSystemItemList::Compare (FileSystemItemList
&a
, bool compareOwnerAndGroup
)
326 unsigned numItems
= (unsigned)size ();
328 if (numItems
!= a
.size ())
330 MacOSError::throwMe (errSecManifestNotEqual
);
333 // sort the two lists
334 sort (begin (), end (), CompareManifestFileItems ());
335 sort (a
.begin (), a
.end (), CompareManifestFileItems ());
337 // compare each item in the list
339 for (i
= 0; i
< numItems
; ++i
)
341 ManifestItem
*thisListPtr
= (*this)[i
];
342 ManifestItem
*aListPtr
= a
[i
];
343 if (thisListPtr
->GetItemType () != aListPtr
->GetItemType ())
345 MacOSError::throwMe (errSecManifestNotEqual
);
347 thisListPtr
->Compare (aListPtr
, compareOwnerAndGroup
);
353 //========================== MANIFEST ==========================
357 ManifestInternal::ManifestInternal ()
363 ManifestInternal::~ManifestInternal ()
365 secinfo ("manifest", "Destroyed manifest internal %p", this);
370 void ManifestInternal::CompareManifests (ManifestInternal
& m1
, ManifestInternal
& m2
, SecManifestCompareOptions options
)
372 if ((options
& ~kSecManifestVerifyOwnerAndGroup
) != 0)
374 MacOSError::throwMe (errSecUnimplemented
); // we don't support these options
377 m1
.mManifestItems
.Compare (m2
.mManifestItems
, (bool) options
& kSecManifestVerifyOwnerAndGroup
);
382 //========================== MANIFEST ITEM ==========================
383 ManifestItem::~ManifestItem ()
389 //========================== DATA BLOB ITEM ==========================
390 ManifestDataBlobItem::ManifestDataBlobItem ()
396 ManifestDataBlobItem::~ManifestDataBlobItem ()
402 ManifestItemType
ManifestDataBlobItem::GetItemType ()
404 return kManifestDataBlobItemType
;
409 const SHA1Digest
* ManifestDataBlobItem::GetDigest ()
416 void ManifestDataBlobItem::SetDigest (const SHA1Digest
*sha1Digest
)
418 memcpy (&mSHA1Digest
, sha1Digest
, sizeof (SHA1Digest
));
423 size_t ManifestDataBlobItem::GetLength ()
430 void ManifestDataBlobItem::SetLength (size_t length
)
437 void ManifestDataBlobItem::Compare (ManifestItem
* item
, bool compareOwnerAndGroup
)
439 ManifestDataBlobItem
* i
= static_cast<ManifestDataBlobItem
*>(item
);
440 if (memcmp (&i
->mSHA1Digest
, &mSHA1Digest
, sizeof (SHA1Digest
)) != 0)
442 MacOSError::throwMe (errSecManifestNotEqual
);
448 //========================== FILE SYSTEM ENTRY ITEM ==========================
452 FileSystemEntryItem::FileSystemEntryItem () : mUserID (0), mGroupID (0), mMode (0)
458 FileSystemEntryItem::~FileSystemEntryItem ()
464 void FileSystemEntryItem::SetName (char* name
)
471 static char* StringTail (char* path
)
473 char* finger
= path
+ strlen (path
) - 1;
474 while (finger
!= path
&& *finger
!= '/')
479 if (finger
!= path
) // did find a separator
489 void FileSystemEntryItem::SetPath (char* path
)
494 // while we are at it, extract that last name of the path name and save it off as the name
495 mName
= StringTail (path
);
496 secinfo ("manifest", "Created file item for %s with name %s", mPath
.c_str (), mName
.c_str ());
501 void FileSystemEntryItem::SetUID (uid_t uid
)
508 void FileSystemEntryItem::SetGID (gid_t gid
)
515 void FileSystemEntryItem::SetMode (mode_t mode
)
522 uid_t
FileSystemEntryItem::GetUID () const
528 gid_t
FileSystemEntryItem::GetGID () const
535 mode_t
FileSystemEntryItem::GetMode () const
542 const char* FileSystemEntryItem::GetName () const
544 return (char*) mName
.c_str ();
549 void FileSystemEntryItem::Compare (ManifestItem
*aa
, bool compareOwnerAndGroup
)
551 FileSystemEntryItem
* a
= static_cast<FileSystemEntryItem
*>(aa
);
553 if (mName
!= a
->mName
|| mMode
!= a
->mMode
)
555 MacOSError::throwMe (errSecManifestNotEqual
);
558 if (compareOwnerAndGroup
)
560 if (mUserID
!= a
->mUserID
|| mGroupID
!= a
->mGroupID
)
562 MacOSError::throwMe (errSecManifestNotEqual
);
569 //========================== MANIFEST FILE ITEM ==========================
573 bool ManifestFileItem::FileSystemHasTrueForks (char* pathToFile
)
575 // return true if volume to which path points supports true forked files
577 int result
= statfs (pathToFile
, &st
);
580 secinfo ("manifest", "Could not get statfs (error was %s)", strerror (errno
));
581 UnixError::throwMe ();
584 return strcmp (st
.f_fstypename
, "afpfs") == 0 || strcmp (st
.f_fstypename
, "hfs") == 0;
589 std::string
ManifestFileItem::ResourceFileName (char* path
)
591 std::string filePath
;
593 if (FileSystemHasTrueForks (path
))
597 return filePath
+ "/rsrc";
607 bool ManifestFileItem::HasResourceFork (char* pathToFile
, std::string
&result
, struct stat
&st
)
609 // try to get the stat on the file. If it works, the file exists
610 result
= ResourceFileName (pathToFile
);
611 if (result
.length () != 0)
613 int stresult
= lstat (result
.c_str (), &st
);
616 return st
.st_size
!= 0;
625 ManifestFileItem::ManifestFileItem () : mNumForks (1)
631 ManifestFileItem::~ManifestFileItem ()
633 secinfo ("manifest", "Destroyed manifest item %p for path %s", this, mPath
.c_str ());
638 ManifestItemType
ManifestFileItem::GetItemType ()
640 return kManifestFileItemType
;
645 u_int32_t
ManifestFileItem::GetNumberOfForks ()
652 void ManifestFileItem::SetNumberOfForks (u_int32_t numForks
)
654 mNumForks
= numForks
;
659 bool ManifestFileItem::FileIsMachOBinary (char* path
)
666 void ManifestFileItem::SetForkLength (int which
, size_t length
)
668 mFileLengths
[which
] = length
;
673 size_t ManifestFileItem::GetForkLength (int which
)
675 return mFileLengths
[which
];
680 void ManifestFileItem::ComputeRepresentations (struct stat
&st
, bool hasAppleDoubleResourceFork
)
682 // digest the data fork
684 ComputeDigestForFile ((char*) mPath
.c_str (), mDigest
[0], mFileLengths
[0], st
);
687 std::string resourceForkName
;
688 if (hasAppleDoubleResourceFork
)
692 resourceForkName
= mPath
;
693 // walk back to find the beginning of the path and insert ._
694 int i
= (int)resourceForkName
.length () - 1;
695 while (i
>= 0 && resourceForkName
[i
] != '/')
702 resourceForkName
.insert (i
, "._");
704 ComputeDigestForAppleDoubleResourceFork ((char*) resourceForkName
.c_str(), mDigest
[1], mFileLengths
[1]);
706 else if (HasResourceFork ((char*) mPath
.c_str (), resourceForkName
, stat2
))
709 ComputeDigestForFile ((char*) resourceForkName
.c_str (), mDigest
[1], mFileLengths
[1], stat2
);
715 static const int kReadChunkSize
= 4096 * 4;
719 static u_int32_t
ExtractUInt32 (u_int8_t
*&finger
)
721 u_int32_t result
= 0;
723 for (i
= 0; i
< 4; ++i
)
725 result
= (result
<< 8) | *finger
++;
733 void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name
, SHA1Digest
&digest
, size_t &fileLength
)
735 secinfo ("manifest", "Creating digest for AppleDouble resource fork %s", name
);
737 CC_SHA1_CTX digestContext
;
738 CC_SHA1_Init (&digestContext
);
740 // bring the file into memory
741 int fileNo
= open (name
, O_RDONLY
, 0);
744 UnixError::throwMe ();
747 // figure out how big the file is.
749 int result
= fstat (fileNo
, &st
);
752 UnixError::throwMe ();
755 u_int8_t
*buffer
= new u_int8_t
[st
.st_size
];
756 ssize_t bytesRead
= read (fileNo
, buffer
, (size_t)st
.st_size
);
759 if (bytesRead
!= st
.st_size
)
762 UnixError::throwMe ();
765 // walk the entry table to find the offset to our resource fork
766 u_int8_t
*bufPtr
= buffer
+ 24; // size of the header + filler
768 // compute the number of entries in the file
769 int numEntries
= (((int) bufPtr
[0]) << 8) | (int) (bufPtr
[1]);
776 for (i
= 0; i
< numEntries
; ++i
)
778 // bufPtr points to an entry descriptor. Four bytes for the ID, four for the offset, four for the length
779 ssize_t id
= ExtractUInt32 (bufPtr
);
780 offset
= ExtractUInt32 (bufPtr
);
781 length
= ExtractUInt32 (bufPtr
);
783 if (id
== 2) // is it the resource fork?
789 if (i
>= numEntries
) // did we run off the end? This had better not happen
791 MacOSError::throwMe (errSecManifestNotSupported
);
797 CC_SHA1_Update (&digestContext
, buffer
+ offset
, (CC_LONG
)length
);
799 // compute the SHA1 hash
800 CC_SHA1_Final (digest
, &digestContext
);
807 void ManifestFileItem::ComputeDigestForFile (char* name
, SHA1Digest
&digest
, size_t &fileLength
, struct stat
&st
)
809 secinfo ("manifest", "Creating digest for %s", name
);
811 // create a context for the digest operation
812 CC_SHA1_CTX digestContext
;
813 CC_SHA1_Init (&digestContext
);
816 int fileNo
= open (name
, O_RDONLY
, 0);
819 UnixError::throwMe ();
822 fileLength
= (size_t)st
.st_size
;
827 char buffer
[kReadChunkSize
];
830 while ((bytesRead
= read (fileNo
, buffer
, kReadChunkSize
)) != 0)
832 // digest the read data
833 CC_SHA1_Update (&digestContext
, buffer
, (CC_LONG
)bytesRead
);
836 // compute the SHA1 hash
837 CC_SHA1_Final (digest
, &digestContext
);
845 void ManifestFileItem::GetItemRepresentation (int whichFork
, void* &itemRep
, size_t &size
)
847 itemRep
= (void*) &mDigest
[whichFork
];
848 size
= kSHA1DigestSize
;
853 void ManifestFileItem::SetItemRepresentation (int whichFork
, const void* itemRep
, size_t size
)
855 memcpy ((void*) &mDigest
[whichFork
], itemRep
, size
);
860 void ManifestFileItem::Compare (ManifestItem
*manifestItem
, bool compareOwnerAndGroup
)
862 FileSystemEntryItem::Compare (manifestItem
, compareOwnerAndGroup
);
864 ManifestFileItem
* item
= static_cast< ManifestFileItem
*>(manifestItem
);
866 secinfo ("manifest", "Comparing file item %s against %s", GetName (), item
->GetName ());
868 // the number of forks should be equal
869 if (mNumForks
!= item
->mNumForks
)
871 MacOSError::throwMe (errSecManifestNotEqual
);
874 // compare file lengths
876 for (i
= 0; i
< mNumForks
; ++i
)
878 if (mFileLengths
[i
] != item
->mFileLengths
[i
])
880 MacOSError::throwMe (errSecManifestNotEqual
);
883 if (memcmp (&mDigest
[i
], item
->mDigest
[i
], kSHA1DigestSize
) != 0)
885 MacOSError::throwMe (errSecManifestNotEqual
);
892 //========================== MANIFEST DIRECTORY ITEM ==========================
896 ManifestDirectoryItem::ManifestDirectoryItem ()
902 ManifestDirectoryItem::~ManifestDirectoryItem ()
904 secinfo ("manifest", "Destroyed directory item %p for path %s", this, mPath
.c_str ());
908 const char* kAppleDoublePrefix
= "._";
909 const int kAppleDoublePrefixLength
= 2;
911 static int CompareFilenames (const FTSENT
** a
, const FTSENT
** b
)
913 // ._name is always greater than name
914 // otherwise, ._ is ignored for sorting purposes
915 const char* aa
= (*a
)->fts_name
;
916 const char* bb
= (*b
)->fts_name
;
917 bool aHasPrefix
= false;
919 if (strncmp (aa
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
922 aa
+= kAppleDoublePrefixLength
;
925 if (strncmp (bb
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
927 bb
+= kAppleDoublePrefixLength
;
930 int compare
= strcmp (aa
, bb
);
932 if (compare
== 0 && aHasPrefix
)
942 const u_int8_t kAppleDoubleMagicNumber
[] = {0x00, 0x05, 0x16, 0x07};
946 static bool PathIsAppleDoubleFile (const char* path
)
948 // Open the file and check the "magic number".
949 int fRef
= open (path
, O_RDONLY
, 0);
953 // read the first four bytes of the file
954 ssize_t bytesRead
= read(fRef
, buffer
, 4);
959 UnixError::throwMe (err
);
964 if (bytesRead
!= 4) // did we get enough bytes?
969 // what we got had better be the proper magic number for this file type
971 for (i
= 0; i
< 4; ++i
)
973 if (buffer
[i
] != kAppleDoubleMagicNumber
[i
])
984 void ManifestDirectoryItem::SetPath (char* path
, StringSet
&exceptions
, bool isRoot
)
993 FileSystemEntryItem::SetPath (path
);
996 secinfo ("manifest", "Added directory entry for %s with name %s", mPath
.c_str (), mName
.c_str ());
998 // enumerate the contents of the directory.
999 char* path_argv
[] = { path
, NULL
};
1000 FTS
* thisDir
= fts_open (path_argv
, FTS_PHYSICAL
| FTS_NOCHDIR
| FTS_NOSTAT
| FTS_XDEV
, CompareFilenames
);
1001 if (thisDir
== NULL
) // huh? The file disappeared or isn't a directory any more
1003 UnixError::throwMe ();
1006 (void)fts_read(thisDir
);
1007 FTSENT
* dirEnt
= fts_children (thisDir
, FTS_NAMEONLY
);
1009 while (dirEnt
!= NULL
)
1011 // get the next entry
1012 FTSENT
* dirEntNext
= dirEnt
->fts_link
;
1013 bool hasAppleDoubleResourceFork
= false;
1015 // see if it is an AppleDouble resource fork for this file
1017 strncmp (dirEntNext
->fts_name
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0 &&
1018 strcmp (dirEnt
->fts_name
, dirEntNext
->fts_name
+ kAppleDoublePrefixLength
) == 0)
1020 if (PathIsAppleDoubleFile ((mPath
+ "/" + dirEntNext
->fts_name
).c_str ()))
1022 hasAppleDoubleResourceFork
= true;
1023 dirEntNext
= dirEntNext
->fts_link
;
1027 // figure out what this is pointing to.
1028 std::string fileName
= mPath
+ "/" + dirEnt
->fts_name
;
1030 mDirectoryItems
.AddFileSystemObject ((char*) fileName
.c_str(), exceptions
, false, hasAppleDoubleResourceFork
);
1032 dirEnt
= dirEntNext
;
1040 ManifestItemType
ManifestDirectoryItem::GetItemType ()
1042 return kManifestDirectoryItemType
;
1047 void ManifestDirectoryItem::Compare (ManifestItem
* a
, bool compareOwnerAndGroup
)
1049 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1050 ManifestDirectoryItem
* aa
= static_cast<ManifestDirectoryItem
*>(a
);
1051 secinfo ("manifest", "Comparing directory item %s against %s", GetName (), aa
->GetName ());
1052 mDirectoryItems
.Compare (aa
->mDirectoryItems
, compareOwnerAndGroup
);
1057 //========================== MANIFEST SYMLINK ITEM ==========================
1061 ManifestSymLinkItem::ManifestSymLinkItem ()
1067 ManifestSymLinkItem::~ManifestSymLinkItem ()
1069 secinfo ("manifest", "Destroyed symlink item for %s", mPath
.c_str ());
1074 void ManifestSymLinkItem::ComputeRepresentation ()
1076 char path
[FILENAME_MAX
];
1077 int result
= (int)readlink (mPath
.c_str (), path
, sizeof (path
));
1078 secinfo ("manifest", "Read content %s for %s", path
, mPath
.c_str ());
1080 // create a digest context
1081 CC_SHA1_CTX digestContext
;
1082 CC_SHA1_Init (&digestContext
);
1085 CC_SHA1_Update (&digestContext
, path
, result
);
1087 // compute the result
1088 CC_SHA1_Final (mDigest
, &digestContext
);
1090 UnixError::check (result
);
1095 const SHA1Digest
* ManifestSymLinkItem::GetDigest ()
1102 void ManifestSymLinkItem::SetDigest (const SHA1Digest
* digest
)
1104 memcpy (mDigest
, digest
, sizeof (SHA1Digest
));
1109 ManifestItemType
ManifestSymLinkItem::GetItemType ()
1111 return kManifestSymLinkItemType
;
1116 void ManifestSymLinkItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1118 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1119 ManifestSymLinkItem
* aa
= static_cast<ManifestSymLinkItem
*>(a
);
1120 secinfo ("manifest", "Comparing symlink item %s against %s", GetName (), aa
->GetName ());
1122 // now compare the data
1123 if (memcmp (&mDigest
, &aa
->mDigest
, kSHA1DigestSize
) != 0)
1125 MacOSError::throwMe (errSecManifestNotEqual
);
1131 //========================== MANIFEST OTHER ITEM ==========================
1135 ManifestOtherItem::ManifestOtherItem ()
1141 ManifestOtherItem::~ManifestOtherItem ()
1143 secinfo ("manifest", "Destroyed other item for path %s", mPath
.c_str ());
1148 ManifestItemType
ManifestOtherItem::GetItemType ()
1150 return kManifestOtherType
;
1155 void ManifestOtherItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1157 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1158 secinfo ("manifest", "Comparing other item %s against %s", GetName (), static_cast<FileSystemEntryItem
*>(a
)->GetName ());