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}