2 * Copyright (c) 2004-2006 Apple Computer, 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 <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
39 #include <CommonCrypto/CommonDigest.h>
43 ModuleNexus
<CSSMInitializer
> CSSMInitializer::mInstance
;
45 CSSMInitializer::CSSMInitializer () : mModule (gGuidAppleCSP
), mCSP (mModule
)
51 CSSMInitializer::~CSSMInitializer ()
57 CssmClient::CSP
* CSSMInitializer::GetCSP ()
59 return &mInstance().mCSP
;
64 //========================== MANIFEST ITEM LIST ==========================
68 ManifestItemList::ManifestItemList ()
74 ManifestItemList::~ManifestItemList ()
76 // throw away all of the items in the list
77 iterator it
= begin ();
86 // return the path portion of a URL after checking to see if we support its scheme
87 void ManifestItemList::DecodeURL (CFURLRef url
, char *pathBuffer
, CFIndex maxBufLen
)
89 // get the scheme from the url and check to make sure it is a "file" scheme
90 CFRef
<CFStringRef
> scheme (CFURLCopyScheme (url
));
91 if (CFStringCompare (scheme
, CFSTR("file"), 0) != 0)
93 // we only support file URL's
94 MacOSError::throwMe (errSecManifestNotSupported
);
97 // convert the url into a "real" path name
98 if (!CFURLGetFileSystemRepresentation (url
, false, (UInt8
*) pathBuffer
, maxBufLen
))
100 MacOSError::throwMe (errSecManifestNotEqual
);
106 void ManifestItemList::AddFileSystemObject (char* path
, StringSet
& exceptions
, bool isRoot
, bool hasAppleDoubleResourceFork
)
108 // see if our path is in the exception list. If it is, do nothing else
109 StringSet::iterator it
= exceptions
.find (path
);
110 if (it
!= exceptions
.end ())
112 secdebug ("manifest", "Did not add %s to the manifest.", path
);
116 // now that we have the path, do a stat and see what we have
117 struct stat nodeStat
;
118 int result
= lstat (path
, &nodeStat
);
119 UnixError::check (result
);
121 FileSystemEntryItem
* mItem
;
123 bool includeUserAndGroup
= true;
125 switch (nodeStat
.st_mode
& S_IFMT
)
127 case S_IFDIR
: // are we a directory?
129 ManifestDirectoryItem
* dirItem
= new ManifestDirectoryItem ();
130 dirItem
->SetPath (path
, exceptions
, isRoot
);
137 ManifestFileItem
* fileItem
= new ManifestFileItem ();
138 fileItem
->SetPath (path
);
139 fileItem
->ComputeRepresentations (nodeStat
, hasAppleDoubleResourceFork
);
146 ManifestSymLinkItem
* symItem
= new ManifestSymLinkItem ();
147 symItem
->SetPath (path
);
148 symItem
->ComputeRepresentation ();
150 nodeStat
.st_mode
= S_IFLNK
;
151 includeUserAndGroup
= false;
157 ManifestOtherItem
* otherItem
= new ManifestOtherItem ();
158 otherItem
->SetPath (path
);
164 if (includeUserAndGroup
) // should we set the info?
166 mItem
->SetUID (nodeStat
.st_uid
);
167 mItem
->SetGID (nodeStat
.st_gid
);
170 mItem
->SetMode (nodeStat
.st_mode
);
177 void ManifestItemList::AddDataObject (CFDataRef object
)
179 // reconstruct the pointer
181 CC_SHA1_CTX digestContext
;
183 CC_SHA1_Init (&digestContext
);
185 const UInt8
* data
= CFDataGetBytePtr (object
);
186 CFIndex length
= CFDataGetLength (object
);
188 CC_SHA1_Update (&digestContext
, data
, length
);
189 CC_SHA1_Final (digest
, &digestContext
);
191 ManifestDataBlobItem
* db
= new ManifestDataBlobItem ();
193 db
->SetDigest (&digest
);
194 db
->SetLength (length
);
201 void ManifestItemList::ConvertToStringSet (const char* path
, CFArrayRef exceptionList
, StringSet
&exceptions
)
203 if (exceptionList
!= NULL
)
205 std::string prefix
= path
;
207 // put us in canonical form
208 if (prefix
[prefix
.length () - 1] != '/')
213 // enumerate the list
214 CFIndex max
= CFArrayGetCount (exceptionList
);
217 for (n
= 0; n
< max
; ++n
)
219 CFTypeRef dataRef
= CFArrayGetValueAtIndex (exceptionList
, n
);
220 if (CFGetTypeID (dataRef
) != CFStringGetTypeID ())
222 MacOSError::throwMe (errSecManifestInvalidException
);
225 // always prepend the prefix -- the spec says that all items in the exception list are relative to the root
226 std::string s
= prefix
+ cfString (CFStringRef (dataRef
));
227 secdebug ("manifest", "Uncanonicalized path is %s", s
.c_str ());
229 // canonicalize the path and insert if successful.
230 char realPath
[PATH_MAX
];
231 if (realpath (s
.c_str (), realPath
) != NULL
)
233 secdebug ("manifest", "Inserted path %s as an exception", realPath
);
234 exceptions
.insert (realPath
);
242 void ManifestItemList::AddObject (CFTypeRef object
, CFArrayRef exceptionList
)
244 // get the type of the object
245 CFTypeID objectID
= CFGetTypeID (object
);
247 if (objectID
== CFDataGetTypeID ())
249 AddDataObject ((CFDataRef
) object
);
251 else if (objectID
== CFURLGetTypeID ())
253 StringSet exceptions
;
255 // get the path from the URL
256 char path
[PATH_MAX
];
257 DecodeURL ((CFURLRef
) object
, path
, sizeof (path
));
260 char realPath
[PATH_MAX
];
261 if (realpath (path
, realPath
) == NULL
)
263 UnixError::throwMe ();
266 ConvertToStringSet (realPath
, exceptionList
, exceptions
);
268 AddFileSystemObject (realPath
, exceptions
, true, false);
272 MacOSError::throwMe (errSecManifestNotEqual
);
278 void RootItemList::Compare (RootItemList
& item
, bool compareOwnerAndGroup
)
280 // the number of items in the list has to be the same
281 unsigned numItems
= size ();
283 if (numItems
!= item
.size ())
285 MacOSError::throwMe (errSecManifestNotEqual
);
288 // for a root item list, items in the manifest MUST have the same creation order
291 for (i
= 0; i
< numItems
; ++i
)
293 ManifestItem
* item1
= (*this)[i
];
294 ManifestItem
* item2
= item
[i
];
296 if (item1
->GetItemType () != item2
->GetItemType ())
298 MacOSError::throwMe (errSecManifestNotEqual
);
301 item1
->Compare (item2
, compareOwnerAndGroup
);
307 class CompareManifestFileItems
310 bool operator () (ManifestItem
*a
, ManifestItem
*b
);
315 bool CompareManifestFileItems::operator () (ManifestItem
*a
, ManifestItem
*b
)
317 FileSystemEntryItem
*aa
= static_cast<FileSystemEntryItem
*>(a
);
318 FileSystemEntryItem
*bb
= static_cast<FileSystemEntryItem
*>(b
);
320 return strcmp (aa
->GetName (), bb
->GetName ()) < 0;
325 void FileSystemItemList::Compare (FileSystemItemList
&a
, bool compareOwnerAndGroup
)
327 unsigned numItems
= size ();
329 if (numItems
!= a
.size ())
331 MacOSError::throwMe (errSecManifestNotEqual
);
334 // sort the two lists
335 sort (begin (), end (), CompareManifestFileItems ());
336 sort (a
.begin (), a
.end (), CompareManifestFileItems ());
338 // compare each item in the list
340 for (i
= 0; i
< numItems
; ++i
)
342 ManifestItem
*thisListPtr
= (*this)[i
];
343 ManifestItem
*aListPtr
= a
[i
];
344 if (thisListPtr
->GetItemType () != aListPtr
->GetItemType ())
346 MacOSError::throwMe (errSecManifestNotEqual
);
348 thisListPtr
->Compare (aListPtr
, compareOwnerAndGroup
);
354 //========================== MANIFEST ==========================
358 ManifestInternal::ManifestInternal ()
364 ManifestInternal::~ManifestInternal ()
366 secdebug ("manifest", "Destroyed manifest internal %p", this);
371 void ManifestInternal::CompareManifests (ManifestInternal
& m1
, ManifestInternal
& m2
, SecManifestCompareOptions options
)
373 if ((options
& ~kSecManifestVerifyOwnerAndGroup
) != 0)
375 MacOSError::throwMe (unimpErr
); // we don't support these options
378 m1
.mManifestItems
.Compare (m2
.mManifestItems
, (bool) options
& kSecManifestVerifyOwnerAndGroup
);
383 //========================== MANIFEST ITEM ==========================
384 ManifestItem::~ManifestItem ()
390 //========================== DATA BLOB ITEM ==========================
391 ManifestDataBlobItem::ManifestDataBlobItem ()
397 ManifestDataBlobItem::~ManifestDataBlobItem ()
403 ManifestItemType
ManifestDataBlobItem::GetItemType ()
405 return kManifestDataBlobItemType
;
410 const SHA1Digest
* ManifestDataBlobItem::GetDigest ()
417 void ManifestDataBlobItem::SetDigest (const SHA1Digest
*sha1Digest
)
419 memcpy (&mSHA1Digest
, sha1Digest
, sizeof (SHA1Digest
));
424 size_t ManifestDataBlobItem::GetLength ()
431 void ManifestDataBlobItem::SetLength (size_t length
)
438 void ManifestDataBlobItem::Compare (ManifestItem
* item
, bool compareOwnerAndGroup
)
440 ManifestDataBlobItem
* i
= static_cast<ManifestDataBlobItem
*>(item
);
441 if (memcmp (&i
->mSHA1Digest
, &mSHA1Digest
, sizeof (SHA1Digest
)) != 0)
443 MacOSError::throwMe (errSecManifestNotEqual
);
449 //========================== FILE SYSTEM ENTRY ITEM ==========================
453 FileSystemEntryItem::FileSystemEntryItem () : mUserID (0), mGroupID (0), mMode (0)
459 FileSystemEntryItem::~FileSystemEntryItem ()
465 void FileSystemEntryItem::SetName (char* name
)
472 static char* StringTail (char* path
)
474 char* finger
= path
+ strlen (path
) - 1;
475 while (finger
!= path
&& *finger
!= '/')
480 if (finger
!= path
) // did find a separator
490 void FileSystemEntryItem::SetPath (char* path
)
495 // while we are at it, extract that last name of the path name and save it off as the name
496 mName
= StringTail (path
);
497 secdebug ("manifest", "Created file item for %s with name %s", mPath
.c_str (), mName
.c_str ());
502 void FileSystemEntryItem::SetUID (uid_t uid
)
509 void FileSystemEntryItem::SetGID (gid_t gid
)
516 void FileSystemEntryItem::SetMode (mode_t mode
)
523 uid_t
FileSystemEntryItem::GetUID () const
529 gid_t
FileSystemEntryItem::GetGID () const
536 mode_t
FileSystemEntryItem::GetMode () const
543 const char* FileSystemEntryItem::GetName () const
545 return (char*) mName
.c_str ();
550 void FileSystemEntryItem::Compare (ManifestItem
*aa
, bool compareOwnerAndGroup
)
552 FileSystemEntryItem
* a
= static_cast<FileSystemEntryItem
*>(aa
);
554 if (mName
!= a
->mName
|| mMode
!= a
->mMode
)
556 MacOSError::throwMe (errSecManifestNotEqual
);
559 if (compareOwnerAndGroup
)
561 if (mUserID
!= a
->mUserID
|| mGroupID
!= a
->mGroupID
)
563 MacOSError::throwMe (errSecManifestNotEqual
);
570 //========================== MANIFEST FILE ITEM ==========================
574 bool ManifestFileItem::FileSystemHasTrueForks (char* pathToFile
)
576 // return true if volume to which path points supports true forked files
578 int result
= statfs (pathToFile
, &st
);
581 secdebug ("manifest", "Could not get statfs (error was %s)", strerror (errno
));
582 UnixError::throwMe ();
585 return strcmp (st
.f_fstypename
, "afpfs") == 0 || strcmp (st
.f_fstypename
, "hfs") == 0;
590 std::string
ManifestFileItem::ResourceFileName (char* path
)
592 std::string filePath
;
594 if (FileSystemHasTrueForks (path
))
598 return filePath
+ "/rsrc";
610 bool ManifestFileItem::HasResourceFork (char* pathToFile
, std::string
&result
, struct stat
&st
)
612 // try to get the stat on the file. If it works, the file exists
613 result
= ResourceFileName (pathToFile
);
614 if (result
.length () != 0)
616 int stresult
= lstat (result
.c_str (), &st
);
619 return st
.st_size
!= 0;
628 ManifestFileItem::ManifestFileItem () : mNumForks (1)
634 ManifestFileItem::~ManifestFileItem ()
636 secdebug ("manifest", "Destroyed manifest item %p for path %s", this, mPath
.c_str ());
641 ManifestItemType
ManifestFileItem::GetItemType ()
643 return kManifestFileItemType
;
648 u_int32_t
ManifestFileItem::GetNumberOfForks ()
655 void ManifestFileItem::SetNumberOfForks (u_int32_t numForks
)
657 mNumForks
= numForks
;
662 bool ManifestFileItem::FileIsMachOBinary (char* path
)
669 void ManifestFileItem::SetForkLength (int which
, size_t length
)
671 mFileLengths
[which
] = length
;
676 size_t ManifestFileItem::GetForkLength (int which
)
678 return mFileLengths
[which
];
683 void ManifestFileItem::ComputeRepresentations (struct stat
&st
, bool hasAppleDoubleResourceFork
)
685 // digest the data fork
687 ComputeDigestForFile ((char*) mPath
.c_str (), mDigest
[0], mFileLengths
[0], st
);
690 std::string resourceForkName
;
691 if (hasAppleDoubleResourceFork
)
695 resourceForkName
= mPath
;
696 // walk back to find the beginning of the path and insert ._
697 int i
= resourceForkName
.length () - 1;
698 while (i
>= 0 && resourceForkName
[i
] != '/')
705 resourceForkName
.insert (i
, "._");
707 ComputeDigestForAppleDoubleResourceFork ((char*) resourceForkName
.c_str(), mDigest
[1], mFileLengths
[1]);
709 else if (HasResourceFork ((char*) mPath
.c_str (), resourceForkName
, stat2
))
712 ComputeDigestForFile ((char*) resourceForkName
.c_str (), mDigest
[1], mFileLengths
[1], stat2
);
718 static const int kReadChunkSize
= 4096 * 4;
722 static u_int32_t
ExtractUInt32 (u_int8_t
*&finger
)
724 u_int32_t result
= 0;
726 for (i
= 0; i
< 4; ++i
)
728 result
= (result
<< 8) | *finger
++;
736 void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name
, SHA1Digest
&digest
, size_t &fileLength
)
738 secdebug ("manifest", "Creating digest for AppleDouble resource fork %s", name
);
740 CC_SHA1_CTX digestContext
;
741 CC_SHA1_Init (&digestContext
);
743 // bring the file into memory
744 int fileNo
= open (name
, O_RDONLY
, 0);
747 UnixError::throwMe ();
750 // figure out how big the file is.
752 int result
= fstat (fileNo
, &st
);
755 UnixError::throwMe ();
758 u_int8_t
*buffer
= new u_int8_t
[st
.st_size
];
759 ssize_t bytesRead
= read (fileNo
, buffer
, st
.st_size
);
762 if (bytesRead
!= st
.st_size
)
765 UnixError::throwMe ();
768 // walk the entry table to find the offset to our resource fork
769 u_int8_t
*bufPtr
= buffer
+ 24; // size of the header + filler
771 // compute the number of entries in the file
772 int numEntries
= (((int) bufPtr
[0]) << 8) | (int) (bufPtr
[1]);
779 for (i
= 0; i
< numEntries
; ++i
)
781 // bufPtr points to an entry descriptor. Four bytes for the ID, four for the offset, four for the length
782 ssize_t id
= ExtractUInt32 (bufPtr
);
783 offset
= ExtractUInt32 (bufPtr
);
784 length
= ExtractUInt32 (bufPtr
);
786 if (id
== 2) // is it the resource fork?
792 if (i
>= numEntries
) // did we run off the end? This had better not happen
794 MacOSError::throwMe (errSecManifestNotSupported
);
800 CC_SHA1_Update (&digestContext
, buffer
+ offset
, length
);
802 // compute the SHA1 hash
803 CC_SHA1_Final (digest
, &digestContext
);
810 void ManifestFileItem::ComputeDigestForFile (char* name
, SHA1Digest
&digest
, size_t &fileLength
, struct stat
&st
)
812 secdebug ("manifest", "Creating digest for %s", name
);
814 // create a context for the digest operation
815 CC_SHA1_CTX digestContext
;
816 CC_SHA1_Init (&digestContext
);
819 int fileNo
= open (name
, O_RDONLY
, 0);
822 UnixError::throwMe ();
825 fileLength
= st
.st_size
;
830 char buffer
[kReadChunkSize
];
833 while ((bytesRead
= read (fileNo
, buffer
, kReadChunkSize
)) != 0)
835 // digest the read data
836 CC_SHA1_Update (&digestContext
, buffer
, bytesRead
);
839 // compute the SHA1 hash
840 CC_SHA1_Final (digest
, &digestContext
);
848 void ManifestFileItem::GetItemRepresentation (int whichFork
, void* &itemRep
, size_t &size
)
850 itemRep
= (void*) &mDigest
[whichFork
];
851 size
= kSHA1DigestSize
;
856 void ManifestFileItem::SetItemRepresentation (int whichFork
, const void* itemRep
, size_t size
)
858 memcpy ((void*) &mDigest
[whichFork
], itemRep
, size
);
863 void ManifestFileItem::Compare (ManifestItem
*manifestItem
, bool compareOwnerAndGroup
)
865 FileSystemEntryItem::Compare (manifestItem
, compareOwnerAndGroup
);
867 ManifestFileItem
* item
= static_cast< ManifestFileItem
*>(manifestItem
);
869 secdebug ("manifest", "Comparing file item %s against %s", GetName (), item
->GetName ());
871 // the number of forks should be equal
872 if (mNumForks
!= item
->mNumForks
)
874 MacOSError::throwMe (errSecManifestNotEqual
);
877 // compare file lengths
879 for (i
= 0; i
< mNumForks
; ++i
)
881 if (mFileLengths
[i
] != item
->mFileLengths
[i
])
883 MacOSError::throwMe (errSecManifestNotEqual
);
886 if (memcmp (&mDigest
[i
], item
->mDigest
[i
], kSHA1DigestSize
) != 0)
888 MacOSError::throwMe (errSecManifestNotEqual
);
895 //========================== MANIFEST DIRECTORY ITEM ==========================
899 ManifestDirectoryItem::ManifestDirectoryItem ()
905 ManifestDirectoryItem::~ManifestDirectoryItem ()
907 secdebug ("manifest", "Destroyed directory item %p for path %s", this, mPath
.c_str ());
911 const char* kAppleDoublePrefix
= "._";
912 const int kAppleDoublePrefixLength
= 2;
914 static int CompareFilenames (const FTSENT
** a
, const FTSENT
** b
)
916 // ._name is always greater than name
917 // otherwise, ._ is ignored for sorting purposes
918 const char* aa
= (*a
)->fts_name
;
919 const char* bb
= (*b
)->fts_name
;
920 bool aHasPrefix
= false;
922 if (strncmp (aa
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
925 aa
+= kAppleDoublePrefixLength
;
928 if (strncmp (bb
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0) // do we have an appledouble prefix?
930 bb
+= kAppleDoublePrefixLength
;
933 int compare
= strcmp (aa
, bb
);
935 if (compare
== 0 && aHasPrefix
)
945 const u_int8_t kAppleDoubleMagicNumber
[] = {0x00, 0x05, 0x16, 0x07};
949 static bool PathIsAppleDoubleFile (const char* path
)
951 // Open the file and check the "magic number".
952 int fRef
= open (path
, O_RDONLY
, 0);
956 // read the first four bytes of the file
957 ssize_t bytesRead
= read(fRef
, buffer
, 4);
962 UnixError::throwMe (err
);
967 if (bytesRead
!= 4) // did we get enough bytes?
972 // what we got had better be the proper magic number for this file type
974 for (i
= 0; i
< 4; ++i
)
976 if (buffer
[i
] != kAppleDoubleMagicNumber
[i
])
987 void ManifestDirectoryItem::SetPath (char* path
, StringSet
&exceptions
, bool isRoot
)
996 FileSystemEntryItem::SetPath (path
);
999 secdebug ("manifest", "Added directory entry for %s with name %s", mPath
.c_str (), mName
.c_str ());
1001 // enumerate the contents of the directory.
1002 char* path_argv
[] = { path
, NULL
};
1003 FTS
* thisDir
= fts_open (path_argv
, FTS_PHYSICAL
| FTS_NOCHDIR
| FTS_NOSTAT
| FTS_XDEV
, CompareFilenames
);
1004 if (thisDir
== NULL
) // huh? The file disappeared or isn't a directory any more
1006 UnixError::throwMe ();
1009 (void)fts_read(thisDir
);
1010 FTSENT
* dirEnt
= fts_children (thisDir
, FTS_NAMEONLY
);
1012 while (dirEnt
!= NULL
)
1014 // get the next entry
1015 FTSENT
* dirEntNext
= dirEnt
->fts_link
;
1016 bool hasAppleDoubleResourceFork
= false;
1018 // see if it is an AppleDouble resource fork for this file
1020 strncmp (dirEntNext
->fts_name
, kAppleDoublePrefix
, kAppleDoublePrefixLength
) == 0 &&
1021 strcmp (dirEnt
->fts_name
, dirEntNext
->fts_name
+ kAppleDoublePrefixLength
) == 0)
1023 if (PathIsAppleDoubleFile ((mPath
+ "/" + dirEntNext
->fts_name
).c_str ()))
1025 hasAppleDoubleResourceFork
= true;
1026 dirEntNext
= dirEntNext
->fts_link
;
1030 // figure out what this is pointing to.
1031 std::string fileName
= mPath
+ "/" + dirEnt
->fts_name
;
1033 mDirectoryItems
.AddFileSystemObject ((char*) fileName
.c_str(), exceptions
, false, hasAppleDoubleResourceFork
);
1035 dirEnt
= dirEntNext
;
1043 ManifestItemType
ManifestDirectoryItem::GetItemType ()
1045 return kManifestDirectoryItemType
;
1050 void ManifestDirectoryItem::Compare (ManifestItem
* a
, bool compareOwnerAndGroup
)
1052 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1053 ManifestDirectoryItem
* aa
= static_cast<ManifestDirectoryItem
*>(a
);
1054 secdebug ("manifest", "Comparing directory item %s against %s", GetName (), aa
->GetName ());
1055 mDirectoryItems
.Compare (aa
->mDirectoryItems
, compareOwnerAndGroup
);
1060 //========================== MANIFEST SYMLINK ITEM ==========================
1064 ManifestSymLinkItem::ManifestSymLinkItem ()
1070 ManifestSymLinkItem::~ManifestSymLinkItem ()
1072 secdebug ("manifest", "Destroyed symlink item for %s", mPath
.c_str ());
1077 void ManifestSymLinkItem::ComputeRepresentation ()
1079 char path
[FILENAME_MAX
];
1080 int result
= readlink (mPath
.c_str (), path
, sizeof (path
));
1081 secdebug ("manifest", "Read content %s for %s", path
, mPath
.c_str ());
1083 // create a digest context
1084 CC_SHA1_CTX digestContext
;
1085 CC_SHA1_Init (&digestContext
);
1088 CC_SHA1_Update (&digestContext
, path
, result
);
1090 // compute the result
1091 CC_SHA1_Final (mDigest
, &digestContext
);
1093 UnixError::check (result
);
1098 const SHA1Digest
* ManifestSymLinkItem::GetDigest ()
1105 void ManifestSymLinkItem::SetDigest (const SHA1Digest
* digest
)
1107 memcpy (mDigest
, digest
, sizeof (SHA1Digest
));
1112 ManifestItemType
ManifestSymLinkItem::GetItemType ()
1114 return kManifestSymLinkItemType
;
1119 void ManifestSymLinkItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1121 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1122 ManifestSymLinkItem
* aa
= static_cast<ManifestSymLinkItem
*>(a
);
1123 secdebug ("manifest", "Comparing symlink item %s against %s", GetName (), aa
->GetName ());
1125 // now compare the data
1126 if (memcmp (&mDigest
, &aa
->mDigest
, kSHA1DigestSize
) != 0)
1128 MacOSError::throwMe (errSecManifestNotEqual
);
1134 //========================== MANIFEST OTHER ITEM ==========================
1138 ManifestOtherItem::ManifestOtherItem ()
1144 ManifestOtherItem::~ManifestOtherItem ()
1146 secdebug ("manifest", "Destroyed other item for path %s", mPath
.c_str ());
1151 ManifestItemType
ManifestOtherItem::GetItemType ()
1153 return kManifestOtherType
;
1158 void ManifestOtherItem::Compare (ManifestItem
*a
, bool compareOwnerAndGroup
)
1160 FileSystemEntryItem::Compare (a
, compareOwnerAndGroup
);
1161 secdebug ("manifest", "Comparing other item %s against %s", GetName (), static_cast<FileSystemEntryItem
*>(a
)->GetName ());