]> git.saurik.com Git - cydia.git/blobdiff - postinst.mm
Do not stash /usr/lib/pam (just wishful thinking).
[cydia.git] / postinst.mm
index b11a9aca80268cfeab222bf2abe32ad28283ce8c..11d70dc953237925130beed95e0af6ba9d7b6ba7 100644 (file)
+#include <dirent.h>
 #include <strings.h>
+
 #include <Sources.h>
 
-#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <Menes/ObjectHandle.h>
+
+void Finish(const char *finish) {
+    if (finish == NULL)
+        return;
+
+    const char *cydia(getenv("CYDIA"));
+    if (cydia == NULL)
+        return;
+
+    int fd([[[[NSString stringWithUTF8String:cydia] componentsSeparatedByString:@" "] objectAtIndex:0] intValue]);
+
+    FILE *fout(fdopen(fd, "w"));
+    fprintf(fout, "finish:%s\n", finish);
+    fclose(fout);
+}
+
+static bool setnsfpn(const char *path) {
+    return system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn %s", path] UTF8String]) == 0;
+}
+
+static bool MoveStash() {
+    struct stat stat;
+
+    if (lstat("/var/stash", &stat) == -1)
+        return errno == ENOENT;
+    else if (S_ISLNK(stat.st_mode))
+        return true;
+    else if (!S_ISDIR(stat.st_mode))
+        return false;
+
+    if (lstat("/var/db/stash", &stat) == -1) {
+        if (errno == ENOENT)
+            goto move;
+        else return false;
+    } else if (S_ISLNK(stat.st_mode))
+        // XXX: this is fixable
+        return false;
+    else if (!S_ISDIR(stat.st_mode))
+        return false;
+    else {
+        if (!setnsfpn("/var/db/stash"))
+            return false;
+        if (system("mv -t /var/stash /var/db/stash/*") != 0)
+            return false;
+        if (rmdir("/var/db/stash") == -1)
+            return false;
+    } move:
+
+    if (!setnsfpn("/var/stash"))
+        return false;
+
+    if (rename("/var/stash", "/var/db/stash") == -1)
+        return false;
+    if (symlink("/var/db/stash", "/var/stash") != -1)
+        return true;
+    if (rename("/var/db/stash", "/var/stash") != -1)
+        return false;
+
+    fprintf(stderr, "/var/stash misplaced -- DO NOT REBOOT\n");
+    return false;
+}
+
+static bool FixProtections() {
+    const char *path("/var/lib");
+    mkdir(path, 0755);
+    if (!setnsfpn(path)) {
+        fprintf(stderr, "failed to setnsfpn %s\n", path);
+        return false;
+    }
+
+    return true;
+}
+
+static void FixPermissions() {
+    DIR *stash(opendir("/var/stash"));
+    if (stash == NULL)
+        return;
+
+    while (dirent *entry = readdir(stash)) {
+        const char *folder(entry->d_name);
+        if (strlen(folder) != 8)
+            continue;
+        if (strncmp(folder, "_.", 2) != 0)
+            continue;
+
+        char path[1024];
+        sprintf(path, "/var/stash/%s", folder);
+
+        struct stat stat;
+        if (lstat(path, &stat) == -1)
+            continue;
+        if (!S_ISDIR(stat.st_mode))
+            continue;
+
+        chmod(path, 0755);
+    }
+
+    closedir(stash);
+}
 
