PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/actions.c

http://github.com/DimaSmirnov/Archlinux-downgrader
C | 352 lines | 286 code | 41 blank | 25 comment | 81 complexity | d8801a9c29bfbd71ff928b135b8267fa MD5 | raw file
Possible License(s): GPL-3.0
  1. int DowngradePackage( char *package) {
  2. int isincache = IsPackageInLogs(package); // Here also parsing pacman.log and using flag actions.package_never_upgraded
  3. if (isincache) {
  4. if (!silent) { sprintf(tmp_string, "Downgrading from Cache, to version %s\n",install_version); dgr_output(tmp_string); }
  5. system(install_command);
  6. return 0;
  7. }
  8. strcpy(install_version,installed_pkg_ver);
  9. if (WITH_ALA) {
  10. int showpkgs = PrepareView(package);
  11. int i=1;
  12. //sprintf(tmp_string, "%d: %s-%s %s\n", i+1, user_pkgs[i].name, user_pkgs[i].version, user_pkgs[i].repo); dgr_output(tmp_string);
  13. if (!silent) { sprintf(tmp_string, "Downgrade %s from ALA to version %s\n", package,user_pkgs[i].version); dgr_output(tmp_string); }
  14. strcpy(install_command,"sudo pacman -U "); strcat(install_command,user_pkgs[i].link);
  15. //printf("%s\n", install_command); //DEBUG
  16. system(install_command);
  17. return 0;
  18. }
  19. if (WITH_ARM) {
  20. ret = IsPackageInArm(package, install_version);
  21. if (arm_pkgs[ret].link) {
  22. if (!silent) { sprintf(tmp_string, "Downgrade %s from ARM to version %s\n", package,arm_pkgs[ret+2].version); dgr_output(tmp_string); }
  23. strcpy(install_command,"sudo pacman -U "); strcat(install_command,arm_pkgs[ret+2].link);
  24. system(install_command);
  25. return 0;
  26. }
  27. }
  28. return 1;
  29. }
  30. char* GetChoiseForPackage( char *package) {
  31. int showpkgs = PrepareView(package); // Готовим массив со списком пакетов для отображения пользователю
  32. for (int i=0;i<MAX_PKGS_FOR_USER && i<=showpkgs;i++) {
  33. sprintf(tmp_string, "%d: %s-%s %s\n", i+1, user_pkgs[i].name, user_pkgs[i].version, user_pkgs[i].repo);
  34. dgr_output(tmp_string);
  35. //printf("%s\n", user_pkgs[i].link); //DEBUG
  36. }
  37. dgr_output (">> Please enter package number, [q] to quit ");
  38. scanf ("%s",tmp_string);
  39. return tmp_string;
  40. }
  41. int IsPackageAvailable(char *package) {
  42. alpm_siglevel_t siglevel=0;
  43. db = alpm_register_syncdb(alpm_handle, "core", siglevel);
  44. pkg = alpm_db_get_pkg(db,(const char*)package);
  45. const char *pkgr= alpm_pkg_get_url(pkg);
  46. if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg);
  47. //printf ("1. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG
  48. return 0; } else return 1; }
  49. db = alpm_register_syncdb(alpm_handle, "extra", siglevel);
  50. pkg = alpm_db_get_pkg(db,(const char*)package);
  51. pkgr= alpm_pkg_get_url(pkg);
  52. if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg);
  53. //printf ("2. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG
  54. return 0; } else return 1; }
  55. db = alpm_register_syncdb(alpm_handle, "community", siglevel);
  56. pkg = alpm_db_get_pkg(db,(const char*)package);
  57. pkgr= alpm_pkg_get_url(pkg);
  58. if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg);
  59. //printf ("3. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG
  60. return 0; } else return 1; }
  61. db = alpm_register_syncdb(alpm_handle, "multilib", siglevel);
  62. pkg = alpm_db_get_pkg(db,(const char*)package);
  63. pkgr= alpm_pkg_get_url(pkg);
  64. if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg);
  65. //printf ("4. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG
  66. return 0; } else return 1; }
  67. return 2;
  68. // return 0 - pkg available
  69. // return 1 - pkg not installed
  70. // return 2 - wrong pkg name
  71. }
  72. int IsPackageInstalled(char *package) {
  73. db = alpm_get_localdb(alpm_handle);
  74. pkg = alpm_db_get_pkg(db,(const char*)package);
  75. if (alpm_pkg_get_name(pkg)) return 1;
  76. else return 0;
  77. }
  78. int PrepareView(char *package) {
  79. int cntr=0;
  80. counter--;
  81. user_pkgs = realloc(user_pkgs, (pkgsinala+2+pkgsinarm)*sizeof(struct user_packs));
  82. //printf ("installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG
  83. //sprintf(tmp_string, "counter: %d\n",counter); dgr_output(tmp_string); // DEBUG
  84. if (WITH_ALA && pkgsinala) { // Создаем список пакетов для вывода по ALA
  85. while (counter) {
  86. //printf ("::: ala_pkgs[counter].version: %s\n", ala_pkgs[counter].version); //DEBUG
  87. strcpy(user_pkgs[cntr].name,ala_pkgs[counter].name);
  88. strcpy(user_pkgs[cntr].version,ala_pkgs[counter].version);
  89. sprintf(tmp_string,"%s-%s", user_pkgs[cntr].name, user_pkgs[cntr].version);
  90. ret = IsPackageInCache(tmp_string);
  91. //printf ("user_pkgs[cntr].version: %s", user_pkgs[cntr].version); //DEBUG
  92. if (!strcmp(user_pkgs[cntr].version, installed_pkg_ver)) {
  93. strcpy(user_pkgs[cntr].link,ala_pkgs[counter].full_path);
  94. strcpy(user_pkgs[cntr].repo," [installed]");
  95. }
  96. else if (ret==1) {
  97. strcpy(user_pkgs[cntr].link,full_path_to_packet);
  98. strcpy(user_pkgs[cntr].repo," (from cache)");
  99. }
  100. else {
  101. strcpy(user_pkgs[cntr].link,ala_pkgs[counter].full_path);
  102. strcpy(user_pkgs[cntr].repo," (from ALA)");
  103. }
  104. cntr++;
  105. counter--;
  106. }
  107. }
  108. if (WITH_ARM && pkgsinarm) { // Создаем список пакетов для вывода по ARM
  109. while (pkgsinarm) {
  110. strcpy(user_pkgs[cntr].name,arm_pkgs[cntr].name);
  111. strcpy(user_pkgs[cntr].version,arm_pkgs[cntr].version);
  112. sprintf(tmp_string,"%s-%s", user_pkgs[cntr].name, user_pkgs[cntr].version);
  113. ret = IsPackageInCache(tmp_string);
  114. if (!strcmp(user_pkgs[cntr].version, installed_pkg_ver)) {
  115. if (ret==1) strcpy(user_pkgs[cntr].link,full_path_to_packet);
  116. else strcpy(user_pkgs[cntr].link,ala_pkgs[cntr].full_path);
  117. strcpy(user_pkgs[cntr].repo," [installed]");
  118. }
  119. else if (ret==1) {
  120. strcpy(user_pkgs[cntr].link,full_path_to_packet);
  121. strcpy(user_pkgs[cntr].repo," (from cache)");
  122. }
  123. else {
  124. strcpy(user_pkgs[cntr].link,arm_pkgs[cntr].full_path);
  125. strcpy(user_pkgs[cntr].repo," (from ARM)");
  126. }
  127. cntr++;
  128. }
  129. }
  130. return cntr-1;
  131. }
  132. int IsPackageInLogs(char *package) {
  133. for (;pacmanlog_length>0;pacmanlog_length--) {
  134. if (!strcmp(package,pkgs[pacmanlog_length].name) && !strcmp("upgraded",pkgs[pacmanlog_length].action)) { // found necessary package
  135. if (strcmp(pkgs[pacmanlog_length].cur_version, pkgs[pacmanlog_length].prev_version)) { // if the same version - search next
  136. strcpy (full_path_to_packet,"/var/cache/pacman/pkg/");
  137. strcat (full_path_to_packet,package);
  138. strcat (full_path_to_packet,"-");
  139. strcat (full_path_to_packet,pkgs[pacmanlog_length].prev_version);
  140. strcat (full_path_to_packet,"-");
  141. strcat (full_path_to_packet,architecture);
  142. strcat (full_path_to_packet,".pkg.tar.xz");
  143. //printf("full_path_to_packet: %s\n",full_path_to_packet); //DEBUG
  144. break; // Package upgraded at least 1 time
  145. }
  146. }
  147. }
  148. //printf("1: %s\n",full_path_to_packet); //DEBUG
  149. strcpy(install_version,pkgs[pacmanlog_length].prev_version);
  150. ptr = full_path_to_packet;
  151. i_com = str_replace(ptr,":","%3A");
  152. strcpy(full_path_to_packet,i_com); // unescape symbol ":" for pkg "go" for example
  153. if(access(full_path_to_packet, F_OK) != -1) { // previous version available in cache
  154. strcpy(tmp_string,"sudo pacman -U "); // install
  155. strcat(tmp_string,full_path_to_packet);
  156. strcpy(install_command,tmp_string);
  157. //printf("install_command: %s\n",install_command); //DEBUG
  158. return 1;
  159. }
  160. else return 0;
  161. }
  162. int IsPackageInCache(char *package) {
  163. sprintf(full_path_to_packet,"/var/cache/pacman/pkg/%s-%s.pkg.tar.xz", package, architecture);
  164. ptr = full_path_to_packet;
  165. i_com = str_replace(ptr,":","%3A");
  166. strcpy(full_path_to_packet,i_com); // unescape symbol ":" for pkg "go" for example
  167. //printf("%s\n",full_path_to_packet); //DEBUG
  168. if(access(full_path_to_packet, F_OK) != -1) { return 1; }// package in cache
  169. else return 0;
  170. }
  171. size_t curl_handler(char *data, size_t size, size_t nmemb, void *userp) {
  172. size_t realsize = size * nmemb;
  173. struct curl_MemoryStruct *mem = (struct curl_MemoryStruct *)userp;
  174. mem->memory = realloc(mem->memory, mem->size + realsize + 1);
  175. memcpy(&(mem->memory[mem->size]), data, realsize);
  176. mem->size += realsize;
  177. mem->memory[mem->size] = 0;
  178. return realsize;
  179. }
  180. int IsPackageInAur(char *package) {
  181. chunk.memory = malloc(1);
  182. chunk.size = 0;
  183. curl_global_init(CURL_GLOBAL_ALL);
  184. curl = curl_easy_init();
  185. sprintf(tmp_string,"https://aur.archlinux.org/rpc.php?type=search&arg=%s",package);
  186. curl_easy_setopt(curl, CURLOPT_URL, tmp_string);
  187. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_handler);
  188. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
  189. curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  190. result = curl_easy_perform(curl);
  191. if(result != CURLE_OK) {
  192. dgr_output ("Please check you internet connection. AUR reading error\n");
  193. return -1; // Exit with error
  194. }
  195. //// Parsing AUR response
  196. cJSON *root = cJSON_Parse(chunk.memory);
  197. cJSON *item = cJSON_GetObjectItem(root,"results");
  198. for (int i=0;i<cJSON_GetArraySize(item);i++) {
  199. cJSON *subitem=cJSON_GetArrayItem(item,i);
  200. str= cJSON_GetObjectItem(subitem,"Name")->valuestring;
  201. if (!strcmp(str,package)) return 1; // package in AUR
  202. }
  203. cJSON_Delete(root);
  204. curl_easy_cleanup(curl);
  205. curl_global_cleanup();
  206. if(chunk.memory) free(chunk.memory);
  207. return 0; // package not in AUR
  208. }
  209. void ReadPacmanLog() {
  210. char *buff = NULL;
  211. size_t len;
  212. char *date, *time, *operat, *pack_name, *cur_version, *prev_version, *fake;
  213. int i=0;
  214. loglines_counter=0;
  215. pFile=fopen("/var/log/pacman.log","r");
  216. while (!feof(pFile)) { // Count lines q-ty in pacman.log
  217. getline(&buff, &len, pFile);
  218. loglines_counter++;
  219. }
  220. rewind(pFile);
  221. pkgs = calloc(1, sizeof(struct packs));
  222. pkgs = realloc(pkgs, loglines_counter * sizeof(struct packs));
  223. loglines_counter=0;
  224. while (!feof(pFile)) { // Count lines q-ty in pacman.log
  225. getline(&buff, &len, pFile);
  226. date = strtok(buff," ");
  227. date++;
  228. time = strtok(NULL,"] ");
  229. fake = strtok(NULL," ");
  230. operat = strtok(NULL," ");
  231. pack_name = strtok(NULL," ");
  232. //printf("Line: %d, operat: %s\n",i, operat); // DEBUG:
  233. if (!operat) continue;
  234. if (!strcmp(operat,"upgraded")) {
  235. //printf("Upgraded: %s, line: %d\n", pack_name, i+1); //DEBUG:
  236. prev_version = strtok(NULL," ");
  237. prev_version++;
  238. cur_version = strtok(NULL," ");
  239. cur_version = strtok(NULL,")");
  240. strcpy(pkgs[loglines_counter].date,date);
  241. strcpy(pkgs[loglines_counter].time,time);
  242. strcpy(pkgs[loglines_counter].name,pack_name);
  243. strcpy(pkgs[loglines_counter].action,operat);
  244. strcpy(pkgs[loglines_counter].cur_version,cur_version);
  245. strcpy(pkgs[loglines_counter].prev_version,prev_version);
  246. loglines_counter++;
  247. //printf ("date: %s, time: %s, operat: %s, pack_name: %s\n", date, time, operat, pack_name); //DEBUG
  248. }
  249. i++;
  250. }
  251. fclose(pFile);
  252. pacmanlog_length =loglines_counter;
  253. //printf ("pacman log contain %d lines\n", pacmanlog_length); //DEBUG
  254. }
  255. int dgr_output(char *string) {
  256. printf("%s",string);
  257. return 0;
  258. }
  259. int Initialization(char *package) {
  260. openlog("downgrader", LOG_PID|LOG_CONS, LOG_USER);
  261. alpm_handle = NULL;
  262. alpm_handle = alpm_initialize("/","/var/lib/pacman/",0);
  263. if(!alpm_handle) { dgr_output("Libalpm initialize error!\n"); return 1; }
  264. db = alpm_get_localdb(alpm_handle);
  265. pkg = alpm_db_get_pkg(db,(const char*)package);
  266. pkgname = alpm_pkg_get_name(pkg);
  267. if(sizeof(void*) == 4) architecture = (char *)"i686"; // architecture of machine
  268. else if (sizeof(void*) == 8) architecture = (char *)"x86_64";
  269. user_pkgs = calloc(1, sizeof(struct user_packs));
  270. ret = IsPackageAvailable(package);
  271. if (ret==2) { // Wrong package name
  272. int ret1 = IsPackageInAur(package); // check AUR
  273. if (ret1>0) { if(!silent) { sprintf(tmp_string, "Package '%s' in AUR. Downgrade impossible.\n", package); dgr_output(tmp_string); return 1; } }
  274. else { if(!silent) { sprintf(tmp_string, "Package '%s' not available. Please check package name\n", package); dgr_output(tmp_string); return 1; } }
  275. }
  276. else if (ret==1) { if(!silent) { sprintf(tmp_string, "Package '%s' not installed.\n", package); dgr_output(tmp_string); return 1; } }
  277. pkgsinala=pkgsinarm=0;
  278. ReadPacmanLog();
  279. if (WITH_ALA) {
  280. //dgr_output ("Reading ALA, "); //DEBUG
  281. ala_pkgs = calloc(1, sizeof(struct ala_packs));
  282. pkgsinala = ReadALA(package);
  283. //printf ("in ALA %d packages\n", pkgsinala); //DEBUG
  284. if (!pkgsinala) dgr_output ("No packages in ALA! Disable\n");
  285. }
  286. if (WITH_ARM) {
  287. arm_pkgs = calloc(1, sizeof(struct arm_packs));
  288. pkgsinarm = ReadArm(package);
  289. if (!pkgsinarm) dgr_output ("No packages in ARM! Disable\n");
  290. }
  291. if (!pkgsinala && !pkgsinarm) { dgr_output ("No source for packages. Terminating\n"); return 1; }
  292. return 0;
  293. }
  294. int Deinitialization() {
  295. alpm_release(alpm_handle);
  296. free (pkgs);
  297. free (user_pkgs);
  298. if (pkgsinarm) free (arm_pkgs);
  299. if (pkgsinala) free (ala_pkgs);
  300. closelog();
  301. return 0;
  302. }
  303. char *str_replace(char *str, char *orig, char *rep) {
  304. static char buffer[4096];
  305. char *p;
  306. if(!(p = strstr(str, orig))) return str;
  307. strncpy(buffer, str, p-str);
  308. buffer[p-str] = '\0';
  309. sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
  310. return buffer;
  311. }