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 secdebug ("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 secdebug ("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 secdebug ("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 secdebug ("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 secdebug ("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 secdebug ("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";
609 bool ManifestFileItem::HasResourceFork (char* pathToFile
, std::string
&result
, struct stat
&st
)
611 // try to get the stat on the file. If it works, the file exists
612 result
= ResourceFileName (pathToFile
);
613 if (result
.length () != 0)
615 int stresult
= lstat (result
.c_str (), &st
);
618 return st
.st_size
!= 0;
627 ManifestFileItem::ManifestFileItem () : mNumForks (1)
633 ManifestFileItem::~ManifestFileItem ()
635 secdebug ("manifest", "Destroyed manifest item %p for path %s", this, mPath
.c_str ());
640 ManifestItemType
ManifestFileItem::GetItemType ()
642 return kManifestFileItemType
;
647 u_int32_t
ManifestFileItem::GetNumberOfForks ()
654 void ManifestFileItem::SetNumberOfForks (u_int32_t numForks
)
656 mNumForks
= numForks
;
661 bool ManifestFileItem::FileIsMachOBinary (char* path
)
668 void ManifestFileItem::SetForkLength (int which
, size_t length
)
670 mFileLengths
[which
] = length
;
675 size_t ManifestFileItem::GetForkLength (int which
)
677 return mFileLengths
[which
];
682 void ManifestFileItem::ComputeRepresentations (struct stat
&st
, bool hasAppleDoubleResourceFork
)
684 // digest the data fork
686 ComputeDigestForFile ((char*) mPath
.c_str (), mDigest
[0], mFileLengths
[0], st
);
689 std::string resourceForkName
;
690 if (hasAppleDoubleResourceFork
)
694 resourceForkName
= mPath
;
695 // walk back to find the beginning of the path and insert ._
696 int i
= (int)resourceForkName
.length () - 1;
697 while (i
>= 0 && resourceForkName
[i
] != '/')
704 resourceForkName
.insert (i
, "._");
706 ComputeDigestForAppleDoubleResourceFork ((char*) resourceForkName
.c_str(), mDigest
[1], mFileLengths
[1]);
708 else if (HasResourceFork ((char*) mPath
.c_str (), resourceForkName
, stat2
))
711 ComputeDigestForFile ((char*) resourceForkName
.c_str (), mDigest
[1], mFileLengths
[1], stat2
);
717 static const int kReadChunkSize
= 4096 * 4;
721 static u_int32_t
ExtractUInt32 (u_int8_t
*&finger
)
723 u_int32_t result
= 0;
725 for (i
= 0; i
< 4; ++i
)
727 result
= (result
<< 8) | *finger
++;
735 void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name
, SHA1Digest
&digest
, size_t &fileLength
)
737 secdebug ("manifest", "Creating digest for AppleDouble resource fork %s", name
);
739 CC_SHA1_CTX digestContext
;
740 CC_SHA1_Init (&digestContext
);
742 // bring the file into memory
743 int fileNo
= open (name
, O_RDONLY
, 0);
746 UnixError::throwMe ();
749 // figure out how big the file is.
751 int result
= fstat (fileNo
, &st
);
754 UnixError::throwMe ();
757 u_int8_t
*buffer
= new u_int8_t
[st
.st_size
];
758 ssize_t bytesRead
= read (fileNo
, buffer
, (size_t)st
.st_size
);
761 if (bytesRead
!= st
.st_size
)
764 UnixError::throwMe ();
767 // walk the entry table to find the offset to our resource fork
768 u_int8_t
*bufPtr
= buffer
+ 24; // size of the header + filler
770 // compute the number of entries in the file
771 int numEntries
= (((int) bufPtr
[0]) << 8) | (int) (bufPtr
[1]);
778 for (i
= 0; i
< numEntries
; ++i
)
780 // bufPtr points to an entry descriptor. Four bytes for the ID, four for the offset, four for the length
781 ssize_t id
= ExtractUInt32 (bufPtr
);
782 offset
= ExtractUInt32 (bufPtr
);
783 length
= ExtractUInt32 (bufPtr
);
785 if (id
== 2) // is it the resource fork?
791 if (i
>= numEntries
) // did we run off the end? This had better not happen
793 MacOSError::throwMe (errSecManifestNotSupported
);
799 CC_SHA1_Update (&digestContext
, buffer
+ offset
, (CC_LONG
)length
);
801 // compute the SHA1 hash
802 CC_SHA1_Final (digest
, &digestContext
);
809 void ManifestFileItem::ComputeDigestForFile (char* name
, SHA1Digest
&digest
, size_t &fileLength
, struct stat
&st
)
811 secdebug ("manifest", "Creating digest for %s", name
);
813 // create a context for the digest operation
814 CC_SHA1_CTX digestContext
;
815 CC_SHA1_Init (&digestContext
);
818 int fileNo
= open (name
, O_RDONLY
, 0);
821 UnixError::throwMe ();
824 fileLength
= (size_t)st
.st_size
;
829 char buffer
[kReadChunkSize
];
832 while ((bytesRead
= read (fileNo
, buffer
, kReadChunkSize
)) != 0)
834 // digest the read data
835 CC_SHA1_Update (&digestContext
, buffer
, (CC_LONG
)bytesRead
);
838 // compute the SHA1 hash
839 CC_SHA1_Final (digest
, &digestContext
);
847 void ManifestFileItem::GetItemRepresentation (int whichFork
, void* &itemRep
, size_t &size
)
849 itemRep
= (void*) &mDigest
[whichFork
];
850 size
= kSHA1DigestSize
;
855 void ManifestFileItem::SetItemRepresentation (int whichFork
, const void* itemRep
, size_t size
)
857 memcpy ((void*) &mDigest
[whichFork
], itemRep
, size
);
862 void ManifestFileItem::Compare (ManifestItem
*manifestItem
, bool compareOwnerAndGroup
)
864 FileSystemEntryItem::Compare (manifestItem
, compareOwnerAndGroup
);
866 ManifestFileItem
* item
= static_cast< ManifestFileItem
*>(manifestItem
);
868 secdebug ("manifest", "Comparing file item %s against %s", GetName (), item
->GetName ());
870 // the number of forks should be equal
871 if (mNumForks
!= item
->mNumForks
)
873 MacOSError::throwMe (errSecManifestNotEqual
);
876 // compare file lengths
878 for (i
= 0; i
< mNumForks
; ++i
)
880 if (mFileLengths
[i
] != item
->mFileLengths
[i
])
882 MacOSError::throwMe (errSecManifestNotEqual
);
885 if (memcmp (&mDigest
[i
], item
->mDigest
[i
], kSHA1DigestSize
) != 0)
887 MacOSError::throwMe (errSecManifestNotEqual
);
894 //========================== MANIFEST DIRECTORY ITEM ==========================
898 ManifestDirectoryItem::ManifestDirectoryItem ()
904 ManifestDirectoryItem::~ManifestDirectoryItem ()
906 secdebug ("manifest", "Destroyed directory item %p for path %s", this, mPath
.c_str ());
910 const char* kAppleDoublePrefix
= "._";
911 const int kAppleDoublePrefixLength
= 2;
913 static int CompareFilenames (const FTSENT
** a
, const FTSENT
** b
)
915 // ._name is always greater than name
916 // otherwise, ._ is ignored for sorting purposes
917 const char* aa
= (*a
)->fts_name
;
918 const char* bb
= (*b
)->fts_name
;
919 bool aHasPrefix
= false;
921 if (strncmp (aa
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
924 aa
+= kAppleDoublePrefixLength
;
927 if (strncmp (bb
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
929 bb
+= kAppleDoublePrefixLength
;
932 int compare
= strcmp (aa
, bb
);
934 if (compare
== 0 && aHasPrefix
)
944 const u_int8_t kAppleDoubleMagicNumber
[] = {0x00, 0x05, 0x16, 0x07};
948 static bool PathIsAppleDoubleFile (const char* path
)
950 // Open the file and check the "magic number".
951 int fRef
= open (path
, O_RDONLY
, 0);
955 // read the first four bytes of the file
956 ssize_t bytesRead
= read(fRef
, buffer
, 4);
961 UnixError::throwMe (err
);
966 if (bytesRead
!= 4) // did we get enough bytes?
971 // what we got had better be the proper magic number for this file type
973 for (i
= 0; i
< 4; ++i
)
975 if (buffer
[i
] != kAppleDoubleMagicNumber
[i
])
986 void ManifestDirectoryItem::SetPath (char* path
, StringSet
&exceptions
, bool isRoot
)
995 FileSystemEntryItem::SetPath (path
);
998 secdebug ("manifest", "Added directory entry for %s with name %s", mPath
.c_str (), mName
.c_str ());
1000 // enumerate the contents of the directory.
1001 char* path_argv
[] = { path
, NULL
};
1002 FTS
* thisDir
= fts_open (path_argv
, FTS_PHYSICAL
| FTS_NOCHDIR
| FTS_NOSTAT
| FTS_XDEV
, CompareFilenames
);
1003 if (thisDir
== NULL
) // huh? The file disappeared or isn't a directory any more
1005 UnixError::throwMe ();
1008 (void)fts_read(thisDir
);
1009 FTSENT
* dirEnt
= fts_children (thisDir
, FTS_NAMEONLY
);
1011 while (dirEnt
!= NULL
)
1013 // get the next entry
1014 FTSENT
* dirEntNext
= dirEnt
->fts_link
;
1015 bool hasAppleDoubleResourceFork
= false;
1017 // see if it is an AppleDouble resource fork for this file
1019 strncmp (dirEntNext
->fts_name
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0 &&
1020 strcmp (dirEnt
->fts_name
, dirEntNext
->fts_name
+ kAppleDoublePrefixLength
) == 0)
1022 if (PathIsAppleDoubleFile ((mPath
+ "/" + dirEntNext
->fts_name
).c_str ()))
1024 hasAppleDoubleResourceFork
= true;
1025 dirEntNext
= dirEntNext
->fts_link
;
1029 // figure out what this is pointing to.
1030 std::string fileName
= mPath
+ "/" + dirEnt
->fts_name
;
1032 mDirectoryItems
.AddFileSystemObject ((char*) fileName
.c_str(), exceptions
, false, hasAppleDoubleResourceFork
);
1034 dirEnt
= dirEntNext
;
1042 ManifestItemType
ManifestDirectoryItem::GetItemType ()
1044 return kManifestDirectoryItemType
;
1049 void ManifestDirectoryItem::Compare (ManifestItem
* a
, bool compareOwnerAndGroup
)
1051 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1052 ManifestDirectoryItem
* aa
= static_cast<ManifestDirectoryItem
*>(a
);
1053 secdebug ("manifest", "Comparing directory item %s against %s", GetName (), aa
->GetName ());
1054 mDirectoryItems
.Compare (aa
->mDirectoryItems
, compareOwnerAndGroup
);
1059 //========================== MANIFEST SYMLINK ITEM ==========================
1063 ManifestSymLinkItem::ManifestSymLinkItem ()
1069 ManifestSymLinkItem::~ManifestSymLinkItem ()
1071 secdebug ("manifest", "Destroyed symlink item for %s", mPath
.c_str ());
1076 void ManifestSymLinkItem::ComputeRepresentation ()
1078 char path
[FILENAME_MAX
];
1079 int result
= (int)readlink (mPath
.c_str (), path
, sizeof (path
));
1080 secdebug ("manifest", "Read content %s for %s", path
, mPath
.c_str ());
1082 // create a digest context
1083 CC_SHA1_CTX digestContext
;
1084 CC_SHA1_Init (&digestContext
);
1087 CC_SHA1_Update (&digestContext
, path
, result
);
1089 // compute the result
1090 CC_SHA1_Final (mDigest
, &digestContext
);
1092 UnixError::check (result
);
1097 const SHA1Digest
* ManifestSymLinkItem::GetDigest ()
1104 void ManifestSymLinkItem::SetDigest (const SHA1Digest
* digest
)
1106 memcpy (mDigest
, digest
, sizeof (SHA1Digest
));
1111 ManifestItemType
ManifestSymLinkItem::GetItemType ()
1113 return kManifestSymLinkItemType
;
1118 void ManifestSymLinkItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1120 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1121 ManifestSymLinkItem
* aa
= static_cast<ManifestSymLinkItem
*>(a
);
1122 secdebug ("manifest", "Comparing symlink item %s against %s", GetName (), aa
->GetName ());
1124 // now compare the data
1125 if (memcmp (&mDigest
, &aa
->mDigest
, kSHA1DigestSize
) != 0)
1127 MacOSError::throwMe (errSecManifestNotEqual
);
1133 //========================== MANIFEST OTHER ITEM ==========================
1137 ManifestOtherItem::ManifestOtherItem ()
1143 ManifestOtherItem::~ManifestOtherItem ()
1145 secdebug ("manifest", "Destroyed other item for path %s", mPath
.c_str ());
1150 ManifestItemType
ManifestOtherItem::GetItemType ()
1152 return kManifestOtherType
;
1157 void ManifestOtherItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1159 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1160 secdebug ("manifest", "Comparing other item %s against %s", GetName (), static_cast<FileSystemEntryItem
*>(a
)->GetName ());