-#include <CydiaSubstrate/CydiaSubstrate.h>
-#include "CyteKit/PerlCompatibleRegEx.hpp"
+#define APPLICATIONS "/Applications"
+static bool FixApplications() {
+    char target[1024];
+    ssize_t length(readlink(APPLICATIONS, target, sizeof(target)));
+    if (length == -1)
+        return false;
+
+    if (length >= sizeof(target)) // >= "just in case" (I'm nervous)
+        return false;
+    target[length] = '\0';
+
+    if (strlen(target) != 30)
+        return false;
+    if (memcmp(target, "/var/stash/Applications.", 24) != 0)
+        return false;
+    if (strchr(target + 24, '/') != NULL)
+        return false;
+
+    struct stat stat;
+    if (lstat(target, &stat) == -1)
+        return false;
+    if (!S_ISDIR(stat.st_mode))
+        return false;
+
+    char temp[] = "/var/stash/_.XXXXXX";
+    if (mkdtemp(temp) == NULL)
+        return false;
+
+    if (false) undo: {
+        unlink(temp);
+        return false;
+    }
+
+    if (chmod(temp, 0755) == -1)
+        goto undo;
+
+    char destiny[strlen(temp) + 32];
+    sprintf(destiny, "%s%s", temp, APPLICATIONS);
+
+    if (unlink(APPLICATIONS) == -1)
+        goto undo;
+
+    if (rename(target, destiny) == -1) {
+        if (symlink(target, APPLICATIONS) == -1)
+            fprintf(stderr, "/Applications damaged -- DO NOT REBOOT\n");
+        goto undo;
+    } else {
+        bool success;
+        if (symlink(destiny, APPLICATIONS) != -1)
+            success = true;
+        else {
+            fprintf(stderr, "/var/stash/Applications damaged -- DO NOT REBOOT\n");
+            success = false;
+        }
+
+        // unneccessary, but feels better (I'm nervous)
+        symlink(destiny, target);
+
+        [@APPLICATIONS writeToFile:[NSString stringWithFormat:@"%s.lnk", temp] atomically:YES encoding:NSNonLossyASCIIStringEncoding error:NULL];
+        return success;
+    }
+}
 
 _H<NSMutableDictionary> Sources_;
-_H<NSString> CydiaSource_;
 bool Changed_;
 
 _H<NSString> System_;
@@ -19,6 +182,19 @@ int main(int argc, const char *argv[]) {
 
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
+    bool restart(false);
+
+    if (kCFCoreFoundationVersionNumber >= 1000) {
+        if (!FixProtections())
+            return 1;
+        if (MoveStash())
+            restart = true;
+        else {
+            fprintf(stderr, "failed to move stash\n");
+            return 1;
+        }
+    }
+
     size_t size;
     sysctlbyname("kern.osversion", NULL, &size, NULL, 0);
     char *osversion = new char[size];
@@ -30,15 +206,11 @@ int main(int argc, const char *argv[]) {
 
     if (metadata != nil) {
         Sources_ = [metadata objectForKey:@"Sources"];
-        CydiaSource_ = [metadata objectForKey:@"CydiaSource"];
 
         if (NSNumber *number = [metadata objectForKey:@"Version"])
             version = [number unsignedIntValue];
     }
 
-    if (CydiaSource_ == nil)
-        CydiaSource_ = @"apt.saurik.com";
-
     if (Sources_ == nil)
         Sources_ = [NSMutableDictionary dictionaryWithCapacity:8];
 
@@ -51,6 +223,40 @@ int main(int argc, const char *argv[]) {
 
     CydiaWriteSources();
 
+    #define OldCache_ "/var/root/Library/Caches/com.saurik.Cydia"
+    if (access(OldCache_, F_OK) == 0)
+        system("rm -rf " OldCache_);
+
+    #define NewCache_ "/var/mobile/Library/Caches/com.saurik.Cydia"
+    system("cd /; su -c 'mkdir -p " NewCache_ "' mobile");
+
+    if (access(NewCache_ "/lists", F_OK) != 0 && errno == ENOENT) {
+        system("cp -at " NewCache_ " /var/lib/apt/lists");
+        system("chown -R 501.501 " NewCache_ "/lists");
+    }
+
+    #define OldLibrary_ "/var/lib/cydia"
+
+    #define NewLibrary_ "/var/mobile/Library/Cydia"
+    system("cd /; su -c 'mkdir -p " NewLibrary_ "' mobile");
+
+    #define Cytore_ "/metadata.cb0"
+
+    if (access(NewLibrary_ Cytore_, F_OK) != 0 && errno == ENOENT) {
+        if (access(NewCache_ Cytore_, F_OK) == 0)
+            system("mv -f " NewCache_ Cytore_ " " NewLibrary_);
+        else if (access(OldLibrary_ Cytore_, F_OK) == 0)
+            system("mv -f " OldLibrary_ Cytore_ " " NewLibrary_);
+        chown(NewLibrary_ Cytore_, 501, 501);
+    }
+
+    FixPermissions();
+
+    restart |= FixApplications();
+
+    if (restart)
+        Finish("restart");
+
     [pool release];
     return 0;
 }