void patch(void) { int32 c, vexit; Prog *p, *q; Sym *s, *s1; int a; if(debug['v']) Bprint(&bso, "%5.2f patch\n", cputime()); Bflush(&bso); mkfwd(); s = lookup("exit", 0); vexit = s->value; for(p = firstp; p != P; p = p->link) { setarch(p); a = p->as; if(a == ATEXT) curtext = p; if(seenthumb && a == ABL){ // if((s = p->to.sym) != S && (s1 = curtext->from.sym) != S) // print("%s calls %s\n", s1->name, s->name); if((s = p->to.sym) != S && (s1 = curtext->from.sym) != S && s->thumb != s1->thumb) s->foreign = 1; } if((a == ABL || a == ABX || a == AB || a == ARET) && p->to.type != D_BRANCH && p->to.sym != S) { s = p->to.sym; switch(s->type) { default: diag("undefined: %s", s->name); s->type = STEXT; s->value = vexit; continue; // avoid more error messages case STEXT: p->to.offset = s->value; p->to.type = D_BRANCH; break; case SUNDEF: if(p->as != ABL) diag("help: SUNDEF in AB || ARET"); p->to.offset = 0; p->to.type = D_BRANCH; p->cond = UP; break; } } if(p->to.type != D_BRANCH || p->cond == UP) continue; c = p->to.offset; for(q = firstp; q != P;) { if(q->forwd != P) if(c >= q->forwd->pc) { q = q->forwd; continue; } if(c == q->pc) break; q = q->link; } if(q == P) { diag("branch out of range %ld\n%P", c, p); p->to.type = D_NONE; } p->cond = q; } for(p = firstp; p != P; p = p->link) { setarch(p); a = p->as; if(p->as == ATEXT) curtext = p; if(seenthumb && a == ABL) { #ifdef CALLEEBX if(0) {} #else if((s = p->to.sym) != S && (s->foreign || s->fnptr)) p->as = ABX; #endif else if(p->to.type == D_OREG) p->as = ABX; } if(p->cond != P && p->cond != UP) { p->cond = brloop(p->cond); if(p->cond != P) if(p->to.type == D_BRANCH) p->to.offset = p->cond->pc; } } }
void xfol(Prog *p) { Prog *q, *r; int a, i; loop: if(p == P) return; setarch(p); a = p->as; if(a == ATEXT) curtext = p; if(!curtext->from.sym->reachable) { p = p->cond; goto loop; } if(a == AB) { q = p->cond; if(q != P) { p->mark |= FOLL; p = q; if(!(p->mark & FOLL)) goto loop; } } if(p->mark & FOLL) { for(i=0,q=p; i<4; i++,q=q->link) { if(q == lastp) break; a = q->as; if(a == ANOP) { i--; continue; } if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) goto copy; if(!q->cond || (q->cond->mark&FOLL)) continue; if(a != ABEQ && a != ABNE) continue; copy: for(;;) { r = prg(); *r = *p; if(!(r->mark&FOLL)) print("cant happen 1\n"); r->mark |= FOLL; if(p != q) { p = p->link; lastp->link = r; lastp = r; continue; } lastp->link = r; lastp = r; if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) return; r->as = ABNE; if(a == ABNE) r->as = ABEQ; r->cond = p->link; r->link = p->cond; if(!(r->link->mark&FOLL)) xfol(r->link); if(!(r->cond->mark&FOLL)) print("cant happen 2\n"); return; } } a = AB; q = prg(); q->as = a; q->line = p->line; q->to.type = D_BRANCH; q->to.offset = p->pc; q->cond = p; p = q; } p->mark |= FOLL; lastp->link = p; lastp = p; if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){ return; } if(p->cond != P) if(a != ABL && a != ABX && p->link != P) { q = brchain(p->link); if(a != ATEXT && a != ABCASE) if(q != P && (q->mark&FOLL)) { p->as = relinv(a); p->link = p->cond; p->cond = q; } xfol(p->link); q = brchain(p->cond); if(q == P) q = p->cond; if(q->mark&FOLL) { p->cond = q; return; } p = q; goto loop; } p = p->link; goto loop; }
void asmb(void) { Prog *p; long t, etext; Optab *o; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); OFFSET = HEADR; seek(cout, OFFSET, 0); pc = INITTEXT; for(p = firstp; p != P; p = p->link) { setarch(p); if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(thumb) thumbasmout(p, o); else asmout(p, o); pc += o->size; } while(pc-INITTEXT < textsize) { cput(0); pc++; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); /* output strings in text segment */ etext = INITTEXT + textsize; for(t = pc; t < etext; t += sizeof(buf)-100) { if(etext-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 1); else datblk(t, etext-t, 1); } curtext = P; switch(HEADTYPE) { case 0: case 1: case 2: case 5: OFFSET = HEADR+textsize; seek(cout, OFFSET, 0); break; case 3: OFFSET = rnd(HEADR+textsize, 4096); seek(cout, OFFSET, 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 0); else datblk(t, datsize-t, 0); } cflush(); symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 4: case 5: debug['s'] = 1; break; case 2: OFFSET = HEADR+textsize+datsize; seek(cout, OFFSET, 0); break; case 3: OFFSET += rnd(datsize, 4096); seek(cout, OFFSET, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f pc\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(!debug['s']) asmthumbmap(); if(dlm) asmdyn(); cflush(); } else if(dlm){ seek(cout, HEADR+textsize+datsize, 0); asmdyn(); cflush(); } curtext = P; if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); OFFSET = 0; seek(cout, OFFSET, 0); switch(HEADTYPE) { case 0: /* no header */ break; case 1: /* aif for risc os */ lputl(0xe1a00000); /* NOP - decompress code */ lputl(0xe1a00000); /* NOP - relocation code */ lputl(0xeb000000 + 12); /* BL - zero init code */ lputl(0xeb000000 + (entryvalue() - INITTEXT + HEADR - 12 - 8) / 4); /* BL - entry code */ lputl(0xef000011); /* SWI - exit code */ lputl(textsize+HEADR); /* text size */ lputl(datsize); /* data size */ lputl(0); /* sym size */ lputl(bsssize); /* bss size */ lputl(0); /* sym type */ lputl(INITTEXT-HEADR); /* text addr */ lputl(0); /* workspace - ignored */ lputl(32); /* addr mode / data addr flag */ lputl(0); /* data addr */ for(t=0; t<2; t++) lputl(0); /* reserved */ for(t=0; t<15; t++) lputl(0xe1a00000); /* NOP - zero init code */ lputl(0xe1a0f00e); /* B (R14) - zero init return */ break; case 2: /* plan 9 */ if(dlm) lput(0x80000000|0x647); /* magic */ else lput(0x647); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: /* boot for NetBSD */ lput((143<<16)|0413); /* magic */ lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(datsize, 4096)); lputl(bsssize); lputl(symsize); /* nsyms */ lputl(entryvalue()); /* va of entry */ lputl(0L); lputl(0L); break; case 4: /* boot for IXP1200 */ break; case 5: /* boot for ipaq */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; } cflush(); if(debug['c']){ print("textsize=%ld\n", textsize); print("datsize=%ld\n", datsize); print("bsssize=%ld\n", bsssize); print("symsize=%ld\n", symsize); print("lcsize=%ld\n", lcsize); print("total=%ld\n", textsize+datsize+bsssize+symsize+lcsize); } }
void asmb(void) { Prog *p; int32 t, etext; int np; vlong va, fo, w, symo; int strtabsize; vlong symdatva = 0x99LL<<24; Optab *o; strtabsize = 0; symo = 0; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); OFFSET = HEADR; seek(cout, OFFSET, 0); pc = INITTEXT; for(p = firstp; p != P; p = p->link) { setarch(p); if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(thumb) thumbasmout(p, o); else asmout(p, o); pc += o->size; } while(pc-INITTEXT < textsize) { cput(0); pc++; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); /* output strings in text segment */ etext = INITTEXT + textsize; for(t = pc; t < etext; t += sizeof(buf)-100) { if(etext-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 1); else datblk(t, etext-t, 1); } /* output section header strings */ curtext = P; switch(HEADTYPE) { case 0: case 1: case 2: case 5: OFFSET = HEADR+textsize; seek(cout, OFFSET, 0); break; case 3: OFFSET = rnd(HEADR+textsize, 4096); seek(cout, OFFSET, 0); break; case 6: seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); strtabsize = linuxstrtable(); cflush(); t = rnd(HEADR+textsize, INITRND); seek(cout, t, 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 0); else datblk(t, datsize-t, 0); } cflush(); /* output symbol table */ symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 4: case 5: debug['s'] = 1; break; case 2: OFFSET = HEADR+textsize+datsize; seek(cout, OFFSET, 0); break; case 3: OFFSET += rnd(datsize, 4096); seek(cout, OFFSET, 0); break; case 6: symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; symo = rnd(symo, INITRND); seek(cout, symo + 8, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f pc\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(!debug['s']) asmthumbmap(); if(dlm) asmdyn(); cflush(); } else if(dlm){ seek(cout, HEADR+textsize+datsize, 0); asmdyn(); cflush(); } curtext = P; if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); OFFSET = 0; seek(cout, OFFSET, 0); switch(HEADTYPE) { case 0: /* no header */ break; case 1: /* aif for risc os */ lputl(0xe1a00000); /* NOP - decompress code */ lputl(0xe1a00000); /* NOP - relocation code */ lputl(0xeb000000 + 12); /* BL - zero init code */ lputl(0xeb000000 + (entryvalue() - INITTEXT + HEADR - 12 - 8) / 4); /* BL - entry code */ lputl(0xef000011); /* SWI - exit code */ lputl(textsize+HEADR); /* text size */ lputl(datsize); /* data size */ lputl(0); /* sym size */ lputl(bsssize); /* bss size */ lputl(0); /* sym type */ lputl(INITTEXT-HEADR); /* text addr */ lputl(0); /* workspace - ignored */ lputl(32); /* addr mode / data addr flag */ lputl(0); /* data addr */ for(t=0; t<2; t++) lputl(0); /* reserved */ for(t=0; t<15; t++) lputl(0xe1a00000); /* NOP - zero init code */ lputl(0xe1a0f00e); /* B (R14) - zero init return */ break; case 2: /* plan 9 */ if(dlm) lput(0x80000000|0x647); /* magic */ else lput(0x647); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: /* boot for NetBSD */ lput((143<<16)|0413); /* magic */ lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(datsize, 4096)); lputl(bsssize); lputl(symsize); /* nsyms */ lputl(entryvalue()); /* va of entry */ lputl(0L); lputl(0L); break; case 4: /* boot for IXP1200 */ break; case 5: /* boot for ipaq */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; case 6: /* elf arm */ strnput("\177ELF", 4); /* e_ident */ cput(1); /* class = 32 bit */ cput(1); /* data = LSB */ cput(1); /* version = CURRENT */ strnput("", 9); wputl(2); /* type = EXEC */ wputl(40); /* machine = ARM */ lputl(1L); /* version = CURRENT */ lputl(entryvalue()); /* entry vaddr */ lputl(52L); /* offset to first phdr */ np = 3; if(!debug['s']) np++; lputl(52L+32*np); /* offset to first shdr */ lputl(0L); /* processor specific flags */ wputl(52); /* Ehdr size */ wputl(32); /* Phdr size */ wputl(np); /* # of Phdrs */ wputl(40); /* Shdr size */ if (!debug['s']) wputl(7); /* # of Shdrs */ else wputl(5); /* # of Shdrs */ wputl(4); /* Shdr with strings */ fo = 0; va = INITTEXT & ~((vlong)INITRND - 1); w = HEADR+textsize; linuxphdr(1, /* text - type = PT_LOAD */ 1L+4L, /* text - flags = PF_X+PF_R */ 0, /* file offset */ va, /* vaddr */ va, /* paddr */ w, /* file size */ w, /* memory size */ INITRND); /* alignment */ fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); w = datsize; linuxphdr(1, /* data - type = PT_LOAD */ 2L+4L, /* data - flags = PF_W+PF_R */ fo, /* file offset */ va, /* vaddr */ va, /* paddr */ w, /* file size */ w+bsssize, /* memory size */ INITRND); /* alignment */ if(!debug['s']) { linuxphdr(1, /* data - type = PT_LOAD */ 2L+4L, /* data - flags = PF_W+PF_R */ symo, /* file offset */ symdatva, /* vaddr */ symdatva, /* paddr */ 8+symsize+lcsize, /* file size */ 8+symsize+lcsize, /* memory size */ INITRND); /* alignment */ } linuxphdr(0x6474e551, /* gok - type = gok */ 1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ 0, /* file offset */ 0, /* vaddr */ 0, /* paddr */ 0, /* file size */ 0, /* memory size */ 8); /* alignment */ linuxshdr(nil, /* name */ 0, /* type */ 0, /* flags */ 0, /* addr */ 0, /* off */ 0, /* size */ 0, /* link */ 0, /* info */ 0, /* align */ 0); /* entsize */ stroffset = 1; /* 0 means no name, so start at 1 */ fo = HEADR; va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; w = textsize; linuxshdr(".text", /* name */ 1, /* type */ 6, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); w = datsize; linuxshdr(".data", /* name */ 1, /* type */ 3, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ fo += w; va += w; w = bsssize; linuxshdr(".bss", /* name */ 8, /* type */ 3, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ w = strtabsize; linuxshdr(".shstrtab", /* name */ 3, /* type */ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 0); /* entsize */ if (debug['s']) break; fo = symo+8; w = symsize; linuxshdr(".gosymtab", /* name */ 1, /* type 1 = SHT_PROGBITS */ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 24); /* entsize */ fo += w; w = lcsize; linuxshdr(".gopclntab", /* name */ 1, /* type 1 = SHT_PROGBITS*/ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 24); /* entsize */ break; } cflush(); if(debug['c']){ print("textsize=%ld\n", textsize); print("datsize=%ld\n", datsize); print("bsssize=%ld\n", bsssize); print("symsize=%ld\n", symsize); print("lcsize=%ld\n", lcsize); print("total=%ld\n", textsize+datsize+bsssize+symsize+lcsize); } }
int main(int argc, char *argv[]) { int i; char *ppfile; ARGBEGIN{ case 'P': pprof =1; ppfile = EARGF(Usage()); pproffd = Bopen(ppfile, OWRITE); if(pproffd == nil) { fprint(2, "prof: cannot open %s: %r\n", ppfile); exit(2); } break; case 'd': delta_msec = atoi(EARGF(Usage())); break; case 't': total_sec = atoi(EARGF(Usage())); break; case 'p': pid = atoi(EARGF(Usage())); break; case 'f': functions = 1; break; case 'h': histograms = 1; break; case 'l': linenums = 1; break; case 'r': registers = 1; break; case 's': stacks++; break; default: Usage(); }ARGEND if(pid <= 0 && argc == 0) Usage(); if(functions+linenums+registers+stacks+pprof == 0) histograms = 1; if(!machbyname("amd64")) { fprint(2, "prof: no amd64 support\n", pid); exit(1); } if(argc > 0) file = argv[0]; else if(pid) { file = proctextfile(pid); if (file == NULL) { fprint(2, "prof: can't find file for pid %d: %r\n", pid); fprint(2, "prof: on Darwin, need to provide file name explicitly\n"); exit(1); } } fd = open(file, 0); if(fd < 0) { fprint(2, "prof: can't open %s: %r\n", file); exit(1); } if(crackhdr(fd, &fhdr)) { have_syms = syminit(fd, &fhdr); if(!have_syms) { fprint(2, "prof: no symbols for %s: %r\n", file); } } else { fprint(2, "prof: crack header for %s: %r\n", file); exit(1); } if(pid <= 0) pid = startprocess(argv); attachproc(pid, &fhdr); // initializes thread list if(setarch() < 0) { detach(); fprint(2, "prof: can't identify binary architecture for pid %d\n", pid); exit(1); } if(getthreads() <= 0) { detach(); fprint(2, "prof: can't find threads for pid %d\n", pid); exit(1); } for(i = 0; i < nthread; i++) ctlproc(thread[i], "start"); samples(); detach(); dumphistogram(); dumppprof(); exit(0); }
int main(int argc, char **argv) { Pool *pool; Repo *commandlinerepo = 0; Id *commandlinepkgs = 0; Id p; struct repoinfo *repoinfos, installedrepoinfo; int nrepoinfos = 0; int mainmode = 0, mode = 0; int i, newpkgs; Queue job, checkq; Solver *solv = 0; Transaction *trans; FILE **newpkgsfps; Queue repofilter; Queue kindfilter; Queue archfilter; int archfilter_src = 0; int cleandeps = 0; int forcebest = 0; char *rootdir = 0; char *keyname = 0; int keyname_depstr = 0; int debuglevel = 0; int answer, acnt = 0; argc--; argv++; while (argc && !strcmp(argv[0], "-d")) { debuglevel++; argc--; argv++; } if (!argv[0]) usage(1); if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in")) { mainmode = MODE_INSTALL; mode = SOLVER_INSTALL; } #if defined(SUSE) || defined(FEDORA) else if (!strcmp(argv[0], "patch")) { mainmode = MODE_PATCH; mode = SOLVER_INSTALL; } #endif else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm")) { mainmode = MODE_ERASE; mode = SOLVER_ERASE; } else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "ls")) { mainmode = MODE_LIST; mode = 0; } else if (!strcmp(argv[0], "info")) { mainmode = MODE_INFO; mode = 0; } else if (!strcmp(argv[0], "search") || !strcmp(argv[0], "se")) { mainmode = MODE_SEARCH; mode = 0; } else if (!strcmp(argv[0], "verify")) { mainmode = MODE_VERIFY; mode = SOLVER_VERIFY; } else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up")) { mainmode = MODE_UPDATE; mode = SOLVER_UPDATE; } else if (!strcmp(argv[0], "dist-upgrade") || !strcmp(argv[0], "dup")) { mainmode = MODE_DISTUPGRADE; mode = SOLVER_DISTUPGRADE; } else if (!strcmp(argv[0], "repos") || !strcmp(argv[0], "repolist") || !strcmp(argv[0], "lr")) { mainmode = MODE_REPOLIST; mode = 0; } else usage(1); for (;;) { if (argc > 2 && !strcmp(argv[1], "--root")) { rootdir = argv[2]; argc -= 2; argv += 2; } else if (argc > 1 && !strcmp(argv[1], "--clean")) { cleandeps = 1; argc--; argv++; } else if (argc > 1 && !strcmp(argv[1], "--best")) { forcebest = 1; argc--; argv++; } else if (argc > 1 && !strcmp(argv[1], "--depstr")) { keyname_depstr = 1; argc--; argv++; } else if (argc > 2 && !strcmp(argv[1], "--keyname")) { keyname = argv[2]; argc -= 2; argv += 2; } else break; } set_userhome(); pool = pool_create(); pool_set_rootdir(pool, rootdir); #if 0 { const char *langs[] = {"de_DE", "de", "en"}; pool_set_languages(pool, langs, sizeof(langs)/sizeof(*langs)); } #endif pool_setloadcallback(pool, load_stub, 0); #ifdef SUSE pool->nscallback = nscallback; #endif if (debuglevel) pool_setdebuglevel(pool, debuglevel); setarch(pool); pool_set_flag(pool, POOL_FLAG_ADDFILEPROVIDESFILTERED, 1); repoinfos = read_repoinfos(pool, &nrepoinfos); sort_repoinfos(repoinfos, nrepoinfos); if (mainmode == MODE_REPOLIST) { int j = 1; for (i = 0; i < nrepoinfos; i++) { struct repoinfo *cinfo = repoinfos + i; if (!cinfo->enabled) continue; printf("%d: %-20s %s (prio %d)\n", j++, cinfo->alias, cinfo->name, cinfo->priority); } exit(0); } memset(&installedrepoinfo, 0, sizeof(installedrepoinfo)); if (!read_installed_repo(&installedrepoinfo, pool)) exit(1); read_repos(pool, repoinfos, nrepoinfos); /* setup filters */ queue_init(&repofilter); queue_init(&kindfilter); queue_init(&archfilter); while (argc > 1) { if (!strcmp(argv[1], "-i")) { queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO, pool->installed->repoid); argc--; argv++; } else if (argc > 2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "--repo"))) { Id repoid = find_repo(argv[2], pool, repoinfos, nrepoinfos); if (!repoid) { fprintf(stderr, "%s: no such repo\n", argv[2]); exit(1); } /* SETVENDOR is actually wrong but useful */ queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO | SOLVER_SETVENDOR, repoid); argc -= 2; argv += 2; } else if (argc > 2 && !strcmp(argv[1], "--arch")) { if (!strcmp(argv[2], "src") || !strcmp(argv[2], "nosrc")) archfilter_src = 1; queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, argv[2], 1), REL_ARCH, 1)); argc -= 2; argv += 2; } else if (argc > 2 && (!strcmp(argv[1], "-t") || !strcmp(argv[1], "--type"))) { const char *kind = argv[2]; if (!strcmp(kind, "srcpackage")) { /* hey! should use --arch! */ queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, ARCH_SRC, REL_ARCH, 1)); archfilter_src = 1; argc -= 2; argv += 2; continue; } if (!strcmp(kind, "package")) kind = ""; if (!strcmp(kind, "all")) queue_push2(&kindfilter, SOLVER_SOLVABLE_ALL, 0); else queue_push2(&kindfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, kind, 1), REL_KIND, 1)); argc -= 2; argv += 2; } else break; } if (mainmode == MODE_SEARCH) { Queue sel, q; Dataiterator di; if (argc != 2) usage(1); pool_createwhatprovides(pool); queue_init(&sel); dataiterator_init(&di, pool, 0, 0, 0, argv[1], SEARCH_SUBSTRING|SEARCH_NOCASE); dataiterator_set_keyname(&di, SOLVABLE_NAME); dataiterator_set_search(&di, 0, 0); while (dataiterator_step(&di)) queue_push2(&sel, SOLVER_SOLVABLE, di.solvid); dataiterator_set_keyname(&di, SOLVABLE_SUMMARY); dataiterator_set_search(&di, 0, 0); while (dataiterator_step(&di)) queue_push2(&sel, SOLVER_SOLVABLE, di.solvid); dataiterator_set_keyname(&di, SOLVABLE_DESCRIPTION); dataiterator_set_search(&di, 0, 0); while (dataiterator_step(&di)) queue_push2(&sel, SOLVER_SOLVABLE, di.solvid); dataiterator_free(&di); if (repofilter.count) selection_filter(pool, &sel, &repofilter); queue_init(&q); selection_solvables(pool, &sel, &q); queue_free(&sel); for (i = 0; i < q.count; i++) { Solvable *s = pool_id2solvable(pool, q.elements[i]); printf(" - %s [%s]: %s\n", pool_solvable2str(pool, s), s->repo->name, solvable_lookup_str(s, SOLVABLE_SUMMARY)); } queue_free(&q); exit(0); } /* process command line packages */ if (mainmode == MODE_LIST || mainmode == MODE_INFO || mainmode == MODE_INSTALL) { for (i = 1; i < argc; i++) { if (!is_cmdline_package((const char *)argv[i])) continue; if (access(argv[i], R_OK)) { perror(argv[i]); exit(1); } if (!commandlinepkgs) commandlinepkgs = solv_calloc(argc, sizeof(Id)); if (!commandlinerepo) commandlinerepo = repo_create(pool, "@commandline"); p = add_cmdline_package(commandlinerepo, (const char *)argv[i]); if (!p) { fprintf(stderr, "could not add '%s'\n", argv[i]); exit(1); } commandlinepkgs[i] = p; } if (commandlinerepo) repo_internalize(commandlinerepo); } #if defined(ENABLE_RPMDB) if (pool->disttype == DISTTYPE_RPM) addfileprovides(pool); #endif #ifdef SUSE add_autopackages(pool); #endif pool_createwhatprovides(pool); if (keyname) keyname = solv_dupjoin("solvable:", keyname, 0); queue_init(&job); for (i = 1; i < argc; i++) { Queue job2; int flags, rflags; if (commandlinepkgs && commandlinepkgs[i]) { queue_push2(&job, SOLVER_SOLVABLE, commandlinepkgs[i]); continue; } queue_init(&job2); flags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_GLOB; flags |= SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL; if (kindfilter.count) flags |= SELECTION_SKIP_KIND; if (mode == MODE_LIST || archfilter_src) flags |= SELECTION_WITH_SOURCE; if (argv[i][0] == '/') flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0); if (!keyname) rflags = selection_make(pool, &job2, argv[i], flags); else { if (keyname_depstr) flags |= SELECTION_MATCH_DEPSTR; rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); } if (repofilter.count) selection_filter(pool, &job2, &repofilter); if (archfilter.count) selection_filter(pool, &job2, &archfilter); if (kindfilter.count) selection_filter(pool, &job2, &kindfilter); if (!job2.count) { flags |= SELECTION_NOCASE; if (!keyname) rflags = selection_make(pool, &job2, argv[i], flags); else rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); if (repofilter.count) selection_filter(pool, &job2, &repofilter); if (archfilter.count) selection_filter(pool, &job2, &archfilter); if (kindfilter.count) selection_filter(pool, &job2, &kindfilter); if (job2.count) printf("[ignoring case for '%s']\n", argv[i]); } if (!job2.count) { fprintf(stderr, "nothing matches '%s'\n", argv[i]); exit(1); } if (rflags & SELECTION_FILELIST) printf("[using file list match for '%s']\n", argv[i]); if (rflags & SELECTION_PROVIDES) printf("[using capability match for '%s']\n", argv[i]); queue_insertn(&job, job.count, job2.count, job2.elements); queue_free(&job2); } keyname = solv_free(keyname); if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count || archfilter.count || kindfilter.count)) { queue_push2(&job, SOLVER_SOLVABLE_ALL, 0); if (repofilter.count) selection_filter(pool, &job, &repofilter); if (archfilter.count) selection_filter(pool, &job, &archfilter); if (kindfilter.count) selection_filter(pool, &job, &kindfilter); } queue_free(&repofilter); queue_free(&archfilter); queue_free(&kindfilter); if (!job.count && mainmode != MODE_PATCH) { printf("no package matched\n"); exit(1); } if (mainmode == MODE_LIST || mainmode == MODE_INFO) { /* list mode, no solver needed */ Queue q; queue_init(&q); for (i = 0; i < job.count; i += 2) { int j; queue_empty(&q); pool_job2solvables(pool, &q, job.elements[i], job.elements[i + 1]); for (j = 0; j < q.count; j++) { Solvable *s = pool_id2solvable(pool, q.elements[j]); if (mainmode == MODE_INFO) { const char *str; printf("Name: %s\n", pool_solvable2str(pool, s)); printf("Repo: %s\n", s->repo->name); printf("Summary: %s\n", solvable_lookup_str(s, SOLVABLE_SUMMARY)); str = solvable_lookup_str(s, SOLVABLE_URL); if (str) printf("Url: %s\n", str); str = solvable_lookup_str(s, SOLVABLE_LICENSE); if (str) printf("License: %s\n", str); printf("Description:\n%s\n", solvable_lookup_str(s, SOLVABLE_DESCRIPTION)); printf("\n"); } else { #if 1 const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de", 1); #else const char *sum = solvable_lookup_str_poollang(s, SOLVABLE_SUMMARY); #endif printf(" - %s [%s]\n", pool_solvable2str(pool, s), s->repo->name); if (sum) printf(" %s\n", sum); } } } queue_free(&q); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); solv_free(commandlinepkgs); exit(0); } #if defined(SUSE) || defined(FEDORA) if (mainmode == MODE_PATCH) add_patchjobs(pool, &job); #endif // add mode for (i = 0; i < job.count; i += 2) { job.elements[i] |= mode; if (mode == SOLVER_UPDATE && pool_isemptyupdatejob(pool, job.elements[i], job.elements[i + 1])) job.elements[i] ^= SOLVER_UPDATE ^ SOLVER_INSTALL; if (cleandeps) job.elements[i] |= SOLVER_CLEANDEPS; if (forcebest) job.elements[i] |= SOLVER_FORCEBEST; } // multiversion test // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae", 1)); // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-base", 1)); // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-extra", 1)); #if 0 queue_push2(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1)); queue_push2(&job, SOLVER_ERASE|SOLVER_CLEANDEPS|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1)); #endif rerunsolver: solv = solver_create(pool); solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1); #ifdef FEDORA solver_set_flag(solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1); #endif if (mainmode == MODE_ERASE) solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1); /* don't nag */ solver_set_flag(solv, SOLVER_FLAG_BEST_OBEY_POLICY, 1); for (;;) { Id problem, solution; int pcnt, scnt; if (!solver_solve(solv, &job)) break; pcnt = solver_problem_count(solv); printf("Found %d problems:\n", pcnt); for (problem = 1; problem <= pcnt; problem++) { int take = 0; printf("Problem %d/%d:\n", problem, pcnt); solver_printprobleminfo(solv, problem); printf("\n"); scnt = solver_solution_count(solv, problem); for (solution = 1; solution <= scnt; solution++) { printf("Solution %d:\n", solution); solver_printsolution(solv, problem, solution); printf("\n"); } for (;;) { char inbuf[128], *ip; printf("Please choose a solution: "); fflush(stdout); *inbuf = 0; if (!(ip = fgets(inbuf, sizeof(inbuf), stdin))) { printf("Abort.\n"); exit(1); } while (*ip == ' ' || *ip == '\t') ip++; if (*ip >= '0' && *ip <= '9') { take = atoi(ip); if (take >= 1 && take <= scnt) break; } if (*ip == 's') { take = 0; break; } if (*ip == 'q') { printf("Abort.\n"); exit(1); } } if (!take) continue; solver_take_solution(solv, problem, take, &job); } } trans = solver_create_transaction(solv); if (!trans->steps.count) { printf("Nothing to do.\n"); transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); solv_free(commandlinepkgs); exit(1); } /* display transaction to the user and ask for confirmation */ printf("\n"); printf("Transaction summary:\n\n"); transaction_print(trans); #if defined(SUSE) showdiskusagechanges(trans); #endif printf("install size change: %d K\n", transaction_calc_installsizechange(trans)); printf("\n"); acnt = solver_alternatives_count(solv); if (acnt) { if (acnt == 1) printf("Have one alternative:\n"); else printf("Have %d alternatives:\n", acnt); for (i = 1; i <= acnt; i++) { Id id, from; int atype = solver_get_alternative(solv, i, &id, &from, 0, 0, 0); printf(" - %s\n", solver_alternative2str(solv, atype, id, from)); } printf("\n"); answer = yesno("OK to continue (y/n/a)? ", 'a'); } else answer = yesno("OK to continue (y/n)? ", 0); if (answer == 'a') { Queue choicesq; Queue answerq; Id id, from, chosen; int j; queue_init(&choicesq); queue_init(&answerq); for (i = 1; i <= acnt; i++) { int atype = solver_get_alternative(solv, i, &id, &from, &chosen, &choicesq, 0); printf("\n%s\n", solver_alternative2str(solv, atype, id, from)); for (j = 0; j < choicesq.count; j++) { Id p = choicesq.elements[j]; if (p < 0) p = -p; queue_push(&answerq, p); printf("%6d: %s\n", answerq.count, pool_solvid2str(pool, p)); } } queue_free(&choicesq); printf("\n"); for (;;) { char inbuf[128], *ip; int neg = 0; printf("OK to continue (y/n), or number to change alternative: "); fflush(stdout); *inbuf = 0; if (!(ip = fgets(inbuf, sizeof(inbuf), stdin))) { printf("Abort.\n"); exit(1); } while (*ip == ' ' || *ip == '\t') ip++; if (*ip == '-' && ip[1] >= '0' && ip[1] <= '9') { neg = 1; ip++; } if (*ip >= '0' && *ip <= '9') { int take = atoi(ip); if (take > 0 && take <= answerq.count) { Id p = answerq.elements[take - 1]; queue_free(&answerq); queue_push2(&job, (neg ? SOLVER_DISFAVOR : SOLVER_FAVOR) | SOLVER_SOLVABLE_NAME, pool->solvables[p].name); solver_free(solv); solv = 0; goto rerunsolver; break; } } if (*ip == 'n' || *ip == 'y') { answer = *ip == 'n' ? 0 : *ip; break; } } queue_free(&answerq); } if (!answer) { printf("Abort.\n"); transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); solv_free(commandlinepkgs); exit(1); } /* download all new packages */ queue_init(&checkq); newpkgs = transaction_installedresult(trans, &checkq); newpkgsfps = 0; if (newpkgs) { int downloadsize = 0; for (i = 0; i < newpkgs; i++) { Solvable *s; p = checkq.elements[i]; s = pool_id2solvable(pool, p); downloadsize += solvable_lookup_sizek(s, SOLVABLE_DOWNLOADSIZE, 0); } printf("Downloading %d packages, %d K\n", newpkgs, downloadsize); newpkgsfps = solv_calloc(newpkgs, sizeof(*newpkgsfps)); for (i = 0; i < newpkgs; i++) { const char *loc; Solvable *s; struct repoinfo *cinfo; p = checkq.elements[i]; s = pool_id2solvable(pool, p); if (s->repo == commandlinerepo) { loc = solvable_lookup_location(s, 0); if (!loc) continue; if (!(newpkgsfps[i] = fopen(loc, "r"))) { perror(loc); exit(1); } putchar('.'); continue; } cinfo = s->repo->appdata; if (!cinfo || cinfo->type == TYPE_INSTALLED) { printf("%s: no repository information\n", s->repo->name); exit(1); } loc = solvable_lookup_location(s, 0); if (!loc) continue; /* pseudo package? */ #if defined(ENABLE_RPMDB) if (pool->installed && pool->installed->nsolvables) { if ((newpkgsfps[i] = trydeltadownload(s, loc)) != 0) { putchar('d'); fflush(stdout); continue; /* delta worked! */ } } #endif if ((newpkgsfps[i] = downloadpackage(s, loc)) == 0) { printf("\n%s: %s not found in repository\n", s->repo->name, loc); exit(1); } putchar('.'); fflush(stdout); } putchar('\n'); } #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA) || defined(MANDRIVA) || defined(MAGEIA)) /* check for file conflicts */ if (newpkgs) { Queue conflicts; queue_init(&conflicts); if (checkfileconflicts(pool, &checkq, newpkgs, newpkgsfps, &conflicts)) { if (yesno("Re-run solver (y/n/q)? ", 0)) { for (i = 0; i < newpkgs; i++) if (newpkgsfps[i]) fclose(newpkgsfps[i]); newpkgsfps = solv_free(newpkgsfps); solver_free(solv); solv = 0; pool_add_fileconflicts_deps(pool, &conflicts); queue_free(&conflicts); goto rerunsolver; } } queue_free(&conflicts); } #endif /* and finally commit the transaction */ printf("Committing transaction:\n\n"); transaction_order(trans, 0); for (i = 0; i < trans->steps.count; i++) { int j; FILE *fp; Id type; p = trans->steps.elements[i]; type = transaction_type(trans, p, SOLVER_TRANSACTION_RPM_ONLY); switch(type) { case SOLVER_TRANSACTION_ERASE: printf("erase %s\n", pool_solvid2str(pool, p)); commit_transactionelement(pool, type, p, 0); break; case SOLVER_TRANSACTION_INSTALL: case SOLVER_TRANSACTION_MULTIINSTALL: printf("install %s\n", pool_solvid2str(pool, p)); for (j = 0; j < newpkgs; j++) if (checkq.elements[j] == p) break; fp = j < newpkgs ? newpkgsfps[j] : 0; if (!fp) continue; commit_transactionelement(pool, type, p, fp); fclose(fp); newpkgsfps[j] = 0; break; default: break; } } for (i = 0; i < newpkgs; i++) if (newpkgsfps[i]) fclose(newpkgsfps[i]); solv_free(newpkgsfps); queue_free(&checkq); transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); solv_free(commandlinepkgs); exit(0); }