int FillPkgDataFromPackage(PkgData *Data, char *filename) { int i = 0, j = 0, end = 0; i = end = strlen(filename); /* Get build and extension */ for (;filename[i] != '-' && i>0;i--) ; if (i == 0) return 1; i++; /* While we are not on a ., it is part of the build */ for (j=i;filename[j]!='.' && j<end; j++) ; if (j == end || j == i) return 1; strncpy(Data->build, filename+i, j-i); /* From the . to the end we are in the extension */ strncpy(Data->extension, filename+j+1, end-j); /* Now, save the arch */ i -= 2; end = i; for (;filename[i]!= '-' && i>0;i--); if (i==0 || i == end) return 1; j = i-1; i++; strncpy(Data->arch, filename+i, end-i+1); /* Now, save the version */ i -= 2; end = i; for (;filename[i]!= '-' && i>0;i--); if (i==0) return 1; j = i-1; i++; strncpy(Data->version, filename+i, end-i+1); /* Now save the name */ if (j == 0) return 1; strncpy(Data->name, filename, j+1); /* The link */ sprintf(Data->link, "%s/%s", link_pkgs, filename); /* Get the hash */ if (GiveMeHash(filename, Data->crc)) { fprintf(stderr, "Error aquiring crc32 from file [%s]\n", filename); return 1; } return 0; }
/** * This function downloads a package from the internet looking for its mirrors calling the SearchLinkForPackage * @param name A package name * @param out Since this function may get called by InstallPkg, the full path to the package downloaded will be saved here. If null is given, this will not change. * @return If no error ocurr, 0 is returned. If the package doesn't exists in any mirror, 1 is returned. In case of error, -1 (And an error message is issued) */ int DownloadPkg(char *name, char *out) { ListOfLinks Links; char filename[PATH_MAX], pkgcrc[32]; int i = 0, fd = 0; char *MIRROR = NULL; /* Initialize everything up */ memset(&Links, 0, sizeof(ListOfLinks)); /* Search for the package's links */ /* If there is no, 1 is returned, so we leave here */ if ((MIRROR = getenv("MIRROR"))) { if (SearchLinkForPackage(name, &Links, MIRROR)) return 1; } else if (SearchLinkForPackage(name, &Links, NULL)) return 1; if (Links.index > 1) i = GetLinkFromInput(&Links); sprintf(filename, "%s/%s#%s#%s#%s.%s", PACKAGES_DIRECTORY, Links.name[i], Links.version[i], Links.arch[i], Links.build[i], Links.extension[i]); /* If the output already exist and the CRC is ok, then great, we already have it, so there's no need to download it again */ if ((fd = open(filename, O_RDONLY)) >= 0) { close(fd); if (GiveMeHash(filename, pkgcrc) == -1) { freeLinks(&Links); return -1; } if (strcmp(pkgcrc, Links.crcs[i])) fprintf(stderr, "CRC error, Downloading the package again...\n"); else { /* Great, it's already installed, so we leave */ if (out) strcpy(out, filename); freeLinks(&Links); return 0; } } /* Download the link */ if (Download(Links.links[i], filename) == -1) { freeLinks(&Links); return -1; } if (out) strcpy(out, filename); /* Get the link hash */ if (GiveMeHash(filename, pkgcrc) == -1) { freeLinks(&Links); return -1; } /* Does the link hash match with the one given in the database? */ if (strcmp(pkgcrc, Links.crcs[i])) { freeLinks(&Links); fprintf(stderr, "CRC error, try to download your package again\n"); return -1; } /* Great, we're cool, so we leave */ freeLinks(&Links); return 0; }
/** * This function installs a package by calling ExtractPackage to extract it and InsertPkgDB to insert the package in PACKAGES and FILESPKG tables * @param name A package name * @return If no error ocurr, 0 is returned. If the package is already installed, 1 is returned (And a message is issued). In case of error, -1 (And an error message is issued) */ int InstallPkg(char *package) { char *ptr_name = NULL, *init_path = NULL, *input = NULL; char pkgfullpathname[PATH_MAX]; char PackageOrig[PATH_MAX]; int fd = 0; PkgData Data; /* Save locations and initialize the package structure */ strncpy(PackageOrig, package, PATH_MAX); PackageOrig[strlen(package)>PATH_MAX?PATH_MAX:strlen(package)] = '\0'; init_path = getcwd(malloc(PATH_MAX), PATH_MAX); memset(&Data, '\0', sizeof(PkgData)); /* Does it fisically exist? */ if ((fd = open(package, O_RDONLY)) < 0) { /* Ok, the package doesn't exists, let's go for a mirror */ if (DownloadPkg(package, pkgfullpathname) != 0) { free(init_path); return -1; } } else { close(fd); /* Get the full pathname instead of its relative name */ if (GetFileFullPath(package, pkgfullpathname)) { fprintf(stderr, "Failed to install %s\n", package); return -1; } } ptr_name = basename(pkgfullpathname); /* Switch to HOME_ROOT */ if (chdir(HOME_ROOT)) { fprintf(stderr, "Can't go to %s (%s)\n", HOME_ROOT, strerror(errno)); free(init_path); return -1; } /* Fill the package structure according to the package name */ if (FillPkgDataFromPackage(&Data, ptr_name)) { fprintf(stdout, "Wrong package name format. It should be \"" PACKAGE_NAME_FORMAT "\"\n"); chdir(init_path); return -1; } /* Open the database */ if (sqlite3_open(dbname, &Database)) { fprintf(stderr, "Failed to open database %s (%s)\n", dbname, sqlite3_errmsg(Database)); chdir(init_path); free(init_path); return -1; } /* Check if it is already installed */ if (ExistsPkg(&Data)) { fprintf(stderr, "Package %s already installed\n", PackageOrig); chdir(init_path); free(init_path); return 1; } /* Get the package hash so we can register it in the database */ if (GiveMeHash(pkgfullpathname, Data.crc) == -1) { chdir(init_path); free(init_path); return -1; } /* Extract the package itself */ if (ExtractPackage(pkgfullpathname, &Data) == -1) { chdir(init_path); free(init_path); return -1; } PostInstall(); /* Register the package in the database */ InsertPkgDB(&Data); /* Clean everything up */ sqlite3_close(Database); chdir(init_path); if (!noreadme) { printf("Press intro to continue"); getline(&input, (size_t *)&fd, stdin); free(input); } fprintf(stdout, "Package %s installed\n", PackageOrig); return 0; }