From 1a787118d847523aa69e3703155fa6b9e673abce Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Mon, 19 Aug 2024 21:23:58 -0600 Subject: [PATCH] Collect data on dirs --- README.md | 26 +++++++-------- main_windows.go | 82 +++++++++++++++++++++++++++--------------------- modes.db | Bin 16384 -> 28672 bytes 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 4892872..1f498d7 100644 --- a/README.md +++ b/README.md @@ -5,30 +5,26 @@ This is an experiment to see how `os.Chmod` and `os.Stat` interact on Windows. T ## Usage -### `go-perm-test` - -Prints the results as a CSV in the format - -```,``` - -where each set of permissions is an octal integer. - -### `go-perm-test ` +``` +go-perm-test +``` Inserts the results into an SQLite database called `filename`. -There are two objects in the DB schema: a table `result_raw(expected INT, actual INT)` and a view `result`. +There are four objects in the DB schema: tables named `{file,dir}_result_raw(expected INT, actual INT)` and views named `{file,dir}_result`. -The `result` view breaks down the permissions into separate fields: The raw data are in the `expected` and `actual` columns, 3-bit fields are in `{expected,actual}_{u,g,o}` columns, and 1-bit fields are in `{expected,actual}_{u,g,o}{r,w,x}` columns. +The `result` views breaks down the permissions into separate fields: The raw data are in the `expected` and `actual` columns, 3-bit fields are in `{expected,actual}_{u,g,o}` columns, and 1-bit fields are in `{expected,actual}_{u,g,o}{r,w,x}` columns. ## Findings Permissions as observed through `os.Stat` depend entirely upon the owner's write bit set through `os.Chmod`: ``` -sqlite> select distinct actual, expected_uw from result; -actual|expected_uw -292|0 -438|1 +sqlite> select distinct format('%o', actual), expected_uw from dir_result; +20000000555|0 +20000000777|1 +sqlite> select distinct format('%o', actual), expected_uw from file_result; +444|0 +666|1 ``` This obviously isn't an exhaustive treatment of the subject, and I'm not really interested in doing one, but it corraborates [Michal Pristas’s findings.](https://archive.is/RZ8WP) \ No newline at end of file diff --git a/main_windows.go b/main_windows.go index 049b088..036510a 100644 --- a/main_windows.go +++ b/main_windows.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "io/fs" "os" @@ -36,56 +37,66 @@ func sqlViewColSpec() string { return strings.Join(cols, ",\n") } -const createTable = `CREATE TABLE result_raw ( +const createTableFile = `CREATE TABLE file_result_raw ( expected INT NOT NULL, actual INT NOT NULL );` -var createView string = `CREATE VIEW result AS +var createViewFile string = `CREATE VIEW file_result AS SELECT ` + sqlViewColSpec() + ` -FROM result_raw;` +FROM file_result_raw;` + +var createTableDir = strings.ReplaceAll(createTableFile, "file_result", "dir_result") +var createViewDir = strings.ReplaceAll(createViewFile, "file_result", "dir_result") func NewSQLite(path string) (*SQLiteEmitter, error) { conn, err := sqlite.OpenConn(path, sqlite.OpenCreate|sqlite.OpenReadWrite|sqlite.OpenWAL) if err != nil { return nil, err } - fmt.Println(createView) - err = sqlitex.Execute(conn, createTable, &sqlitex.ExecOptions{}) + script := strings.Join([]string{createTableFile, createTableDir, createViewFile, createViewDir}, "\n") + fmt.Println(script) + err = sqlitex.ExecuteScript(conn, script, &sqlitex.ExecOptions{}) if err != nil { - return nil, fmt.Errorf("NewSQLite: cannot create table: %w", err) - } - err = sqlitex.Execute(conn, createView, &sqlitex.ExecOptions{}) - if err != nil { - return nil, fmt.Errorf("NewSQLite: cannot create view: %w", err) + return nil, fmt.Errorf("NewSQLite: cannot create schema: %w", err) } + // err = sqlitex.Execute(conn, createTableFile, &sqlitex.ExecOptions{}) + // if err != nil { + // return nil, fmt.Errorf("NewSQLite: cannot create table: %w", err) + // } + // err = sqlitex.Execute(conn, createViewFile, &sqlitex.ExecOptions{}) + // if err != nil { + // return nil, fmt.Errorf("NewSQLite: cannot create view: %w", err) + // } return &SQLiteEmitter{ conn: conn, }, nil } -func (s *SQLiteEmitter) Emit(r Result) error { - return sqlitex.Execute(s.conn, "INSERT INTO result_raw(expected, actual) VALUES (?, ?)", &sqlitex.ExecOptions{ - Args: []any{r.Expected, r.Actual}, - }) -} - -func emitCSV(r Result) error { - _, err := fmt.Printf("%03o,%03o\n", r.Expected, r.Actual) - if err != nil { - return fmt.Errorf("emitCSV: %w", err) +func (s *SQLiteEmitter) Emit(tablePrefix string) func(r Result) error { + query := fmt.Sprintf("INSERT INTO %sresult_raw(expected, actual) VALUES (?, ?)", tablePrefix) + return func(r Result) error { + return sqlitex.Execute(s.conn, query, &sqlitex.ExecOptions{ + Args: []any{r.Expected, r.Actual}, + }) } - return nil } -func getData(emit func(Result) error) (err error) { - f, err := os.CreateTemp("", "go-perm-test-*") +func createFile(dir, pattern string) (path string, err error) { + f, err := os.CreateTemp(dir, pattern) + if err != nil { + return "", err + } + f.Close() + return f.Name(), nil +} + +func getData(create func(string, string) (string, error), emit func(Result) error) (err error) { + path, err := create("", "go-perm-test-*") if err != nil { return err } - path := f.Name() - f.Close() for mode := fs.FileMode(0); mode <= os.ModePerm; mode++ { err := os.Chmod(path, mode) @@ -109,19 +120,18 @@ func getData(emit func(Result) error) (err error) { } func run() error { - var emit func(Result) error if len(os.Args) < 2 { - emit = emitCSV - } else { - dbPath := os.Args[1] - db, err := NewSQLite(dbPath) - if err != nil { - return err - } - defer db.Close() - emit = db.Emit + fmt.Fprintf(os.Stderr, "usage: %s ", os.Args[0]) } - return getData(emit) + + dbPath := os.Args[1] + db, err := NewSQLite(dbPath) + if err != nil { + return err + } + defer db.Close() + + return errors.Join(getData(createFile, db.Emit("file_")), getData(os.MkdirTemp, db.Emit("dir_"))) } func main() { diff --git a/modes.db b/modes.db index 9ee60547f65f38aafa707b6237bb7e9da0d7fd78..a7b7e69f6e619a62f0839d9224fc6c2ef4e2850b 100644 GIT binary patch literal 28672 zcmeI4chpoxv#+~*rh3opJwZ`KF}*}dl2lYgl&E9{L`5YBK@dff7w>?UsmBiL}%L1IkJogS5Jtu^v$SReJ|&@4)}; zJ8-nmM-7`aDV(y)oGBCMPM9)t^vsF-%$_#uFX}b4Pmke!>PGbIvt!*~f48p3uy|OX zfqi-nk0;LCYvTA>6DPF$lj>U5wc50FuJnXNRxSX!=%$2=FeQfp;m(vxVy0Vw3kIi1dGuSMn0W z!~S}S%jpWwT-i(1$7U~aIbGqYD|?Ch*z6@Prz<=aFLCVnS+mDZ)A*l1uFD?F59>1G zqyNtzRecs-;(znBm3~b1X?S`6&C^!;5!I*t`O^M;N#XzVvQKq}crUVtEX*1)#Lx&7nE}4#=Id<;RaV~1utXbid(M-gX zrc9fdW#Z*<`Bc2z->&82tlWeT)Zahsf0mnCE@mCpPbmI8;19r`Z_eymF3!#jqSxz3_ zqvyare@p3gt>U8o0jujbczE65A^2;Dfdkvc#jHv#|99io^K8_pZCkrwgYet_?Z4@7 z>Q?xT|Mn06uYYGj7hma$99_Wl`nA z%9)jgm7^;4mHCyKm8q3+m64U9mHw5Um9CY}l{S^8mBy6@mAK-{zm&fze^Oprezp8; z`O)%{@@?hCDAJ+rAJFkO1G63mll;SES*_eSURdyUz%TM@7`7!xCc{h0_c`A7zxjnf)xhy#+IVm|ZIVhQ(?2(L3c1#8(y^_t7 z4oQn-?PS#?ihqm0jX#dxieHEyi|>tZj<1d{iqD9Tj}MLai}#Kv$GgSD;(qZ~@g{NG zxJle7F2}jz&&4l`?-ySyK2v# zhJ|K@wF=dOME{Pyjy{auh@OiciSCa66P{{(Tr$fv`e&ov`w^Sv{BSL zT0d$SC6V<%`p^Bl{uTd}f56}FulJYvbNosENPm!@?f39w{f>T+@8vi59efMFwqMmp z@|%1sAIn?vf;=Yo%FS}MTqI}6@p7o_Cwt3e*-eH?KiNt)k+#xA8cA7l`JeM&=HJi1 zmVYMyQ2x&R4f!kb=jBhyADv&2pPQeaAD`bjKP2BLzeT=NeuMnF`PK5p+#k8`bD!qk z$-R_&B6nZz*4(wZOLAxBPRt#iJ0Q1DZc1)+Zin1}T#wwQxeas8a%<(PIdT7XU%L<8 z8z!osnsd%hvCX6UDWu&=yOSo9CX*(SCXptRCXyzQCXmLH#*@a8#*xO7#*)U6#*jvn zMw3R7Mv--eZNjsBvBJD)lk+dUe1Zf0m2ht9t;iTcDVWeTC zp`@Xt?Md5{wj*sv8bTUE8cZ5Y8blgI8b}&Q8bBIA>QCxV>PPBF+Lp8}X&cfuq`suS zq&}oRq~4_7q+X<6q@JXnq#mRmq^(I?leQvlMe0uKPTG>RC8-;!8)*yD7NoAEuB6RL zo0B#pZARLZv?-|zsS9Zn(k7&hNgIHQlq{gJiq_s$Ek=7)wNoquDL|TKi2B{&bA!&8e>ZH|3 ztC1Rz8jw~ctx8&jv2uO_(r2V; zq)$nEkUk+X|Cx_T%zx%167!$=ki`6FJ|HpwnfFP|f95^X1k$^t@ua1sain)h%zx%> z67!#Vi^TkA-Xt;qnKwwxf97=(^PhQ*#QbMoB{Bb*S4hl%=4BG|pLvPI{AXSyG5?tt zNX&occ@p!Vd5*;VXPzZ7|Cwh<%zx%-67!#Vip2b9o+L5|{xf%z znE%XOB<4SJCyDvb+(BagGq;nN|IBS9=09^QiTTgmLSp_iHnUhJ(f950- z^PgErV*WEHl9>O@2_)t}b3BRp&m2c${xiptnE%W%B<4SJG>Q4o97SUOGe?q`|I862 z=09^diTTeQMq>Umhmx58%ps&aDJA7d^(5v$vw+0>XAZVE`2{9t-9fgwKM3(a!~+oz zKs*3(f5iO}_e0zdaX#XF#C;L>MVyB?4{$umP(&Qj z{Pu`Ap!w|(aXj-w5OFy3gAs8w^Mep^F!KWuaV+x#5OFB;{Sk2_^ZgKUAoJTI;yC8F zLBwIq_eI1}%=baWLCp6??1k71u_t0r#2$z}5ODzWTO;E5<+nn_;mdbN#L>%diHL)j z?}mtDm)`;rhc4e05l1e+IU){ReltWIxBRAvIBfYYh&XEbO%QR=@*5-KnB_M@#39Rf zM#K@zcS6Jg%XdV?@yd5V#No=fN5s*}Z-|J4m2ZcLW0h}Bi8DcX;9HM+v#3qPM5OIL=b%;1V`SlTTc=GEZ;^^ep zMa03$uY-tVlV2MVhbG?`5l1G!79tKzeoaIimwY2c9G3hVh&U?whKM*Q`PC6|O!BKC z;*jJUAmWJRS4G4D$*+QlFWI)HCub;YH{~w|Mf42G{I{$0X_n(Tc z|3LKolhE-GM!(+$-Tr#$^*uWMFVN?|h%Wyw^!S&e!#@uF{Ty`nqtM&;MQ7h0ef=7h zxcobM`VY|2KZ$<+CUo=XqL)7mo&28Y<42&2?~We6B|7*D`u88uy}yax{Xul@*Pw4d z6_{n%ld{ewAJ~v(%9~RG#_l(EIBjWyX_qcQ1GHx7KVq5$c zefdkpM~b%>uSQRPVlgewE>1>2KA^Z|u|u&5dT}ZISopZ`8v5|N3)dGeDx88IeBZ(z zh2086(0^}KXi;cXD5CfNJbEj7Cb|!O_hr!;(b3TX=()#6!=gUXrs%iVj>`TI|22B; z7yLv1R(~b>?Bo3czmK1Y9=o64!f)u;M}M7@@8v^z1-fZCEap3w8ETo>k{arn*hCFAO>C@&x+b=$hT0~!poaP;7K10t z{++0CV!ayboLGEjm;E!;I_$2O#47>677ApiM03BCeYqh8&6xRHjeg= z+F07#YUn@2yrqU7M9iCN=tIQ3p@v>W%3^gv?nQbQjk=1w*ALSpVvLq8)mBierhJH!R4Ql9_#4J`r-z4UGHS|tmu2Vz*B<5PR4zz33 z+S9I9+mLpZT07d6YHewY)Y{OlP-{)QT&)%DGPMn8m#Vd-U82^4cClJ>+C^&3XcwwA zrCp%bgm%6f`Y$o(si6lGbFLctFfr$-p%)W#wi@~|F=wfvClhm~8u~IZXQ-h!6LY#6 z`ZF=7si8*`bE+EpG%=^Bp;r@gvKsm|F(;{^XA`qf4Sk!K6V=eWi8(KXZ&4>z_GVjrGqQrN;Vaj#Oj)Ge@Yg{+YwoSpUpnYOH_eP&L*+bBG%2 zpGnnN|4h9a>z`Sm#`7nNNzMn5XMWQ?9v zMrMq@RCdl7y{YV!G5S;4F=Ol^z+R_m!6$V6V%a=n^v1GT#^{e_(~Qw0OP7q%C(9-oqgR%VGe*BG8)b~1SvqHozF9hD zjNVx~W{mz>I%M1d+&*LU(XwI2=%uAy#^|S|ZN})SrA@}@tEF|u=&hwy#^|qQgN)H* zOUsPWXG@EW(Q8ZdjL~mPvy9PmOVf#^}Fg{fyCr%X%5350`Z_MlUYw zWQ=}X*3K9`xirogeYvcaF?w@ZGh_7U(kNr}=(0w}=+mWP#^}{$^^DQ4%W4^;XO{*U zqi>g0Ge++&t7MG+U8)(Qlaflt=;NiFF?x9^WsH7al8n*QOPn$KdMRd%-d+kBqraCZ zWAymqGe(~;k}-OH$!CmyUve3v=NGq(i|G5ahZk+G05rb7ivK`66<4LzpR3Of2ZY*uYwZH}4$RWJweD<=Lws=Qfw9+Lp~RBozVg=zoOF$-`AX8rf7 zOsedPX@G4j-76bo&c6=x03}TM|5W~>{2nF(o-RLFz5^5fmt!X2WX$&;T%J>&hN*y^ z%7e?jG27n}a{=pMvcFLJz4RR>1KuvZSb7{&{kLE?;9|`5pHMoiv_GZ;b}x-84aYqH z)|d}yhiU#bOO;X{69Qi)A0)3Q&n6FJM&QO|QF4BAYH|#w1m-1sCKHm8$#$3%=$3R& zS|#fxt0!?{;veGA;-&G+m=(A`zAe5kzBE1?(*j4t2gbAFsqq-h3k-~V#+$|M@n+S2 z)!u>HJ5YNEYVSbp9jLtnwRhlu`8yCDf)P1qxgwKdJkD9J$fOvJbCxSIDaPWQ<%&#- zkvM1h65lY;GE@(Op5V0XSpJi&LMF{CdJsBvs{r$ zG4kf@wf2nzLMyNim-0ELUVwjHWru6`2%cY0h#*CdEja zv#*gbj^->^WKxWxIm;E96k}-4az!S^2%588kx4Or<}6oa(h(%C$fOuMbCxSIDMrqm zeU5~2GiSLXlVa4&S+2;W7&CL0D>5lY%$((lOp5U`XSpJiVzkUzuE?YqD|41BGATyN zoaKs4ig7Y$xgwKdl+0PK$fOt}bCxSIDMrYgbrHicE^pF=rnjVQkFV`$@e? zT#-pJF6QhK5=O7*p5?5qWjD0!F6`2$xU(Vh@ z!nl{ST#-pJ>g6m~WKxWIIm;E96eC{Faz!S^c$c$Wkx4Py36`2$xT+Uub!uXc6T#-pJy5;O8B#do2doigwi7PTG z#EE2}C zoaKs4icu_QxgwKd49i)r$fOv-a+WJHDaNmy<%&!it_ZjylVa@3S+2;W7`bwmUy-F4 zw{n&%GATx_oaKs4iZLr^xgwKd#L8K&$fOvra+WJHDMqWD<%&#-u_|Y|B9mgI%2}?+ zq!_1imMbzTMyZ_TicE?zDrdPOlVXI**~3W~pK_KfGATx~P2kx4Nw z%rxLlf19{D&=?s6OOB?9oK^A^%~MCaMql54$u`eaL^k2PWNpNjkX`SG-PRJNm!2 z|C(`J{I&Q+@$KTX#ruml6)!KISv;nAU~#YFxZ?0)-{NM)HpO*{m7*zpQ+TiNV&UP! zZH21}=N3*V)E8zICKYxn^e=QPv@g^Z8Wi%;579@_tI^}pUD0*Xh0)2;VbQ#3YP4%K zINCbu95s*DhzkA}|CxW&Kkb+J8~vsJbbplJ-|y+i_@TbH@8Vne#=a!K%U7~go|gyZ z7Fi@`%W-nB%#;Z-LbjEz(oWWsRmA1L%YTr6Isa(>j{G(G^YaVyhvetvch8T^56pMZ zcg#1^#D1p6hTeXvhHn7Hexin35V0St;U+}vM{2kY5&NMU zZbZa>pf-v2z8Y>u#J;CCf%dN2c-m4m+>(fWM-4Y6V&7I9LwieYH0@2bQM5PIcB8$n zwkz#5wOwehs*R+*qQ-{azO1$r?IpDxX)mgcpuM2B1MPXW;k4(}hSBh+3|SSQx}mgZ z)V8NRt+pNQDYYTAC)Ebio=_V^dt7ZG?J>0hv`5u&3nTUsHQdCAeOL{*F=8K5!;OsC z2i4fn+XvKeGb8qXwcfP*)OyjDsNt4I?7eEZsS$gR+SatY)wZJDrPiHxr`ndZJJh<- zZdcoacAHvP+O2Av({54QjCQlyrnH;Xy3qcmwh8SvsIj59i`6>Qu2<_syH2em z?OL@Cv}@Gb)2>$Akam??JKB|MZE1_ta0?{%3N_pWiM?D6w?SerQ^Spr*h|$~(k@ZM z&5+oO)tb{TQfo%LPz|?4VlPm`O_A91)!5M6^VHU-ovXGU?HsjrX=kggLpw`tZQ7Y? zjcI47twlRsZB5!~YK>^8s;xmgMXe$2WVO|4C#kJQTd3B6cB0yaEv_sW!GbQ#AwLC3V z%hBr9a7!h2ff{bA#2%~`>fb@Z@FRLc{X0-C)V~ANLjBucE!4mL)I$B6uNLaxzG|WV z%~K2YZ?0OXe{fbE2Q2+K(3-xcNTBv_}tA+Zvms+TQGt@%;+fyynzv*hB z{!LR0^=}WgQ2(Z?h59!|E!4l=)k6K7tQP9uB(+fgCaQ({H$g4bzwv6J{*6-$^>3_N zsDESBLj4=97V6(9wNU?dQw#NPSG7?8c2NuUZ=_nNe>sDC@Eh59!_E!4jq z)I$9mt`_RwFtt$shN^}7x4l}Zf7_{r`Zq)^)W5-Mq5ch03-xcHTBv^m)I$C1uNLZG zKebT*wp9!DZyU8x|N5$h`qxJ-)W6#i2+ z-R&6hQ2#bi3-zz1 zTBv_5)I$Aht`_QFGqq6vnyQ8R*F-JUzdE&0|JGLv^>013Q2*9d3-xauwNU@oRtxp7 zv0A8qYpI3$x29UCe~r{a{aZsV)W3#mq5iF|7V6(>YN7r$Pz&{MRkcw6R#6M}ue!|s E3*V*#kN^Mx delta 166 zcmZp8z}V2hI6zzaaEY?&2K$PfSZwJGmpSWerD#TtVIS20Nb!IMgRZ+