code wiki / (root) / nx_installed_census.nx

nx_installed_census.nx source

↩ module page · 135 lines · 6934 B

1// nx_installed_census.nx -- INSTALLED MODE of the intelmine miner, the thin program over nx_installed_census_lib. 2// nx_installed_census steam <steam-root> [maxdepth=4] [reviews-dir=knowledge/reviews/steam/] [fingerprints-conf] 3// Reads the Steam client's libraries and every app manifest, walks each install tree (bounded), fingerprints what the 4// title SHIPS from knowledge/reviewmine/fingerprints.conf, ties each row to the review rubric journaled for the same 5// appid, prints one INSTALLED line per title, and truncate-writes knowledge/reviews/installed/steam.census (a census is 6// a snapshot, so it is rewritten whole; a run appends nothing). Under WSL pass the Windows root (C:\Program Files 7// (x86)\Steam) or its /mnt/c form; both are mapped. license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_reviewmine_lib.nx" 10import "nx_installed_census_lib.nx" 11 12const ICP_FP_CONF: *u8 = "knowledge/reviewmine/fingerprints.conf" 13const ICP_OUT_DIR: *u8 = "knowledge/reviews/installed" 14const ICP_CENSUS: *u8 = "knowledge/reviews/installed/steam.census" 15const ICP_REVIEWS: *u8 = "knowledge/reviews/steam/" 16const ICP_ROW_CAP: i64 = 8192 17const ICP_OUT_CAP: i64 = 1048576 18const ICP_EXIT_USAGE: i64 = 2 19const ICP_ARGC_MIN: i64 = 3 // nx_installed_census steam <steam-root> 20const ICP_ARG_ROOT: i64 = 2 // argv positions 21const ICP_ARG_DEPTH: i64 = 3 22const ICP_ARG_REVIEWS: i64 = 4 23const ICP_ARG_CONF: i64 = 5 24const ICP_HEADER: *u8 = "# knowledge/reviews/installed/steam.census -- snapshot rows i|appid|name|installdir|size_bytes|buildid|last_updated|last_played|language|library|on_disk|engine|anticheat|vr|audio|net|video|physics|script|mod|redist|files|dirs|walk_capped|reviews_journaled|review_score|total_positive|total_negative|walk_bytes|assets(ext:files:bytes top 8 by bytes)\n" 25 26func icp_usage() -> i64 { 27 rm_w("usage: nx_installed_census steam <steam-root> [maxdepth=4] [reviews-dir] [fingerprints-conf]\n" as *u8) 28 return ICP_EXIT_USAGE 29} 30func icp_print_app(libidx: i64) -> i64 { 31 let lab: *u8 = sys_mmap(IC_LABELS_CAP) 32 rm_w("INSTALLED app=" as *u8); rm_wn(ic_rec_get(IC_R_APPID)) 33 rm_w(" name=" as *u8); rm_w(ic_name_get()) 34 rm_w(" size_bytes=" as *u8); rm_wn(ic_rec_get(IC_R_SIZE)) 35 rm_w(" library=" as *u8); rm_wn(libidx) 36 rm_w(" on_disk=" as *u8); rm_wn(ic_rec_get(IC_R_ON_DISK)) 37 var c: i64 = 0 38 while c < IC_CLASS_N { ic_class_labels(c, lab, IC_LABELS_CAP); rm_w(" " as *u8); rm_w(ic_class_name(c)); rm_w("=" as *u8); rm_w(lab); c = c + 1 } 39 rm_w(" files=" as *u8); rm_wn(ic_rec_get(IC_R_FILES)) 40 rm_w(" dirs=" as *u8); rm_wn(ic_rec_get(IC_R_DIRS)) 41 rm_w(" walk_capped=" as *u8); rm_wn(ic_rec_get(IC_R_CAPPED)) 42 rm_w(" reviews_journaled=" as *u8); rm_wn(ic_rec_get(IC_R_REVIEWS)) 43 rm_w(" review_score=" as *u8); rm_wn(ic_rec_get(IC_R_SCORE)) 44 rm_w(" positive=" as *u8); rm_wn(ic_rec_get(IC_R_POS)) 45 rm_w(" negative=" as *u8); rm_wn(ic_rec_get(IC_R_NEG)) 46 rm_w(" language=" as *u8); rm_w(ic_lang_get()) 47 rm_w(" walk_bytes=" as *u8); rm_wn(ic_rec_get(IC_R_BYTES)) 48 ic_assets_summary(lab, IC_LABELS_CAP, IC_ASSETS_TOP) 49 rm_w(" assets=" as *u8); rm_w(lab) 50 rm_w("\n" as *u8) 51 return 0 52} 53func main(argc: i64, argv: *i64) -> i64 { 54 if argc < ICP_ARGC_MIN { let u: i64 = icp_usage(); sys_exit(u); return u } 55 if rm_streq(argv[1] as *u8, "steam" as *u8) == 0 { let u2: i64 = icp_usage(); sys_exit(u2); return u2 } 56 let root: *u8 = argv[ICP_ARG_ROOT] as *u8 57 var depth: i64 = IC_MAXDEPTH_DEFAULT 58 var reviews: *u8 = ICP_REVIEWS 59 var conf: *u8 = ICP_FP_CONF 60 if argc > ICP_ARG_DEPTH { depth = rm_atoi(argv[ICP_ARG_DEPTH] as *u8) } 61 if argc > ICP_ARG_REVIEWS { reviews = argv[ICP_ARG_REVIEWS] as *u8 } 62 if argc > ICP_ARG_CONF { conf = argv[ICP_ARG_CONF] as *u8 } 63 ic_init() 64 ic_set_maxdepth(depth) 65 let fps: i64 = ic_fp_load(conf) 66 if fps == 0 { rm_w(" NOTE fingerprints conf absent or empty at " as *u8); rm_w(conf); rm_w(" -- every class will read '-'\n" as *u8) } 67 let libs: i64 = ic_libraries(root) 68 rm_mkdirp(ICP_OUT_DIR) 69 let out: *u8 = sys_mmap(ICP_OUT_CAP) 70 var oo: i64 = rm_cat(out, 0, ICP_HEADER) 71 let row: *u8 = sys_mmap(ICP_ROW_CAP) 72 let dbuf: *u8 = sys_mmap(IC_DIRBUF) 73 let sa: *u8 = sys_mmap(IC_PATH_CAP) 74 let mp: *u8 = sys_mmap(IC_PATH_CAP) 75 var apps: i64 = 0 76 var on_disk: i64 = 0 77 var unreadable: i64 = 0 78 var li: i64 = 0 79 while li < libs { 80 let lib: *u8 = ic_lib_at(li) 81 var o: i64 = rm_cat(sa, 0, lib) 82 o = rm_cat(sa, o, "/steamapps" as *u8) 83 sa[o] = 0 as u8 84 rm_w("LIBRARY idx=" as *u8); rm_wn(li); rm_w(" path=" as *u8); rm_w(lib) 85 let fd: i64 = sys_openat_rd(sa) 86 if fd < 0 { rm_w(" steamapps=ABSENT\n" as *u8) } 87 else { 88 rm_w("\n" as *u8) 89 var go: i64 = 1 90 while go == 1 { 91 let nread: i64 = sys_getdents64(fd, dbuf, IC_DIRBUF) 92 if nread <= 0 { go = 0 } 93 else { 94 var off: i64 = 0 95 while off < nread { 96 let rec: *u8 = (dbuf as i64 + off) as *u8 97 let reclen: i64 = dirent_reclen(rec) 98 let name: *u8 = dirent_name(rec) 99 if ic_is_manifest(name) == 1 { 100 var m: i64 = rm_cat(mp, 0, sa) 101 mp[m] = RM_CH_SLASH as u8; m = m + 1 102 m = rm_cat(mp, m, name) 103 mp[m] = 0 as u8 104 if ic_census_app(lib, mp, reviews) == 1 { 105 apps = apps + 1 106 if ic_rec_get(IC_R_ON_DISK) == 1 { on_disk = on_disk + 1 } 107 icp_print_app(li) 108 let rl: i64 = ic_row_emit(li, row, ICP_ROW_CAP) 109 if oo + rl < ICP_OUT_CAP { oo = rm_catn(out, oo, row, rl) } 110 } else { unreadable = unreadable + 1; rm_w("UNREADABLE manifest=" as *u8); rm_w(mp); rm_w("\n" as *u8) } 111 } 112 if reclen <= 0 { off = nread } else { off = off + reclen } 113 } 114 } 115 } 116 sys_close(fd) 117 } 118 li = li + 1 119 } 120 let wrote: i64 = rm_file_put(ICP_CENSUS, out, oo) 121 rm_w("INSTALLED-CENSUS root=" as *u8); rm_w(root) 122 rm_w(" libraries=" as *u8); rm_wn(libs) 123 rm_w(" apps=" as *u8); rm_wn(apps) 124 rm_w(" on_disk=" as *u8); rm_wn(on_disk) 125 rm_w(" not_on_disk=" as *u8); rm_wn(apps - on_disk) 126 rm_w(" unreadable=" as *u8); rm_wn(unreadable) 127 rm_w(" fingerprints=" as *u8); rm_wn(fps) 128 rm_w(" maxdepth=" as *u8); rm_wn(depth) 129 rm_w(" census=" as *u8); rm_w(ICP_CENSUS) 130 rm_w(" bytes=" as *u8); rm_wn(wrote) 131 rm_w("\n" as *u8) 132 if apps == 0 { sys_exit(1); return 1 } 133 sys_exit(0) 134 return 0 135}