aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/mac_updater/mac_updater.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/mac_updater/mac_updater.cpp')
-rw-r--r--linden/indra/mac_updater/mac_updater.cpp194
1 files changed, 143 insertions, 51 deletions
diff --git a/linden/indra/mac_updater/mac_updater.cpp b/linden/indra/mac_updater/mac_updater.cpp
index 58819a2..a30f024 100644
--- a/linden/indra/mac_updater/mac_updater.cpp
+++ b/linden/indra/mac_updater/mac_updater.cpp
@@ -537,8 +537,7 @@ bool isDirWritable(FSRef &dir)
537 537
538static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src) 538static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src)
539{ 539{
540 LLWString wstr = utf8str_to_wstring(src); 540 llutf16string utf16str = utf8str_to_utf16str(src);
541 llutf16string utf16str = wstring_to_utf16str(wstr);
542 541
543 dest->length = utf16str.size(); 542 dest->length = utf16str.size();
544 if(dest->length > 255) 543 if(dest->length > 255)
@@ -550,6 +549,13 @@ static void utf8str_to_HFSUniStr255(HFSUniStr255 *dest, const char* src)
550 memcpy(dest->unicode, utf16str.data(), sizeof(UniChar)* dest->length); /* Flawfinder: ignore */ 549 memcpy(dest->unicode, utf16str.data(), sizeof(UniChar)* dest->length); /* Flawfinder: ignore */
551} 550}
552 551
552static std::string HFSUniStr255_to_utf8str(const HFSUniStr255* src)
553{
554 llutf16string string16((U16*)&(src->unicode), src->length);
555 std::string result = utf16str_to_utf8str(string16);
556 return result;
557}
558
553int restoreObject(const char* aside, const char* target, const char* path, const char* object) 559int restoreObject(const char* aside, const char* target, const char* path, const char* object)
554{ 560{
555 char source[PATH_MAX]; /* Flawfinder: ignore */ 561 char source[PATH_MAX]; /* Flawfinder: ignore */
@@ -598,6 +604,123 @@ void filterFile(const char* filename)
598 system(temp); /* Flawfinder: ignore */ 604 system(temp); /* Flawfinder: ignore */
599} 605}
600 606
607static bool isFSRefViewerBundle(FSRef *targetRef)
608{
609 bool result = false;
610 CFURLRef targetURL = NULL;
611 CFBundleRef targetBundle = NULL;
612 CFStringRef targetBundleID = NULL;
613
614 targetURL = CFURLCreateFromFSRef(NULL, targetRef);
615
616 if(targetURL == NULL)
617 {
618 llinfos << "Error creating target URL." << llendl;
619 }
620 else
621 {
622 targetBundle = CFBundleCreate(NULL, targetURL);
623 }
624
625 if(targetBundle == NULL)
626 {
627 llinfos << "Failed to create target bundle." << llendl;
628 }
629 else
630 {
631 targetBundleID = CFBundleGetIdentifier(targetBundle);
632 }
633
634 if(targetBundleID == NULL)
635 {
636 llinfos << "Couldn't retrieve target bundle ID." << llendl;
637 }
638 else
639 {
640 if(CFStringCompare(targetBundleID, CFSTR("com.secondlife.indra.viewer"), 0) == kCFCompareEqualTo)
641 {
642 // This is the bundle we're looking for.
643 result = true;
644 }
645 else
646 {
647 llinfos << "Target bundle ID mismatch." << llendl;
648 }
649 }
650
651 // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released.
652 if(targetURL != NULL)
653 CFRelease(targetURL);
654 if(targetBundle != NULL)
655 CFRelease(targetBundle);
656
657 return result;
658}
659
660// Search through the directory specified by 'parent' for an item that appears to be a Second Life viewer.
661static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app)
662{
663 FSIterator iterator;
664 bool found = false;
665
666 OSErr err = FSOpenIterator( parent, kFSIterateFlat, &iterator );
667 if(!err)
668 {
669 do
670 {
671 ItemCount actualObjects = 0;
672 Boolean containerChanged = false;
673 FSCatalogInfo info;
674 FSRef ref;
675 HFSUniStr255 unicodeName;
676 err = FSGetCatalogInfoBulk(
677 iterator,
678 1,
679 &actualObjects,
680 &containerChanged,
681 kFSCatInfoNodeFlags,
682 &info,
683 &ref,
684 NULL,
685 &unicodeName );
686
687 if(actualObjects == 0)
688 break;
689
690 if(!err)
691 {
692 // Call succeeded and not done with the iteration.
693 std::string name = HFSUniStr255_to_utf8str(&unicodeName);
694
695 llinfos << "Considering \"" << name << "\"" << llendl;
696
697 if(info.nodeFlags & kFSNodeIsDirectoryMask)
698 {
699 // This is a directory. See if it's a .app
700 if(name.find(".app") != std::string::npos)
701 {
702 // Looks promising. Check to see if it has the right bundle identifier.
703 if(isFSRefViewerBundle(&ref))
704 {
705 // This is the one. Return it.
706 *app = ref;
707 found = true;
708 }
709 }
710 }
711 }
712 }
713 while(!err && !found);
714
715 FSCloseIterator(iterator);
716 }
717
718 if(!err && !found)
719 err = fnfErr;
720
721 return err;
722}
723
601void *updatethreadproc(void*) 724void *updatethreadproc(void*)
602{ 725{
603 char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ 726 char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */
@@ -670,57 +793,15 @@ void *updatethreadproc(void*)
670 // Sanity check: make sure the target is a bundle with the right identifier 793 // Sanity check: make sure the target is a bundle with the right identifier
671 if(err == noErr) 794 if(err == noErr)
672 { 795 {
673 CFURLRef targetURL = NULL;
674 CFBundleRef targetBundle = NULL;
675 CFStringRef targetBundleID = NULL;
676
677 // Assume the worst... 796 // Assume the worst...
678 err = -1; 797 err = -1;
679
680 targetURL = CFURLCreateFromFSRef(NULL, &targetRef);
681 798
682 if(targetURL == NULL) 799 if(isFSRefViewerBundle(&targetRef))
683 {
684 llinfos << "Error creating target URL." << llendl;
685 }
686 else
687 { 800 {
688 targetBundle = CFBundleCreate(NULL, targetURL); 801 // This is the bundle we're looking for.
689 } 802 err = noErr;
690 803 replacingTarget = true;
691 if(targetBundle == NULL)
692 {
693 llinfos << "Failed to create target bundle." << llendl;
694 }
695 else
696 {
697 targetBundleID = CFBundleGetIdentifier(targetBundle);
698 }
699
700 if(targetBundleID == NULL)
701 {
702 llinfos << "Couldn't retrieve target bundle ID." << llendl;
703 }
704 else
705 {
706 if(CFStringCompare(targetBundleID, CFSTR("com.secondlife.indra.viewer"), 0) == kCFCompareEqualTo)
707 {
708 // This is the bundle we're looking for.
709 err = noErr;
710 replacingTarget = true;
711 }
712 else
713 {
714 llinfos << "Target bundle ID mismatch." << llendl;
715 }
716 } 804 }
717
718 // Don't release targetBundleID -- since we don't retain it, it's released when targetBundle is released.
719 if(targetURL != NULL)
720 CFRelease(targetURL);
721 if(targetBundle != NULL)
722 CFRelease(targetBundle);
723
724 } 805 }
725 806
726 // Make sure the target's parent directory is writable. 807 // Make sure the target's parent directory is writable.
@@ -943,13 +1024,24 @@ void *updatethreadproc(void*)
943 1024
944 // Get an FSRef to the new application on the disk image 1025 // Get an FSRef to the new application on the disk image
945 FSRef sourceRef; 1026 FSRef sourceRef;
946 snprintf(temp, sizeof(temp), "%s/mnt/Second Life.app", tempDir); 1027 FSRef mountRef;
1028 snprintf(temp, sizeof(temp), "%s/mnt", tempDir);
947 1029
948 llinfos << "Source application is: " << temp << llendl; 1030 llinfos << "Disk image mount point is: " << temp << llendl;
949 1031
950 err = FSPathMakeRef((UInt8 *)temp, &sourceRef, NULL); 1032 err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL);
951 if(err != noErr) 1033 if(err != noErr)
1034 {
1035 llinfos << "Couldn't make FSRef to disk image mount point." << llendl;
952 throw 0; 1036 throw 0;
1037 }
1038
1039 err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
1040 if(err != noErr)
1041 {
1042 llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
1043 throw 0;
1044 }
953 1045
954 FSRef asideRef; 1046 FSRef asideRef;
955 char aside[MAX_PATH]; /* Flawfinder: ignore */ 1047 char aside[MAX_PATH]; /* Flawfinder: ignore */