mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-19 04:41:37 +03:00
Merge branch 'next/vere' into jo/khan-c3
This commit is contained in:
commit
50de7b45b0
@ -159,6 +159,42 @@ so that I can type e.g. `git mu origin/foo 1337`.
|
||||
|
||||
If you're making a Vere release, just play it safe and update all the pills.
|
||||
|
||||
To produce multi pills, you will need to set up an environment with the
|
||||
appropriate desks with the appropriate contents, doing something like the
|
||||
following (where `> ` denotes an urbit command and `% ` denotes a unix shell
|
||||
command):
|
||||
|
||||
```console
|
||||
> |merge %garden our %base
|
||||
> |merge %landscape our %base
|
||||
> |merge %bitcoin our %base
|
||||
> |merge %webterm our %base
|
||||
> |mount %
|
||||
> |mount %garden
|
||||
> |mount %landscape
|
||||
> |mount %bitcoin
|
||||
> |mount %webterm
|
||||
% rsync -avL --delete pkg/arvo/ zod/base/
|
||||
% for desk in garden landscape bitcoin webterm; do \
|
||||
rsync -avL --delete pkg/$desk/ zod/$desk/ \
|
||||
done
|
||||
> |commit %base
|
||||
> |commit %garden
|
||||
> |commit %landscape
|
||||
> |commit %bitcoin
|
||||
> |commit %webterm
|
||||
> .multi/pill +solid %base %garden %landscape %bitcoin %webterm
|
||||
> .brass-multi/pill +brass %base %garden %landscape %bitcoin %webterm
|
||||
```
|
||||
|
||||
And then of course:
|
||||
|
||||
```console
|
||||
> .solid/pill +solid
|
||||
> .brass/pill +brass
|
||||
> .ivory/pill +ivory
|
||||
```
|
||||
|
||||
For an Urbit OS release, after all the merge commits, make a release with the
|
||||
commit message "release: urbit-os-v1.0.xx". This commit should have up-to-date
|
||||
artifacts from pkg/interface and a new version number in the desk.docket-0 of
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9a56f675d2a6c5dafa92a9e2d55040d994f3d3d27a1ed827bd87d1158b1e69d0
|
||||
size 3749183
|
||||
oid sha256:ae4a7a69fe81c5f2114d7b7360c05602f614fe66b96d1db4c3dc0c2a2a5d856e
|
||||
size 7536000
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:843387cce113f18b403f76b6ba97ddf1746a5436b107d087d1f33b38db6f8c1a
|
||||
size 26237959
|
||||
oid sha256:bcab0698de6efda1bbac54b0833da5e853bca058919110aa5668aa63fb40626e
|
||||
size 9392699
|
||||
|
@ -1,6 +1,9 @@
|
||||
{
|
||||
"name": "root",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.29.0",
|
||||
"husky": "^6.0.0",
|
||||
|
@ -60,18 +60,31 @@
|
||||
::
|
||||
++ poke-rekey :: rotate private keys
|
||||
|= des=@t
|
||||
=/ sed=(unit seed:jael)
|
||||
=/ fud=(unit feed:jael)
|
||||
%+ biff
|
||||
(bind (slaw %uw des) cue)
|
||||
(soft seed:jael)
|
||||
(soft feed:jael)
|
||||
=< abet
|
||||
?~ sed
|
||||
?~ fud
|
||||
~& %invalid-private-key
|
||||
this
|
||||
?. =(our.bowl who.u.sed)
|
||||
~& [%wrong-private-key-ship who.u.sed]
|
||||
=/ fed (need fud)
|
||||
?@ -.fed
|
||||
?. =(our.bowl who.fed)
|
||||
~& [%wrong-private-key-ship who.fed]
|
||||
this
|
||||
(emit %pass / %arvo %j %rekey lyf.fed key.fed)
|
||||
?. =(our.bowl who.fed)
|
||||
~& [%wrong-private-key-ship who.fed]
|
||||
this
|
||||
(emit %pass / %arvo %j %rekey lyf.u.sed key.u.sed)
|
||||
=| caz=(list card)
|
||||
%- emil
|
||||
|-
|
||||
?~ kyz.fed (flop caz)
|
||||
%= $
|
||||
kyz.fed t.kyz.fed
|
||||
caz [[%pass / %arvo %j %rekey i.kyz.fed] caz]
|
||||
==
|
||||
::
|
||||
++ ames-secret
|
||||
^- @t
|
||||
|
@ -2235,6 +2235,112 @@
|
||||
=/ pub (from.j qj)
|
||||
?< =([0 0] pub)
|
||||
pub
|
||||
++ schnorr
|
||||
~% %schnorr ..schnorr ~
|
||||
=> |%
|
||||
++ tagged-hash
|
||||
|= [tag=@ [l=@ x=@]]
|
||||
=+ hat=(sha-256:sha (swp 3 tag))
|
||||
%- sha-256l:sha
|
||||
:- (add 64 l)
|
||||
(can 3 ~[[l x] [32 hat] [32 hat]])
|
||||
++ lift-x
|
||||
|= x=@I
|
||||
^- (unit point)
|
||||
=/ c curve
|
||||
?. (lth x p.domain.c)
|
||||
~
|
||||
=/ fop field-p.c
|
||||
=+ [fadd fpow]=[sum.fop exp.fop]
|
||||
=/ cp (fadd (fpow 3 x) 7)
|
||||
=/ y (fpow (rsh [0 2] +(p.domain.c)) cp)
|
||||
?. =(cp (fpow 2 y))
|
||||
~
|
||||
%- some :- x
|
||||
?: =(0 (mod y 2))
|
||||
y
|
||||
(sub p.domain.c y)
|
||||
--
|
||||
|%
|
||||
::
|
||||
++ sign :: schnorr signature
|
||||
~/ %sosi
|
||||
|= [sk=@I m=@I a=@I]
|
||||
^- @J
|
||||
?> (gte 32 (met 3 m))
|
||||
?> (gte 32 (met 3 a))
|
||||
=/ c curve
|
||||
:: implies (gte 32 (met 3 sk))
|
||||
::
|
||||
?< |(=(0 sk) (gte sk n.domain.c))
|
||||
=/ pp
|
||||
(mul-point-scalar g.domain.c sk)
|
||||
=/ d
|
||||
?: =(0 (mod y.pp 2))
|
||||
sk
|
||||
(sub n.domain.c sk)
|
||||
=/ t
|
||||
%+ mix d
|
||||
(tagged-hash 'BIP0340/aux' [32 a])
|
||||
=/ rand
|
||||
%+ tagged-hash 'BIP0340/nonce'
|
||||
:- 96
|
||||
(rep 8 ~[m x.pp t])
|
||||
=/ kp (mod rand n.domain.c)
|
||||
?< =(0 kp)
|
||||
=/ rr (mul-point-scalar g.domain.c kp)
|
||||
=/ k
|
||||
?: =(0 (mod y.rr 2))
|
||||
kp
|
||||
(sub n.domain.c kp)
|
||||
=/ e
|
||||
%- mod
|
||||
:_ n.domain.c
|
||||
%+ tagged-hash 'BIP0340/challenge'
|
||||
:- 96
|
||||
(rep 8 ~[m x.pp x.rr])
|
||||
=/ sig
|
||||
%^ cat 8
|
||||
(mod (add k (mul e d)) n.domain.c)
|
||||
x.rr
|
||||
?> (verify x.pp m sig)
|
||||
sig
|
||||
::
|
||||
++ verify :: schnorr verify
|
||||
~/ %sove
|
||||
|= [pk=@I m=@I sig=@J]
|
||||
^- ?
|
||||
?> (gte 32 (met 3 pk))
|
||||
?> (gte 32 (met 3 m))
|
||||
?> (gte 64 (met 3 sig))
|
||||
=/ c curve
|
||||
=/ pup (lift-x pk)
|
||||
?~ pup
|
||||
%.n
|
||||
=/ pp u.pup
|
||||
=/ r (cut 8 [1 1] sig)
|
||||
?: (gte r p.domain.c)
|
||||
%.n
|
||||
=/ s (end 8 sig)
|
||||
?: (gte s n.domain.c)
|
||||
%.n
|
||||
=/ e
|
||||
%- mod
|
||||
:_ n.domain.c
|
||||
%+ tagged-hash 'BIP0340/challenge'
|
||||
:- 96
|
||||
(rep 8 ~[m x.pp r])
|
||||
=/ aa
|
||||
(mul-point-scalar g.domain.c s)
|
||||
=/ bb
|
||||
(mul-point-scalar pp (sub n.domain.c e))
|
||||
?: &(=(x.aa x.bb) !=(y.aa y.bb)) :: infinite?
|
||||
%.n
|
||||
=/ rr (add-points aa bb)
|
||||
?. =(0 (mod y.rr 2))
|
||||
%.n
|
||||
=(r x.rr)
|
||||
--
|
||||
--
|
||||
--
|
||||
::
|
||||
|
21
pkg/arvo/tests/run/hints.hoon
Normal file
21
pkg/arvo/tests/run/hints.hoon
Normal file
@ -0,0 +1,21 @@
|
||||
:: Test that these hints do not crash the runtime
|
||||
:: there is no need to include the hints for dynamic %bout
|
||||
:: since all hoon tests exersize dynamic %bout
|
||||
|%
|
||||
:: these test that the hilt-trace hints
|
||||
:: are safe to run or ignore
|
||||
++ test-hela-hilt
|
||||
~> %hela
|
||||
~
|
||||
++ test-nara-hilt
|
||||
~> %nara
|
||||
~
|
||||
:: these test that the hint-trace hints
|
||||
:: are safe to run or ignore
|
||||
++ test-hela-hint
|
||||
~> %hela.[1 leaf+"test-hela-trace-hint"]
|
||||
~
|
||||
++ test-nara-hint
|
||||
~> %nara.[1 leaf+"test-nara-trace-hint"]
|
||||
~
|
||||
--
|
@ -116,4 +116,237 @@
|
||||
3d07.03a9.9925.0581.
|
||||
f7de.cd5e.f0f4.f809
|
||||
==
|
||||
++ test-schnorr
|
||||
=> |%
|
||||
+$ case-sec
|
||||
$: sec=@
|
||||
pub=@
|
||||
aux=@
|
||||
mes=@
|
||||
sig=@
|
||||
==
|
||||
+$ case-pub
|
||||
$: pub=@
|
||||
mes=@
|
||||
sig=@
|
||||
res=?
|
||||
==
|
||||
--
|
||||
=< %+ category "bip-0340 vectors"
|
||||
(zing :(weld t1 t2 t3))
|
||||
=/ cases-sec=(list case-sec)
|
||||
:~
|
||||
:* 0x3
|
||||
0xf930.8a01.9258.c310.4934.4f85.f89d.5229.
|
||||
b531.c845.836f.99b0.8601.f113.bce0.36f9
|
||||
0
|
||||
0
|
||||
0xe907.831f.8084.8d10.69a5.371b.4024.1036.
|
||||
4bdf.1c5f.8307.b008.4c55.f1ce.2dca.8215.
|
||||
25f6.6a4a.85ea.8b71.e482.a74f.382d.2ce5.
|
||||
ebee.e8fd.b217.2f47.7df4.900d.3105.36c0
|
||||
==
|
||||
:* 0xb7e1.5162.8aed.2a6a.bf71.5880.9cf4.f3c7.
|
||||
62e7.160f.38b4.da56.a784.d904.5190.cfef
|
||||
0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
1
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x6896.bd60.eeae.296d.b48a.229f.f71d.fe07.
|
||||
1bde.413e.6d43.f917.dc8d.cf8c.78de.3341.
|
||||
8906.d11a.c976.abcc.b20b.0912.92bf.f4ea.
|
||||
897e.fcb6.39ea.871c.fa95.f6de.339e.4b0a
|
||||
==
|
||||
:* 0xc90f.daa2.2168.c234.c4c6.628b.80dc.1cd1.
|
||||
2902.4e08.8a67.cc74.020b.bea6.3b14.e5c9
|
||||
0xdd30.8afe.c577.7e13.121f.a72b.9cc1.b7cc.
|
||||
0139.7153.09b0.86c9.60e1.8fd9.6977.4eb8
|
||||
0xc87a.a538.24b4.d7ae.2eb0.35a2.b5bb.bccc.
|
||||
080e.76cd.c6d1.692c.4b0b.62d7.98e6.d906
|
||||
0x7e2d.58d8.b3bc.df1a.bade.c782.9054.f90d.
|
||||
da98.05aa.b56c.7733.3024.b9d0.a508.b75c
|
||||
0x5831.aaee.d7b4.4bb7.4e5e.ab94.ba9d.4294.
|
||||
c49b.cf2a.6072.8d8b.4c20.0f50.dd31.3c1b.
|
||||
ab74.5879.a5ad.954a.72c4.5a91.c3a5.1d3c.
|
||||
7ade.a98d.82f8.481e.0e1e.0367.4a6f.3fb7
|
||||
==
|
||||
:* 0xb43.2b26.7793.7381.aef0.5bb0.2a66.ecd0.
|
||||
1277.3062.cf3f.a254.9e44.f58e.d240.1710
|
||||
0x25d1.dff9.5105.f525.3c40.22f6.28a9.96ad.
|
||||
3a0d.95fb.f21d.468a.1b33.f8c1.60d8.f517
|
||||
0xffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff
|
||||
0xffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff
|
||||
0x7eb0.5097.57e2.46f1.9449.8856.5161.1cb9.
|
||||
65ec.c1a1.87dd.51b6.4fda.1edc.9637.d5ec.
|
||||
9758.2b9c.b13d.b393.3705.b32b.a982.af5a.
|
||||
f25f.d788.81eb.b327.71fc.5922.efc6.6ea3
|
||||
==
|
||||
==
|
||||
=/ t1
|
||||
%+ turn cases-sec
|
||||
|= case-sec
|
||||
^- tang
|
||||
%+ expect-eq
|
||||
!> sig
|
||||
!> (sign:schnorr:ecc sec mes aux)
|
||||
=/ t2
|
||||
%+ turn cases-sec
|
||||
|= case-sec
|
||||
^- tang
|
||||
%- expect
|
||||
!> (verify:schnorr:ecc pub mes sig)
|
||||
=/ cases-pub=(list case-pub)
|
||||
:~
|
||||
:* 0xd69c.3509.bb99.e412.e68b.0fe8.544e.7283.
|
||||
7dfa.3074.6d8b.e2aa.6597.5f29.d22d.c7b9
|
||||
0x4df3.c3f6.8fcc.83b2.7e9d.42c9.0431.a724.
|
||||
99f1.7875.c81a.599b.566c.9889.b969.6703
|
||||
0x3b.78ce.563f.89a0.ed94.14f5.aa28.ad0d.
|
||||
96d6.795f.9c63.76af.b154.8af6.03b3.eb45.
|
||||
c9f8.207d.ee10.60cb.71c0.4e80.f593.060b.
|
||||
07d2.8308.d7f4
|
||||
%.y
|
||||
==
|
||||
:* 0xeefd.ea4c.db67.7750.a420.fee8.07ea.cf21.
|
||||
eb98.98ae.79b9.7687.66e4.faa0.4a2d.4a34
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x6cff.5c3b.a86c.69ea.4b73.76f3.1a9b.cb4f.
|
||||
74c1.9760.89b2.d996.3da2.e554.3e17.7769.
|
||||
69e8.9b4c.5564.d003.4910.6b84.9778.5dd7.
|
||||
d1d7.13a8.ae82.b32f.a79d.5f7f.c407.d39b
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0xfff9.7bd5.755e.eea4.2045.3a14.3552.35d3.
|
||||
82f6.472f.8568.a18b.2f05.7a14.6029.7556.
|
||||
3cc2.7944.640a.c607.cd10.7ae1.0923.d9ef.
|
||||
7a73.c643.e166.be5e.beaf.a34b.1ac5.53e2
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x1fa6.2e33.1edb.c21c.3947.92d2.ab11.00a7.
|
||||
b432.b013.df3f.6ff4.f99f.cb33.e0e1.515f.
|
||||
2889.0b3e.db6e.7189.b630.448b.515c.e4f8.
|
||||
622a.954c.fe54.5735.aaea.5134.fccd.b2bd
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x6cff.5c3b.a86c.69ea.4b73.76f3.1a9b.cb4f.
|
||||
74c1.9760.89b2.d996.3da2.e554.3e17.7769.
|
||||
9617.64b3.aa9b.2ffc.b6ef.947b.6887.a226.
|
||||
e8d7.c93e.00c5.ed0c.1834.ff0d.0c2e.6da6
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x123d.da83.28af.9c23.a94c.1fee.cfd1.23ba.
|
||||
4fb7.3476.f0d5.94dc.b65c.6425.bd18.6051
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x1.7615.fbaf.5ae2.8864.013c.0997.42de.
|
||||
adb4.dba8.7f11.ac67.54f9.3780.d5a1.837c.
|
||||
f197
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x4a29.8dac.ae57.395a.15d0.795d.dbfd.1dcb.
|
||||
564d.a82b.0f26.9bc7.0a74.f822.0429.ba1d.
|
||||
69e8.9b4c.5564.d003.4910.6b84.9778.5dd7.
|
||||
d1d7.13a8.ae82.b32f.a79d.5f7f.c407.d39b
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0xffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.fffe.ffff.fc2f.
|
||||
69e8.9b4c.5564.d003.4910.6b84.9778.5dd7.
|
||||
d1d7.13a8.ae82.b32f.a79d.5f7f.c407.d39b
|
||||
%.n
|
||||
==
|
||||
:* 0xdff1.d77f.2a67.1c5f.3618.3726.db23.41be.
|
||||
58fe.ae1d.a2de.ced8.4324.0f7b.502b.a659
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x6cff.5c3b.a86c.69ea.4b73.76f3.1a9b.cb4f.
|
||||
74c1.9760.89b2.d996.3da2.e554.3e17.7769.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.fffe.
|
||||
baae.dce6.af48.a03b.bfd2.5e8c.d036.4141
|
||||
%.n
|
||||
==
|
||||
:* 0xffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.fffe.ffff.fc30
|
||||
0x243f.6a88.85a3.08d3.1319.8a2e.0370.7344.
|
||||
a409.3822.299f.31d0.082e.fa98.ec4e.6c89
|
||||
0x6cff.5c3b.a86c.69ea.4b73.76f3.1a9b.cb4f.
|
||||
74c1.9760.89b2.d996.3da2.e554.3e17.7769.
|
||||
69e8.9b4c.5564.d003.4910.6b84.9778.5dd7.
|
||||
d1d7.13a8.ae82.b32f.a79d.5f7f.c407.d39b
|
||||
%.n
|
||||
==
|
||||
==
|
||||
:_ .
|
||||
^= t3
|
||||
%+ turn cases-pub
|
||||
|= case-pub
|
||||
^- tang
|
||||
%+ expect-eq
|
||||
!> res
|
||||
!> (verify:schnorr:ecc pub mes sig)
|
||||
++ test-schnorr-bounds
|
||||
=> |% +$ case [sec=@ pub=@ aux=@ mes=@ sig=@] --
|
||||
=< %+ category "bounds"
|
||||
(zing (weld t1 t2))
|
||||
=/ too-big
|
||||
0xff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff
|
||||
=/ big-sig
|
||||
0xff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff.
|
||||
ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff
|
||||
=/ cases-big-sec=(list case)
|
||||
:~ [too-big 0 0 0 0]
|
||||
[1 0 too-big 0 0]
|
||||
[1 0 0 too-big 0]
|
||||
==
|
||||
=/ cases-big-pub=(list case)
|
||||
:~ [0 too-big 0 0 0]
|
||||
[0 0 0 too-big 0]
|
||||
[0 0 0 0 big-sig]
|
||||
==
|
||||
=/ t1
|
||||
%+ turn cases-big-sec
|
||||
|= case
|
||||
%- expect-fail
|
||||
|. (sign:schnorr:ecc sec mes aux)
|
||||
:_ .
|
||||
^= t2
|
||||
%+ turn cases-big-pub
|
||||
|= case
|
||||
%- expect-fail
|
||||
|. (verify:schnorr:ecc pub mes sig)
|
||||
--
|
||||
|
@ -1,10 +1,10 @@
|
||||
:~ title+'System'
|
||||
info+'An app launcher for Urbit.'
|
||||
color+0xee.5432
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0v5.1o2c9.g1btf.nandl.703oh.40up1.glob' 0v5.1o2c9.g1btf.nandl.703oh.40up1]
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0vcggb9.v4sgp.jbo30.t34mk.58i52.glob' 0vcggb9.v4sgp.jbo30.t34mk.58i52]
|
||||
::glob-ames+~zod^0v0
|
||||
base+'grid'
|
||||
version+[1 0 3]
|
||||
version+[1 1 0]
|
||||
website+'https://tlon.io'
|
||||
license+'MIT'
|
||||
==
|
||||
|
48997
pkg/grid/package-lock.json
generated
48997
pkg/grid/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,10 @@
|
||||
"tsc": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-checkbox": "^0.1.5",
|
||||
"@radix-ui/react-dialog": "^0.0.20",
|
||||
"@radix-ui/react-dropdown-menu": "^0.0.23",
|
||||
"@radix-ui/react-icons": "^1.1.0",
|
||||
"@radix-ui/react-polymorphic": "^0.0.13",
|
||||
"@radix-ui/react-portal": "^0.0.15",
|
||||
"@radix-ui/react-toggle": "^0.0.10",
|
||||
@ -36,6 +38,9 @@
|
||||
"postcss-import": "^14.0.2",
|
||||
"query-string": "^7.0.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dnd": "^15.1.1",
|
||||
"react-dnd-html5-backend": "^15.1.2",
|
||||
"react-dnd-touch-backend": "^15.1.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
|
35
pkg/grid/src/components/Checkbox.tsx
Normal file
35
pkg/grid/src/components/Checkbox.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as RadixCheckbox from '@radix-ui/react-checkbox';
|
||||
import { CheckIcon } from '@radix-ui/react-icons';
|
||||
|
||||
export const Checkbox: React.FC<RadixCheckbox.CheckboxProps> = ({
|
||||
defaultChecked,
|
||||
checked,
|
||||
onCheckedChange,
|
||||
disabled,
|
||||
className,
|
||||
children
|
||||
}) => {
|
||||
const [on, setOn] = useState(defaultChecked);
|
||||
const isControlled = !!onCheckedChange;
|
||||
const proxyChecked = isControlled ? checked : on;
|
||||
const proxyOnCheckedChange = isControlled ? onCheckedChange : setOn;
|
||||
|
||||
return (
|
||||
<div className="flex content-center space-x-2">
|
||||
<RadixCheckbox.Root
|
||||
className={classNames('default-ring rounded-lg bg-white h-7 w-7', className)}
|
||||
checked={proxyChecked}
|
||||
onCheckedChange={proxyOnCheckedChange}
|
||||
disabled={disabled}
|
||||
id="checkbox"
|
||||
>
|
||||
<RadixCheckbox.Indicator className="flex justify-center">
|
||||
<CheckIcon className="text-black" />
|
||||
</RadixCheckbox.Indicator>
|
||||
</RadixCheckbox.Root>
|
||||
<label htmlFor="checkbox">{children}</label>
|
||||
</div>
|
||||
);
|
||||
};
|
20
pkg/grid/src/components/icons/Lock.tsx
Normal file
20
pkg/grid/src/components/icons/Lock.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
export const Lock = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
width="10"
|
||||
height="12"
|
||||
viewBox="-11 -8 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M8 5H9C9.55228 5 10 5.44772 10 6V11C10 11.5523 9.55229 12 9 12H1C0.447716 12 0 11.5523 0 11V6C0 5.44772 0.447715 5 1 5H2V3C2 1.34315 3.34315 0 5 0C6.65685 0 8 1.34315 8 3V5ZM7 5V3C7 1.89543 6.10457 1 5 1C3.89543 1 3 1.89543 3 3V5H7ZM3 6H9V11H1V6H2H3Z"
|
||||
className="fill-current"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
</svg>
|
||||
);
|
@ -5,6 +5,7 @@ import classNames from 'classnames';
|
||||
import { NotificationPrefs } from './preferences/NotificationPrefs';
|
||||
import { SystemUpdatePrefs } from './preferences/SystemUpdatePrefs';
|
||||
import { InterfacePrefs } from './preferences/InterfacePrefs';
|
||||
import { SecurityPrefs } from './preferences/SecurityPrefs';
|
||||
import { useCharges } from '../state/docket';
|
||||
import { AppPrefs } from './preferences/AppPrefs';
|
||||
import { DocketImage } from '../components/DocketImage';
|
||||
@ -14,6 +15,7 @@ import { LeftArrow } from '../components/icons/LeftArrow';
|
||||
import { System } from '../components/icons/System';
|
||||
import { Interface } from '../components/icons/Interface';
|
||||
import { Notifications } from '../components/icons/Notifications';
|
||||
import { Lock } from '../components/icons/Lock';
|
||||
import { getAppName } from '../state/util';
|
||||
|
||||
interface SystemPreferencesSectionProps {
|
||||
@ -77,11 +79,11 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
FallbackComponent={ErrorAlert}
|
||||
onReset={() => history.push('/leap/system-preferences')}
|
||||
>
|
||||
<div className="sm:flex h-full overflow-y-auto">
|
||||
<div className="h-full overflow-y-auto sm:flex">
|
||||
<Route exact={isMobile} path={match.url}>
|
||||
<aside className="flex-none self-start w-full sm:w-auto min-w-60 py-4 sm:py-8 font-semibold text-black sm:text-gray-600 border-r-2 border-gray-50">
|
||||
<aside className="self-start flex-none w-full py-4 font-semibold text-black border-r-2 sm:w-auto min-w-60 sm:py-8 sm:text-gray-600 border-gray-50">
|
||||
<nav className="px-2 sm:px-6">
|
||||
<h2 className="sm:hidden h3 mb-4 px-2">System Preferences</h2>
|
||||
<h2 className="px-2 mb-4 sm:hidden h3">System Preferences</h2>
|
||||
<ul className="space-y-1">
|
||||
<SystemPreferencesSection
|
||||
url={subUrl('notifications')}
|
||||
@ -101,6 +103,10 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
<Interface className="w-8 h-8 mr-3 bg-gray-100 rounded-md" />
|
||||
Interface Settings
|
||||
</SystemPreferencesSection>
|
||||
<SystemPreferencesSection url={subUrl('security')} active={matchSub('security')}>
|
||||
<Lock className="w-8 h-8 mr-3 bg-gray-100 rounded-md" />
|
||||
Security
|
||||
</SystemPreferencesSection>
|
||||
</ul>
|
||||
</nav>
|
||||
<hr className="my-4 border-t-2 border-gray-50" />
|
||||
@ -126,6 +132,7 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
<Route path={`${match.url}/apps/:desk`} component={AppPrefs} />
|
||||
<Route path={`${match.url}/system-updates`} component={SystemUpdatePrefs} />
|
||||
<Route path={`${match.url}/interface`} component={InterfacePrefs} />
|
||||
<Route path={`${match.url}/security`} component={SecurityPrefs} />
|
||||
<Route
|
||||
path={[`${match.url}/notifications`, match.url]}
|
||||
component={NotificationPrefs}
|
||||
@ -133,7 +140,7 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
</Switch>
|
||||
<Link
|
||||
to={match.url}
|
||||
className="inline-flex sm:hidden items-center sm:none mt-auto pt-4 h4 text-gray-400"
|
||||
className="inline-flex items-center pt-4 mt-auto text-gray-400 sm:hidden sm:none h4"
|
||||
>
|
||||
<LeftArrow className="w-3 h-3 mr-2" /> Back
|
||||
</Link>
|
||||
|
32
pkg/grid/src/nav/preferences/SecurityPrefs.tsx
Normal file
32
pkg/grid/src/nav/preferences/SecurityPrefs.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Button } from '../../components/Button';
|
||||
import { Checkbox } from '../../components/Checkbox';
|
||||
|
||||
export const SecurityPrefs = () => {
|
||||
const [allSessions, setAllSessions] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="h3 mb-7">Security</h2>
|
||||
<div className="space-y-3">
|
||||
<section className={classNames('inner-section')}>
|
||||
<h3 className="flex items-center mb-2 h4">Logout</h3>
|
||||
<div className="flex flex-col justify-center flex-1 space-y-6">
|
||||
<Checkbox
|
||||
defaultChecked={false}
|
||||
checked={allSessions}
|
||||
onCheckedChange={() => setAllSessions((prev) => !prev)}
|
||||
>
|
||||
Log out of all sessions.
|
||||
</Checkbox>
|
||||
<form method="post" action="/~/logout">
|
||||
{allSessions && <input type="hidden" name="all" />}
|
||||
<Button>Logout</Button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,46 +1,43 @@
|
||||
import { map, omit } from 'lodash';
|
||||
import React, { FunctionComponent, useEffect } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { Route, RouteComponentProps, useHistory, useParams } from 'react-router-dom';
|
||||
import { Route, useHistory, useParams } from 'react-router-dom';
|
||||
import { ErrorAlert } from '../components/ErrorAlert';
|
||||
import { MenuState, Nav } from '../nav/Nav';
|
||||
import { useCharges } from '../state/docket';
|
||||
import useKilnState from '../state/kiln';
|
||||
import { RemoveApp } from '../tiles/RemoveApp';
|
||||
import { SuspendApp } from '../tiles/SuspendApp';
|
||||
import { Tile } from '../tiles/Tile';
|
||||
import { TileGrid } from '../tiles/TileGrid';
|
||||
|
||||
import { TileInfo } from '../tiles/TileInfo';
|
||||
|
||||
interface RouteProps {
|
||||
menu?: MenuState;
|
||||
}
|
||||
|
||||
export const Grid: FunctionComponent<{}> = () => {
|
||||
const charges = useCharges();
|
||||
export const Grid: FunctionComponent = () => {
|
||||
const { push } = useHistory();
|
||||
const { menu } = useParams<RouteProps>();
|
||||
const chargesLoaded = Object.keys(charges).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
// TOOD: rework
|
||||
// Heuristically detect reload completion and redirect
|
||||
async function attempt(count = 0) {
|
||||
if(count > 5) {
|
||||
if (count > 5) {
|
||||
window.location.reload();
|
||||
}
|
||||
const start = performance.now();
|
||||
await useKilnState.getState().fetchVats();
|
||||
await useKilnState.getState().fetchVats();
|
||||
if((performance.now() - start) > 5000) {
|
||||
attempt(count+1);
|
||||
if (performance.now() - start > 5000) {
|
||||
attempt(count + 1);
|
||||
} else {
|
||||
push('/');
|
||||
}
|
||||
}
|
||||
if(menu === 'upgrading') {
|
||||
if (menu === 'upgrading') {
|
||||
attempt();
|
||||
}
|
||||
}, [menu])
|
||||
}, [menu]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
@ -49,15 +46,7 @@ export const Grid: FunctionComponent<{}> = () => {
|
||||
</header>
|
||||
|
||||
<main className="h-full w-full flex justify-center pt-4 md:pt-16 pb-32 relative z-0">
|
||||
{!chargesLoaded && <span>Loading...</span>}
|
||||
{chargesLoaded && (
|
||||
<div className="grid justify-center grid-cols-2 sm:grid-cols-[repeat(auto-fit,minmax(auto,250px))] gap-4 px-4 md:px-8 w-full max-w-6xl">
|
||||
{charges &&
|
||||
map(omit(charges, window.desk), (charge, desk) => (
|
||||
<Tile key={desk} charge={charge} desk={desk} disabled={menu === 'upgrading'} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<TileGrid menu={menu} />
|
||||
<ErrorBoundary FallbackComponent={ErrorAlert} onReset={() => push('/')}>
|
||||
<Route exact path="/app/:desk">
|
||||
<TileInfo />
|
||||
|
@ -4,7 +4,7 @@ import { compose } from 'lodash/fp';
|
||||
import _ from 'lodash';
|
||||
import create, { GetState, SetState, UseStore } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api';
|
||||
import Urbit, { FatalError, SubscriptionRequestInterface } from '@urbit/http-api';
|
||||
import { Poke } from '@urbit/api';
|
||||
import api from './api';
|
||||
import { clearStorageMigration, createStorageKey, storageVersion, useMockData } from './util';
|
||||
@ -107,7 +107,9 @@ export function createSubscription(
|
||||
path,
|
||||
event: e,
|
||||
err: () => {},
|
||||
quit: () => {}
|
||||
quit: () => {
|
||||
throw new FatalError("subscription clogged");
|
||||
}
|
||||
};
|
||||
// TODO: err, quit handling (resubscribe?)
|
||||
return request;
|
||||
|
@ -21,6 +21,9 @@ interface BaseSettingsState {
|
||||
theme: 'light' | 'dark' | 'auto';
|
||||
doNotDisturb: boolean;
|
||||
};
|
||||
tiles: {
|
||||
order: string[];
|
||||
};
|
||||
putEntry: (bucket: string, key: string, value: Value) => Promise<void>;
|
||||
[ref: string]: unknown;
|
||||
}
|
||||
@ -71,6 +74,9 @@ export const useSettingsState = createState<BaseSettingsState>(
|
||||
theme: 'auto',
|
||||
doNotDisturb: true
|
||||
},
|
||||
tiles: {
|
||||
order: []
|
||||
},
|
||||
loaded: false,
|
||||
putEntry: async (bucket, key, val) => {
|
||||
const poke = doPutEntry(window.desk, bucket, key, val);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { useDrag } from 'react-dnd';
|
||||
import { chadIsRunning } from '@urbit/api';
|
||||
import { TileMenu } from './TileMenu';
|
||||
import { Spinner } from '../components/Spinner';
|
||||
@ -9,6 +10,7 @@ import { ChargeWithDesk } from '../state/docket';
|
||||
import { useTileColor } from './useTileColor';
|
||||
import { useVat } from '../state/kiln';
|
||||
import { Bullet } from '../components/icons/Bullet';
|
||||
import { dragTypes } from './TileGrid';
|
||||
|
||||
type TileProps = {
|
||||
charge: ChargeWithDesk;
|
||||
@ -28,13 +30,23 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = fa
|
||||
const link = getAppHref(href);
|
||||
const backgroundColor = suspended ? suspendColor : active ? tileColor || 'purple' : suspendColor;
|
||||
|
||||
const [{ isDragging }, drag] = useDrag(() => ({
|
||||
type: dragTypes.TILE,
|
||||
item: { desk },
|
||||
collect: (monitor) => ({
|
||||
isDragging: !!monitor.isDragging()
|
||||
})
|
||||
}));
|
||||
|
||||
return (
|
||||
<a
|
||||
ref={drag}
|
||||
href={active ? link : undefined}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={classNames(
|
||||
'group relative font-semibold aspect-w-1 aspect-h-1 rounded-3xl default-ring focus-visible:ring-4 overflow-hidden',
|
||||
'group absolute font-semibold w-full h-full rounded-3xl default-ring focus-visible:ring-4 overflow-hidden',
|
||||
isDragging && 'opacity-0',
|
||||
lightText && active && !loading ? 'text-gray-200' : 'text-gray-800',
|
||||
!active && 'cursor-default'
|
||||
)}
|
||||
@ -48,7 +60,7 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = fa
|
||||
<>
|
||||
{loading && <Spinner className="h-6 w-6 mr-2" />}
|
||||
<span className="text-gray-500">
|
||||
{suspended ? 'Suspended' : loading ? 'Installing' : hung ? 'Errored' : null }
|
||||
{suspended ? 'Suspended' : loading ? 'Installing' : hung ? 'Errored' : null}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
|
56
pkg/grid/src/tiles/TileContainer.tsx
Normal file
56
pkg/grid/src/tiles/TileContainer.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import classNames from 'classnames';
|
||||
import { uniq, without } from 'lodash';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { useDrop } from 'react-dnd';
|
||||
import { useSettingsState } from '../state/settings';
|
||||
import { dragTypes, selTiles } from './TileGrid';
|
||||
|
||||
interface TileContainerProps {
|
||||
desk: string;
|
||||
}
|
||||
|
||||
export const TileContainer: FunctionComponent<TileContainerProps> = ({ desk, children }) => {
|
||||
const { order } = useSettingsState(selTiles);
|
||||
const [{ isOver }, drop] = useDrop<{ desk: string }, undefined, { isOver: boolean }>(
|
||||
() => ({
|
||||
accept: dragTypes.TILE,
|
||||
drop: ({ desk: itemDesk }) => {
|
||||
if (!itemDesk || itemDesk === desk) {
|
||||
return undefined;
|
||||
}
|
||||
// [1, 2, 3, 4] 1 -> 3
|
||||
// [2, 3, 4]
|
||||
const beforeSlot = order.indexOf(itemDesk) < order.indexOf(desk);
|
||||
const orderWithoutOriginal = without(order, itemDesk);
|
||||
const slicePoint = orderWithoutOriginal.indexOf(desk);
|
||||
// [2, 3] [4]
|
||||
const left = orderWithoutOriginal.slice(0, beforeSlot ? slicePoint + 1 : slicePoint);
|
||||
const right = orderWithoutOriginal.slice(slicePoint);
|
||||
// concat([2, 3], [1], [4])
|
||||
const newOrder = uniq(left.concat([itemDesk], right));
|
||||
// [2, 3, 1, 4]
|
||||
console.log({ order, left, right, slicePoint, newOrder });
|
||||
useSettingsState.getState().putEntry('tiles', 'order', newOrder);
|
||||
|
||||
return undefined;
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isOver: !!monitor.isOver()
|
||||
})
|
||||
}),
|
||||
[desk, order]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={drop}
|
||||
className={classNames(
|
||||
'relative aspect-w-1 aspect-h-1 rounded-3xl ring-4',
|
||||
isOver && 'ring-blue-500',
|
||||
!isOver && 'ring-transparent'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
77
pkg/grid/src/tiles/TileGrid.tsx
Normal file
77
pkg/grid/src/tiles/TileGrid.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { TouchBackend } from 'react-dnd-touch-backend';
|
||||
import { uniq } from 'lodash';
|
||||
import { ChargeWithDesk, useCharges } from '../state/docket';
|
||||
import { Tile } from './Tile';
|
||||
import { MenuState } from '../nav/Nav';
|
||||
import { SettingsState, useSettingsState } from '../state/settings';
|
||||
import { TileContainer } from './TileContainer';
|
||||
import { useMedia } from '../logic/useMedia';
|
||||
|
||||
export interface TileData {
|
||||
desk: string;
|
||||
charge: ChargeWithDesk;
|
||||
position: number;
|
||||
dragging: boolean;
|
||||
}
|
||||
|
||||
interface TileGridProps {
|
||||
menu?: MenuState;
|
||||
}
|
||||
|
||||
export const dragTypes = {
|
||||
TILE: 'tile'
|
||||
};
|
||||
|
||||
export const selTiles = (s: SettingsState) => s.tiles;
|
||||
|
||||
export const TileGrid = ({ menu }: TileGridProps) => {
|
||||
const charges = useCharges();
|
||||
const chargesLoaded = Object.keys(charges).length > 0;
|
||||
const { order } = useSettingsState(selTiles);
|
||||
const isMobile = useMedia('(pointer: coarse)');
|
||||
|
||||
useEffect(() => {
|
||||
const hasKeys = order && !!order.length;
|
||||
const chargeKeys = Object.keys(charges);
|
||||
|
||||
if (!hasKeys) {
|
||||
useSettingsState.getState().putEntry('tiles', 'order', chargeKeys);
|
||||
} else if (order.length < chargeKeys.length) {
|
||||
useSettingsState.getState().putEntry('tiles', 'order', uniq(order.concat(chargeKeys)));
|
||||
}
|
||||
}, [charges, order]);
|
||||
|
||||
if (!chargesLoaded) {
|
||||
return <span>Loading...</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<DndProvider
|
||||
backend={isMobile ? TouchBackend : HTML5Backend}
|
||||
options={
|
||||
isMobile
|
||||
? {
|
||||
delay: 50,
|
||||
scrollAngleRanges: [
|
||||
{ start: 30, end: 150 },
|
||||
{ start: 210, end: 330 }
|
||||
]
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<div className="grid justify-center grid-cols-2 sm:grid-cols-[repeat(auto-fit,minmax(auto,250px))] gap-4 px-4 md:px-8 w-full max-w-6xl">
|
||||
{order
|
||||
.filter((d) => d !== window.desk)
|
||||
.map((desk) => (
|
||||
<TileContainer desk={desk}>
|
||||
<Tile key={desk} charge={charges[desk]} desk={desk} disabled={menu === 'upgrading'} />
|
||||
</TileContainer>
|
||||
))}
|
||||
</div>
|
||||
</DndProvider>
|
||||
);
|
||||
};
|
1
pkg/interface/.nvmrc
Normal file
1
pkg/interface/.nvmrc
Normal file
@ -0,0 +1 @@
|
||||
16.14.0
|
@ -4,6 +4,9 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.14.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@radix-ui/react-dialog": "^0.1.0",
|
||||
|
@ -7,7 +7,6 @@
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no,maximum-scale=1"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-touch-fullscreen" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<link rel="manifest"
|
||||
href='data:application/manifest+json,{
|
||||
"name": "Groups",
|
||||
@ -16,6 +15,9 @@
|
||||
"display": "standalone",
|
||||
"background_color": "%23FFFFFF",
|
||||
"theme_color": "%23000000"}' />
|
||||
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#1A1A1A" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#FFFFFF">
|
||||
<script src="/apps/landscape/desk.js"></script>
|
||||
<script src="/session.js"></script>
|
||||
</head>
|
||||
|
@ -229,6 +229,18 @@ export function deSig(ship: string): string {
|
||||
return ship.replace('~', '');
|
||||
}
|
||||
|
||||
export function preSig(ship: string): string {
|
||||
if (!ship) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (ship.trim().startsWith('~')) {
|
||||
return ship.trim();
|
||||
}
|
||||
|
||||
return '~'.concat(ship.trim());
|
||||
}
|
||||
|
||||
export function uxToHex(ux: string) {
|
||||
if (ux.length > 2 && ux.substr(0, 2) === '0x') {
|
||||
const value = ux.substr(2).replace('.', '').padStart(6, '0');
|
||||
|
@ -143,6 +143,8 @@ function PendingGroup(props: PendingGroupProps) {
|
||||
<Box>
|
||||
{!joining ? (
|
||||
<Text color="blue">Invited</Text>
|
||||
) : joining === 'no-perms' || joining == 'strange' ? (
|
||||
<Text color="red">Join Failed</Text>
|
||||
) : joining !== "done" ? (
|
||||
<Text gray>Joining...</Text>
|
||||
) : (
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
} from '@urbit/api';
|
||||
import { BigInteger } from 'big-integer';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useHovering } from '~/logic/lib/util';
|
||||
import { deSig, useHovering } from '~/logic/lib/util';
|
||||
import useLocalState from '~/logic/state/local';
|
||||
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
|
||||
import { SwipeMenu } from '~/views/components/SwipeMenu';
|
||||
@ -38,7 +38,7 @@ const NotificationText = ({ contents, ...rest }: NotificationTextProps) => {
|
||||
return (
|
||||
<Mention
|
||||
key={idx}
|
||||
ship={content.ship}
|
||||
ship={deSig(content.ship)}
|
||||
first={idx === 0}
|
||||
{...rest}
|
||||
/>
|
||||
|
@ -1,54 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
StatelessCheckboxField, Text
|
||||
} from '@tlon/indigo-react';
|
||||
import React, { useState } from 'react';
|
||||
import { BackButton } from './BackButton';
|
||||
|
||||
export default function SecuritySettings() {
|
||||
const [allSessions, setAllSessions] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<BackButton />
|
||||
<Col gapY={5} p={5} pt={4}>
|
||||
<Col gapY={1} mt={0}>
|
||||
<Text fontSize={2} fontWeight="medium">
|
||||
Security Preferences
|
||||
</Text>
|
||||
<Text gray>
|
||||
Manage sessions, login credentials and web access
|
||||
</Text>
|
||||
</Col>
|
||||
<Col gapY={1}>
|
||||
<Text color="black">
|
||||
Log out of this session
|
||||
</Text>
|
||||
<Text mb={3} gray>
|
||||
{allSessions
|
||||
? 'You will be logged out of all browsers that have currently logged into your Urbit.'
|
||||
: 'You will be logged out of your Urbit on this browser.'}
|
||||
</Text>
|
||||
<StatelessCheckboxField
|
||||
mb={3}
|
||||
selected={allSessions}
|
||||
onChange={() => setAllSessions(s => !s)}
|
||||
>
|
||||
<Text>Log out of all sessions</Text>
|
||||
</StatelessCheckboxField>
|
||||
<form method="post" action="/~/logout">
|
||||
{allSessions && <input type="hidden" name="all" />}
|
||||
<Button
|
||||
primary
|
||||
destructive
|
||||
border={1}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
</form>
|
||||
</Col>
|
||||
</Col>
|
||||
</>
|
||||
);
|
||||
}
|
@ -11,7 +11,6 @@ import DisplayForm from './components/lib/DisplayForm';
|
||||
import { LeapSettings } from './components/lib/LeapSettings';
|
||||
import { NotificationPreferences } from './components/lib/NotificationPref';
|
||||
import S3Form from './components/lib/S3Form';
|
||||
import SecuritySettings from './components/lib/Security';
|
||||
import { DmSettings } from './components/lib/DmSettings';
|
||||
import ShortcutSettings from './components/lib/ShortcutSettings';
|
||||
|
||||
@ -117,11 +116,6 @@ return;
|
||||
<SidebarItem icon='Messages' text='Direct Messages' hash='dm' />
|
||||
<SidebarItem icon='Node' text='CalmEngine' hash='calm' />
|
||||
<SidebarItem icon='EastCarat' text='Shortcuts' hash='shortcuts' />
|
||||
<SidebarItem
|
||||
icon='Locked'
|
||||
text='Devices + Security'
|
||||
hash='security'
|
||||
/>
|
||||
</Col>
|
||||
</Col>
|
||||
<Col flexGrow={1} overflowY='auto'>
|
||||
@ -138,7 +132,6 @@ return;
|
||||
{hash === 's3' && <S3Form />}
|
||||
{hash === 'leap' && <LeapSettings />}
|
||||
{hash === 'calm' && <CalmPrefs />}
|
||||
{hash === 'security' && <SecuritySettings />}
|
||||
{hash === 'debug' && <DebugPane />}
|
||||
</SettingsItem>
|
||||
</Col>
|
||||
|
@ -40,8 +40,9 @@ export function MentionText(props: MentionTextProps) {
|
||||
export function Mention(props: {
|
||||
ship: string;
|
||||
first?: boolean;
|
||||
emphasis?: 'bold' | 'italic';
|
||||
} & PropFunc<typeof Text>) {
|
||||
const { ship, first = false, ...rest } = props;
|
||||
const { ship, first = false, emphasis, ...rest } = props;
|
||||
const contact = useContact(`~${deSig(ship)}`);
|
||||
const showNickname = useShowNickname(contact);
|
||||
const name = showNickname ? contact?.nickname : cite(ship);
|
||||
@ -51,8 +52,10 @@ export function Mention(props: {
|
||||
marginLeft={first? 0 : 1}
|
||||
marginRight={1}
|
||||
px={1}
|
||||
bold={emphasis === 'bold' ? true : false}
|
||||
bg='washedBlue'
|
||||
color='blue'
|
||||
fontStyle={emphasis === 'italic' ? 'italic' : undefined}
|
||||
fontSize={showNickname ? 1 : 0}
|
||||
mono={!showNickname}
|
||||
title={showNickname ? cite(ship) : contact?.nickname}
|
||||
|
@ -34,11 +34,14 @@ const FixedOverlay = styled(Col)`
|
||||
transition: all 0.1s ease-out;
|
||||
`;
|
||||
|
||||
type ProfileOverlayProps = BoxProps & {
|
||||
ship: string;
|
||||
children?: ReactNode;
|
||||
color?: string;
|
||||
};
|
||||
interface ProfileOverlayProps extends BoxProps {
|
||||
/**
|
||||
* A valid patp (without sig)
|
||||
*/
|
||||
ship: string,
|
||||
children?: ReactNode,
|
||||
color?: string,
|
||||
}
|
||||
|
||||
const selSettings = (s: SettingsState) => [s.calm.hideAvatars, s.calm.hideNicknames];
|
||||
|
||||
|
@ -167,9 +167,11 @@ export function ShipSearch<I extends string, V extends Value<I>>(
|
||||
name={id}
|
||||
render={(arrayHelpers) => {
|
||||
const onAdd = (ship: string) => {
|
||||
setFieldValue(name(), ship);
|
||||
inputIdx.current += 1;
|
||||
arrayHelpers.push('');
|
||||
if (!pills.includes(ship)) {
|
||||
setFieldValue(name(), ship);
|
||||
inputIdx.current += 1;
|
||||
arrayHelpers.push('');
|
||||
}
|
||||
};
|
||||
|
||||
const onRemove = (idx: number) => {
|
||||
|
@ -34,6 +34,72 @@ interface GraphMentionNode {
|
||||
ship: string;
|
||||
}
|
||||
|
||||
const addEmphasisToMention = (contents: Content[], content: Content, index: number) => {
|
||||
const prevContent = contents[index - 1];
|
||||
const nextContent = contents[index + 1];
|
||||
|
||||
if (
|
||||
'text' in content &&
|
||||
(content.text.trim() === '**' || content.text.trim() === '*' )
|
||||
) {
|
||||
return {
|
||||
text: ''
|
||||
};
|
||||
}
|
||||
if(
|
||||
'text' in content &&
|
||||
content.text.endsWith('*') &&
|
||||
!content.text.startsWith('*') &&
|
||||
nextContent !== undefined &&
|
||||
'mention' in nextContent
|
||||
) {
|
||||
if (content.text.charAt((content.text.length - 2)) === '*') {
|
||||
return { text: content.text.slice(0, content.text.length - 2) };
|
||||
}
|
||||
return { text: content.text.slice(0, content.text.length - 1) };
|
||||
}
|
||||
if (
|
||||
'text' in content &&
|
||||
content.text.startsWith('*') &&
|
||||
!content.text.endsWith('*') &&
|
||||
prevContent !== undefined &&
|
||||
'mention' in contents[index - 1]
|
||||
) {
|
||||
if (content.text.charAt(1) === '*') {
|
||||
return { text: content.text.slice(2, content.text.length) };
|
||||
}
|
||||
return { text: content.text.slice(1, content.text.length) };
|
||||
}
|
||||
if (
|
||||
'mention' in content &&
|
||||
prevContent !== undefined &&
|
||||
'text' in prevContent &&
|
||||
// @ts-ignore type guard above covers this.
|
||||
prevContent.text.endsWith('*') &&
|
||||
nextContent !== undefined &&
|
||||
'text' in contents[index + 1] &&
|
||||
// @ts-ignore type guard above covers this.
|
||||
nextContent.text.startsWith('*')
|
||||
) {
|
||||
if (
|
||||
// @ts-ignore covered by typeguard in conditions
|
||||
prevContent.text.charAt(prevContent.text.length - 2) === '*' &&
|
||||
// @ts-ignore covered by typeguard in conditions
|
||||
nextContent.text.charAt(nextContent.text[1]) === '*'
|
||||
) {
|
||||
return {
|
||||
mention: content.mention,
|
||||
emphasis: 'bold'
|
||||
};
|
||||
}
|
||||
return {
|
||||
mention: content.mention,
|
||||
emphasis: 'italic'
|
||||
};
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
const codeToMdAst = (content: CodeContent) => {
|
||||
return {
|
||||
type: 'root',
|
||||
@ -100,7 +166,8 @@ const contentToMdAst = (tall: boolean) => (
|
||||
children: [
|
||||
{
|
||||
type: 'graph-mention',
|
||||
ship: content.mention
|
||||
ship: content.mention,
|
||||
emphasis: content.emphasis
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -343,7 +410,9 @@ const renderers = {
|
||||
list: ({ depth, ordered, children }) => {
|
||||
return ordered ? <Ol>{children}</Ol> : <Ul>{children}</Ul>;
|
||||
},
|
||||
'graph-mention': ({ ship }) => <Mention ship={ship} />,
|
||||
'graph-mention': (obj) => {
|
||||
return <Mention ship={obj.ship} emphasis={obj.emphasis} />;
|
||||
},
|
||||
image: ({ url, tall }) => (
|
||||
<Box mt="1" mb="2" flexShrink={0}>
|
||||
<RemoteContent key={url} url={url} tall={tall} />
|
||||
@ -439,7 +508,10 @@ export const GraphContent = React.memo((
|
||||
transcluded = 0,
|
||||
...rest
|
||||
} = props;
|
||||
const [, ast] = stitchAsts(contents.map(contentToMdAst(tall)));
|
||||
const [, ast] = stitchAsts(
|
||||
contents
|
||||
.map((content, index) => addEmphasisToMention(contents, content, index))
|
||||
.map(contentToMdAst(tall)));
|
||||
return (
|
||||
<Box {...rest}>
|
||||
<Graphdown transcluded={transcluded} ast={ast} tall={tall} />
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
Button,
|
||||
ManagedTextInputField,
|
||||
ManagedCheckboxField,
|
||||
ContinuousProgressBar,
|
||||
ContinuousProgressBar
|
||||
} from '@tlon/indigo-react';
|
||||
import { Formik, Form } from 'formik';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@ -20,6 +20,7 @@ import airlock from '~/logic/api';
|
||||
import { joinError, joinLoad, JoinProgress } from '@urbit/api';
|
||||
import { useQuery } from '~/logic/lib/useQuery';
|
||||
import { JoinKind, JoinDesc, JoinSkeleton } from './Skeleton';
|
||||
import { preSig } from '~/logic/lib/util';
|
||||
|
||||
interface InviteWithUid extends Invite {
|
||||
uid: string;
|
||||
@ -32,7 +33,7 @@ interface FormSchema {
|
||||
|
||||
const initialValues = {
|
||||
autojoin: false,
|
||||
shareContact: false,
|
||||
shareContact: false
|
||||
};
|
||||
|
||||
function JoinForm(props: {
|
||||
@ -150,22 +151,37 @@ function JoinError(props: {
|
||||
desc: JoinDesc;
|
||||
request: JoinRequest;
|
||||
modal: boolean;
|
||||
dismiss: () => void;
|
||||
}) {
|
||||
const { desc, request, modal } = props;
|
||||
const { dismiss, desc, request, modal } = props;
|
||||
const { preview } = usePreview(desc.group);
|
||||
const group = preview?.metadata?.title ?? desc.group;
|
||||
const title = `Joining ${group} failed`;
|
||||
const explanation =
|
||||
request.progress === 'no-perms'
|
||||
? 'You do not have the correct permissions'
|
||||
: 'An unexpected error occurred';
|
||||
: 'An unexpected error occurred';
|
||||
|
||||
const onRetry = () => {
|
||||
useGroupState.getState().abortJoin(desc.group);
|
||||
const [,,ship,name] = group.split('/');
|
||||
airlock.poke(
|
||||
join(ship, name, desc.kind, false, false)
|
||||
);
|
||||
};
|
||||
|
||||
const onAbort = () => {
|
||||
useGroupState.getState().abortJoin(desc.group);
|
||||
dismiss();
|
||||
};
|
||||
|
||||
return (
|
||||
<JoinSkeleton modal={modal} title={title} desc={desc}>
|
||||
<Col p='4' gapY='4'>
|
||||
<Text fontWeight='medium'>{explanation}</Text>
|
||||
<Row>
|
||||
<Button>Dismiss</Button>
|
||||
<Row gapX="2">
|
||||
<Button onClick={onRetry} primary>Retry</Button>
|
||||
<Button onClick={onAbort} destructive>Abort</Button>
|
||||
</Row>
|
||||
</Col>
|
||||
</JoinSkeleton>
|
||||
@ -233,7 +249,7 @@ export function Join(props: JoinProps) {
|
||||
finished={finishedPath}
|
||||
/>
|
||||
) : isErrored ? (
|
||||
<JoinError modal={modal} desc={desc} request={openedRequest} />
|
||||
<JoinError dismiss={dismiss} modal={modal} desc={desc} request={openedRequest} />
|
||||
) : (
|
||||
<JoinInitial modal={modal} dismiss={dismiss} desc={desc} invite={invite} />
|
||||
);
|
||||
@ -256,7 +272,7 @@ export function JoinPrompt(props: JoinPromptProps) {
|
||||
};
|
||||
|
||||
const onSubmit = async ({ link }: PromptFormSchema) => {
|
||||
const path = `/ship/${link}`;
|
||||
const path = `/ship/${preSig(link)}`;
|
||||
history.push({
|
||||
search: appendQuery({ 'join-path': path })
|
||||
});
|
||||
|
@ -622,6 +622,9 @@
|
||||
[%x %keys ~]
|
||||
:- ~ :- ~ :- mar
|
||||
!>(`update:store`[now.bowl [%keys ~(key by graphs)]])
|
||||
[%x %archived-keys ~]
|
||||
:- ~ :- ~ :- mar
|
||||
!>(`update:store`[now.bowl [%keys ~(key by archive)]])
|
||||
::
|
||||
[%x %tag-queries *]
|
||||
:- ~ :- ~ :- mar
|
||||
@ -636,7 +639,7 @@
|
||||
=/ =ship (slav %p i.t.t.path)
|
||||
=/ =term i.t.t.t.path
|
||||
=/ marked-graph=(unit marked-graph:store)
|
||||
(~(get by graphs) [ship term])
|
||||
(~(get by archive) [ship term])
|
||||
?~ marked-graph [~ ~]
|
||||
=* graph p.u.marked-graph
|
||||
=* mark q.u.marked-graph
|
||||
|
@ -295,12 +295,14 @@
|
||||
::
|
||||
++ rollback
|
||||
|^
|
||||
=/ =request:view (~(got by joining) rid)
|
||||
=/ =request:view (~(got by joining) rid)
|
||||
?+ progress.request ~|(cannot-rollback/progress.request !!)
|
||||
%start start
|
||||
%added added
|
||||
%metadata metadata
|
||||
%start start
|
||||
%added added
|
||||
%metadata metadata
|
||||
?(%no-perms %strange %abort) error
|
||||
==
|
||||
++ error jn-core
|
||||
++ start jn-core
|
||||
++ added (emit del-us:pass)
|
||||
++ metadata (emit:added remove-pull-groups:pass)
|
||||
|
@ -127,7 +127,7 @@
|
||||
++ hark-graph-migrate
|
||||
|= old=state-7:hist
|
||||
=| cards=(list card)
|
||||
|^
|
||||
|^
|
||||
[(flop get-places) state]
|
||||
::
|
||||
++ hark
|
||||
@ -225,7 +225,7 @@
|
||||
?+ -.q.update `state
|
||||
%add-graph (add-graph resource.q.update)
|
||||
::
|
||||
?(%remove-graph %archive-graph)
|
||||
?(%remove-graph %archive-graph)
|
||||
(remove-graph resource.q.update)
|
||||
::
|
||||
%remove-posts
|
||||
@ -258,20 +258,20 @@
|
||||
%+ skim ~(tap in watching)
|
||||
|= [r=resource idx=index:graph-store]
|
||||
=(r rid)
|
||||
:_
|
||||
:_
|
||||
%_ state
|
||||
watching (~(dif in watching) unwatched)
|
||||
places (~(del by places) rid)
|
||||
==
|
||||
%+ turn ~(tap in (~(get ju places) rid))
|
||||
|= =place:store
|
||||
(poke-hark %del-place place)
|
||||
(poke-hark %del-place place)
|
||||
:: XX: fix
|
||||
::
|
||||
++ add-graph
|
||||
|= rid=resource
|
||||
^- (quip card _state)
|
||||
=/ graph=graph:graph-store :: graph in subscription is bunted
|
||||
=/ graph=graph:graph-store :: graph in subscription is bunted
|
||||
(get-graph-mop:gra rid)
|
||||
=/ node=(unit node:graph-store)
|
||||
(bind (pry:orm:graph-store graph) |=([@ =node:graph-store] node))
|
||||
@ -294,7 +294,7 @@
|
||||
++ on-peek on-peek:def
|
||||
::
|
||||
++ on-leave on-leave:def
|
||||
++ on-arvo
|
||||
++ on-arvo
|
||||
|= [=wire =sign-arvo]
|
||||
^- (quip card _this)
|
||||
?+ wire (on-arvo:def wire sign-arvo)
|
||||
@ -317,7 +317,7 @@
|
||||
::
|
||||
++ get-place
|
||||
|= [rid=resource =index:graph-store]
|
||||
:- q.byk.bowl
|
||||
:- q.byk.bowl
|
||||
%+ welp /graph/(scot %p entity.rid)/[name.rid]
|
||||
(graph-index-to-path index)
|
||||
::
|
||||
@ -372,7 +372,7 @@
|
||||
^- (unit _update-core)
|
||||
=/ m=(unit ^mark)
|
||||
(get-mark:gra r)
|
||||
?~ m ~
|
||||
?~ m ~
|
||||
:- ~
|
||||
%_ update-core
|
||||
rid r
|
||||
@ -394,7 +394,7 @@
|
||||
^- (list card)
|
||||
%+ welp (turn (flop hark-pokes) poke-hark)
|
||||
%- zing
|
||||
%+ turn (flop new-watches)
|
||||
%+ turn (flop new-watches)
|
||||
|=(=index:graph-store (give ~[/updates] [%listen rid index]))
|
||||
::
|
||||
++ hark
|
||||
@ -409,7 +409,7 @@
|
||||
?~ updates update-core
|
||||
=/ cor=(unit _post-core)
|
||||
(abed:post-core i.updates)
|
||||
?~ cor $(updates t.updates)
|
||||
?~ cor $(updates t.updates)
|
||||
$(updates t.updates, update-core abet:added:u.cor)
|
||||
::
|
||||
++ remove-posts
|
||||
@ -428,7 +428,7 @@
|
||||
++ post-core
|
||||
|_ [kind=notif-kind:hook =post:graph-store]
|
||||
++ post-core .
|
||||
++ abet
|
||||
++ abet
|
||||
=. places (~(put ju places) rid place)
|
||||
update-core
|
||||
++ abed
|
||||
@ -471,6 +471,7 @@
|
||||
^+ post-core
|
||||
?. should-notify post-core
|
||||
=/ title=(list content:store)
|
||||
?: =(title (crip "{(scow %p our.bowl)}/dm-inbox")) title.kind
|
||||
?. is-mention title.kind
|
||||
~[text/(rap 3 'You were mentioned in ' title ~)]
|
||||
=/ link=path
|
||||
@ -484,7 +485,7 @@
|
||||
^+ post-core
|
||||
%_ post-core
|
||||
update-core
|
||||
?- mode.kind
|
||||
?- mode.kind
|
||||
%count (hark %unread-count place %.y 1)
|
||||
%each (hark %unread-each place /(rsh 4 (scot %ui (rear self-idx))))
|
||||
%none update-core
|
||||
@ -495,7 +496,7 @@
|
||||
^+ post-core
|
||||
%_ post-core
|
||||
update-core
|
||||
?- mode.kind
|
||||
?- mode.kind
|
||||
%count (hark %unread-count place %.n 1)
|
||||
%each (hark %read-each place /(rsh 4 (scot %ui (rear self-idx))))
|
||||
%none update-core
|
||||
@ -535,7 +536,7 @@
|
||||
++ notif-kind
|
||||
|= p=post:graph-store
|
||||
^- (unit notif-kind:hook)
|
||||
|^
|
||||
|^
|
||||
?+ mark ~
|
||||
%graph-validator-chat chat
|
||||
%graph-validator-publish publish
|
||||
@ -572,7 +573,7 @@
|
||||
++ link
|
||||
^- (unit notif-kind:hook)
|
||||
?+ index.p ~
|
||||
[@ ~]
|
||||
[@ ~]
|
||||
:- ~
|
||||
:* [text+(rap 3 'New links in ' title ~)]~
|
||||
[ship+author.p text+': ' (hark-contents:graph-store contents.p)]
|
||||
@ -599,7 +600,7 @@
|
||||
::
|
||||
++ dm
|
||||
?+ index.p ~
|
||||
[@ @ ~]
|
||||
[@ @ ~]
|
||||
:- ~
|
||||
:* ~[text+'New messages from ' ship+author.p]
|
||||
(hark-contents:graph-store contents.p)
|
||||
|
@ -22,6 +22,7 @@
|
||||
[%4 observers=(map serial observer:sur)]
|
||||
[%5 observers=(map serial observer:sur) warm-cache=_|]
|
||||
[%6 state-0]
|
||||
[%7 state-0]
|
||||
==
|
||||
::
|
||||
+$ serial @uv
|
||||
@ -35,7 +36,7 @@
|
||||
--
|
||||
::
|
||||
%- agent:dbug
|
||||
=| [%6 state-0]
|
||||
=| [%7 state-0]
|
||||
=* state -
|
||||
::
|
||||
^- agent:gall
|
||||
@ -117,8 +118,10 @@
|
||||
=| cards=(list card)
|
||||
|-
|
||||
?- -.old-state
|
||||
%6
|
||||
%7
|
||||
[cards this(state old-state)]
|
||||
%6
|
||||
$(-.old-state %7, cards :_(cards (act %warm-cache-all ~)))
|
||||
::
|
||||
%5
|
||||
=. cards
|
||||
|
@ -1,10 +1,10 @@
|
||||
:~ title+'Groups'
|
||||
info+'A suite of applications to communicate on Urbit'
|
||||
color+0xee.5432
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0v2.2tc97.h3e0k.7b26d.a0ma8.em5ce.glob' 0v2.2tc97.h3e0k.7b26d.a0ma8.em5ce]
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0v1r2v6.v94vo.0v3ei.0ukff.upuui.glob' 0v1r2v6.v94vo.0v3ei.0ukff.upuui]
|
||||
|
||||
base+'landscape'
|
||||
version+[1 0 6]
|
||||
version+[1 0 9]
|
||||
website+'https://tlon.io'
|
||||
license+'MIT'
|
||||
==
|
||||
|
@ -41,6 +41,7 @@ export interface AppReference {
|
||||
|
||||
export interface MentionContent {
|
||||
mention: string;
|
||||
emphasis?: 'bold' | 'italic';
|
||||
}
|
||||
export type Content =
|
||||
| TextContent
|
||||
|
@ -350,8 +350,9 @@ intmax_t mdb_get_filesize(HANDLE han_u)
|
||||
|
||||
char *realpath(const char *path, char *resolved_path)
|
||||
{
|
||||
// TODO
|
||||
return strdup(path);
|
||||
// XX MAX_PATH
|
||||
//
|
||||
return _fullpath(resolved_path, path, MAX_PATH);
|
||||
}
|
||||
|
||||
long sysconf(int name)
|
||||
|
@ -10,7 +10,7 @@ _dup_std_handle(HANDLE* new_u, DWORD typ_u)
|
||||
HANDLE han_u = GetStdHandle(typ_u);
|
||||
BOOL con_u = GetConsoleMode(han_u, &dum_u);
|
||||
if ( con_u ) {
|
||||
han_u = (HANDLE)_get_osfhandle(open(c3_dev_null, O_RDWR, 0));
|
||||
han_u = (HANDLE)_get_osfhandle(c3_open(c3_dev_null, O_RDWR, 0));
|
||||
}
|
||||
|
||||
if ( !DuplicateHandle(GetCurrentProcess(), han_u, GetCurrentProcess(), new_u, 0, TRUE, DUPLICATE_SAME_ACCESS) ) {
|
||||
|
@ -55,6 +55,44 @@ _main_presig(c3_c* txt_c)
|
||||
return new_c;
|
||||
}
|
||||
|
||||
/* _main_repath(): canonicalize path, using dirname if needed.
|
||||
*/
|
||||
c3_c*
|
||||
_main_repath(c3_c* pax_c)
|
||||
{
|
||||
c3_c* rel_c;
|
||||
c3_c* fas_c;
|
||||
c3_c* dir_c;
|
||||
c3_w len_w;
|
||||
c3_i wit_i;
|
||||
|
||||
c3_assert(pax_c);
|
||||
if ( 0 != (rel_c = realpath(pax_c, 0)) ) {
|
||||
return rel_c;
|
||||
}
|
||||
fas_c = strrchr(pax_c, '/');
|
||||
if ( !fas_c ) {
|
||||
c3_c rec_c[2048];
|
||||
|
||||
wit_i = snprintf(rec_c, sizeof(rec_c), "./%s", pax_c);
|
||||
c3_assert(sizeof(rec_c) > wit_i);
|
||||
return _main_repath(rec_c);
|
||||
}
|
||||
c3_assert(u3_unix_cane(fas_c + 1));
|
||||
*fas_c = 0;
|
||||
dir_c = realpath(pax_c, 0);
|
||||
*fas_c = '/';
|
||||
if ( 0 == dir_c ) {
|
||||
return 0;
|
||||
}
|
||||
len_w = strlen(dir_c) + strlen(fas_c) + 1;
|
||||
rel_c = c3_malloc(len_w);
|
||||
wit_i = snprintf(rel_c, len_w, "%s%s", dir_c, fas_c);
|
||||
c3_assert(len_w == wit_i + 1);
|
||||
c3_free(dir_c);
|
||||
return rel_c;
|
||||
}
|
||||
|
||||
/* _main_getopt(): extract option map from command line.
|
||||
*/
|
||||
static u3_noun
|
||||
@ -139,7 +177,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'Y': {
|
||||
u3_Host.ops_u.puk_c = strdup(optarg);
|
||||
u3_Host.ops_u.puk_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'Z': {
|
||||
@ -147,11 +185,11 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'J': {
|
||||
u3_Host.ops_u.lit_c = strdup(optarg);
|
||||
u3_Host.ops_u.lit_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'B': {
|
||||
u3_Host.ops_u.pil_c = strdup(optarg);
|
||||
u3_Host.ops_u.pil_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
@ -163,7 +201,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'A': {
|
||||
u3_Host.ops_u.arv_c = strdup(optarg);
|
||||
u3_Host.ops_u.arv_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'H': {
|
||||
@ -171,7 +209,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'I': {
|
||||
u3_Host.ops_u.jin_c = strdup(optarg);
|
||||
u3_Host.ops_u.jin_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
@ -209,7 +247,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'k': {
|
||||
u3_Host.ops_u.key_c = strdup(optarg);
|
||||
u3_Host.ops_u.key_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
@ -231,7 +269,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
u3_Host.ops_u.imp_c = strdup(optarg);
|
||||
u3_Host.ops_u.imp_c = _main_repath(optarg);
|
||||
break;
|
||||
}
|
||||
case 'L': { u3_Host.ops_u.net = c3n; break; }
|
||||
@ -291,7 +329,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
}
|
||||
}
|
||||
|
||||
u3_Host.dir_c = strdup(argv[optind]);
|
||||
u3_Host.dir_c = _main_repath(argv[optind]);
|
||||
}
|
||||
|
||||
// daemon mode (-d) implies disabling terminal assumptions (-t)
|
||||
@ -705,31 +743,7 @@ main(c3_i argc,
|
||||
printf("~\n");
|
||||
// printf("welcome.\n");
|
||||
printf("urbit %s\n", URBIT_VERSION);
|
||||
|
||||
// prints the absolute path of the pier
|
||||
//
|
||||
c3_c* abs_c = realpath(u3_Host.dir_c, 0);
|
||||
|
||||
// if the ship is being booted, we use realpath(). Otherwise, we use getcwd()
|
||||
// with a memory-allocation loop
|
||||
//
|
||||
if (abs_c == NULL) {
|
||||
c3_i mprint_i = 1000;
|
||||
abs_c = c3_malloc(mprint_i);
|
||||
|
||||
// allocates more memory as needed if the path is too large
|
||||
//
|
||||
while ( abs_c != getcwd(abs_c, mprint_i) ) {
|
||||
c3_free(abs_c);
|
||||
mprint_i *= 2;
|
||||
abs_c = c3_malloc(mprint_i);
|
||||
}
|
||||
printf("boot: home is %s/%s\n", abs_c, u3_Host.dir_c);
|
||||
c3_free(abs_c);
|
||||
} else {
|
||||
printf("boot: home is %s\n", abs_c);
|
||||
c3_free(abs_c);
|
||||
}
|
||||
printf("boot: home is %s\n", u3_Host.dir_c);
|
||||
// printf("vere: hostname is %s\n", u3_Host.ops_u.nam_c);
|
||||
|
||||
if ( c3y == u3_Host.ops_u.dem ) {
|
||||
|
@ -122,4 +122,35 @@
|
||||
} \
|
||||
rut;})
|
||||
|
||||
/* Asserting unix fs wrappers.
|
||||
**
|
||||
** these all crash the process if passed a non-canonical
|
||||
** path (i.e., one containing '.', '..', or the empty path
|
||||
** component), so make sure you don't pass them one. if you
|
||||
** find yourself fighting with them, then please delete them
|
||||
** and do a sed search-and-replace to remove the `c3_` from
|
||||
** their call sites; their goal is to decrease maintenance
|
||||
** burden, not increase it.
|
||||
*/
|
||||
// defined in vere/io/unix.c.
|
||||
c3_t u3_unix_cane(const c3_c* pax_c);
|
||||
# define c3_open(a, ...) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
open(a, __VA_ARGS__);})
|
||||
# define c3_opendir(a) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
opendir(a);})
|
||||
# define c3_mkdir(a, b) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
mkdir(a, b);})
|
||||
# define c3_rmdir(a) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
rmdir(a);})
|
||||
# define c3_unlink(a) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
unlink(a);})
|
||||
# define c3_fopen(a, b) ({ \
|
||||
c3_assert(u3_unix_cane(a)); \
|
||||
fopen(a, b);})
|
||||
|
||||
#endif /* ifndef C3_DEFS_H */
|
||||
|
@ -36,18 +36,16 @@
|
||||
# define c3__bac c3_s3('b','a','c')
|
||||
# define c3__bach c3_s4('b','a','c','h')
|
||||
# define c3__bag c3_s3('b','a','g')
|
||||
# define c3__bar c3_s3('b','a','r')
|
||||
# define c3__bail c3_s4('b','a','i','l')
|
||||
# define c3__ball c3_s4('b','a','l','l')
|
||||
# define c3__band c3_s4('b','a','n','d')
|
||||
# define c3__bank c3_s4('b','a','n','k')
|
||||
# define c3__bar c3_s3('b','a','r')
|
||||
# define c3__bark c3_s4('b','a','r','k')
|
||||
# define c3__barn c3_s4('b','a','r','n')
|
||||
# define c3__base c3_s4('b','a','s','e')
|
||||
# define c3__bask c3_s4('b','a','s','k')
|
||||
# define c3__basp c3_s4('b','a','s','p')
|
||||
# define c3__bee c3_s3('b','e','e')
|
||||
# define c3__bel c3_s3('b','e','l')
|
||||
# define c3__bbye c3_s4('b','b','y','e')
|
||||
# define c3__bcbn c3_s4('b','c','b','n')
|
||||
# define c3__bcbr c3_s4('b','c','b','r')
|
||||
@ -68,7 +66,9 @@
|
||||
# define c3__bean c3_s4('b','e','a','n')
|
||||
# define c3__bear c3_s4('b','e','a','r')
|
||||
# define c3__bede c3_s4('b','e','d','e')
|
||||
# define c3__bee c3_s3('b','e','e')
|
||||
# define c3__behn c3_s4('b','e','h','n')
|
||||
# define c3__bel c3_s3('b','e','l')
|
||||
# define c3__belt c3_s4('b','e','l','t')
|
||||
# define c3__bend c3_s4('b','e','n','d')
|
||||
# define c3__ber c3_s3('b','e','r')
|
||||
@ -101,6 +101,7 @@
|
||||
# define c3__bnpd c3_s4('b','n','p','d')
|
||||
# define c3__bnps c3_s4('b','n','p','s')
|
||||
# define c3__bnsp c3_s4('b','n','s','p')
|
||||
# define c3__boat c3_s4('b','o','a','t')
|
||||
# define c3__boce c3_s4('b','o','c','e')
|
||||
# define c3__boil c3_s4('b','o','i','l')
|
||||
# define c3__boin c3_s4('b','o','i','n')
|
||||
@ -110,7 +111,6 @@
|
||||
# define c3__bong c3_s4('b','o','n','g')
|
||||
# define c3__book c3_s4('b','o','o','k')
|
||||
# define c3__bool c3_s4('b','o','o','l')
|
||||
# define c3__boat c3_s4('b','o','a','t')
|
||||
# define c3__boot c3_s4('b','o','o','t')
|
||||
# define c3__born c3_s4('b','o','r','n')
|
||||
# define c3__both c3_s4('b','o','t','h')
|
||||
@ -121,16 +121,16 @@
|
||||
# define c3__brax c3_s4('b','r','a','x')
|
||||
# define c3__brbn c3_s4('b','r','b','n')
|
||||
# define c3__brcb c3_s4('b','r','c','b')
|
||||
# define c3__brcl c3_s4('b','r','c','l')
|
||||
# define c3__brcn c3_s4('b','r','c','n')
|
||||
# define c3__brcs c3_s4('b','r','c','s')
|
||||
# define c3__brdg c3_s4('b','r','d','g')
|
||||
# define c3__brdl c3_s4('b','r','d','l')
|
||||
# define c3__brdp c3_s4('b','r','d','p')
|
||||
# define c3__brdt c3_s4('b','r','d','t')
|
||||
# define c3__brkt c3_s4('b','r','k','t')
|
||||
# define c3__brhp c3_s4('b','r','h','p')
|
||||
# define c3__brip c3_s4('b','r','i','p')
|
||||
# define c3__brcl c3_s4('b','r','c','l')
|
||||
# define c3__brkt c3_s4('b','r','k','t')
|
||||
# define c3__brlc c3_s4('b','r','l','c')
|
||||
# define c3__brld c3_s4('b','r','l','d')
|
||||
# define c3__brls c3_s4('b','r','l','s')
|
||||
@ -212,9 +212,9 @@
|
||||
# define c3__clkt c3_s4('c','l','k','t')
|
||||
# define c3__clls c3_s4('c','l','l','s')
|
||||
# define c3__clms c3_s4('c','l','m','s')
|
||||
# define c3__clr c3_s3('c','l','r')
|
||||
# define c3__clsg c3_s4('c','l','s','g')
|
||||
# define c3__clsp c3_s4('c','l','s','p')
|
||||
# define c3__clr c3_s3('c','l','r')
|
||||
# define c3__cltr c3_s4('c','l','t','r')
|
||||
# define c3__cnbc c3_s4('c','n','b','c')
|
||||
# define c3__cnbr c3_s4('c','n','b','r')
|
||||
@ -248,9 +248,9 @@
|
||||
# define c3__cook c3_s4('c','o','o','k')
|
||||
# define c3__cool c3_s4('c','o','o','l')
|
||||
# define c3__core c3_s4('c','o','r','e')
|
||||
# define c3__corp c3_s4('c','o','r','p')
|
||||
# define c3__corm c3_s4('c','o','r','m')
|
||||
# define c3__corp c3_s4('c','o','r','p')
|
||||
# define c3__corp c3_s4('c','o','r','p')
|
||||
# define c3__cow c3_s3('c','o','w')
|
||||
# define c3__cpu c3_s3('c','p','u')
|
||||
# define c3__crad c3_s4('c','r','a','d')
|
||||
@ -281,11 +281,11 @@
|
||||
# define c3__cstg c3_s4('c','s','t','g')
|
||||
# define c3__cstr c3_s4('c','s','t','r')
|
||||
# define c3__cszp c3_s4('c','s','z','p')
|
||||
# define c3__ctl c3_s3('c','t','l')
|
||||
# define c3__cttp c3_s4('c','t','t','p')
|
||||
# define c3__cube c3_s4('c','u','b','e')
|
||||
# define c3__cull c3_s4('c','u','l','l')
|
||||
# define c3__curd c3_s4('c','u','r','d')
|
||||
# define c3__ctl c3_s3('c','t','l')
|
||||
# define c3__cut c3_s3('c','u','t')
|
||||
# define c3__cyl c3_s3('c','y','l')
|
||||
# define c3__czar c3_s4('c','z','a','r')
|
||||
@ -365,13 +365,13 @@
|
||||
# define c3__dtwt c3_s4('d','t','w','t')
|
||||
# define c3__dtzy c3_s4('d','t','z','y')
|
||||
# define c3__dtzz c3_s4('d','t','z','z')
|
||||
# define c3__dxkt c3_s4('d','x','k','t')
|
||||
# define c3__dub c3_s3('d','u','b')
|
||||
# define c3__duct c3_s4('d','u','c','t')
|
||||
# define c3__duke c3_s4('d','u','k','e')
|
||||
# define c3__dumb c3_s4('d','u','m','b')
|
||||
# define c3__dump c3_s4('d','u','m','p')
|
||||
# define c3__dust c3_s4('d','u','s','t')
|
||||
# define c3__dxkt c3_s4('d','x','k','t')
|
||||
# define c3__e c3_s1('e')
|
||||
# define c3__earl c3_s4('e','a','r','l')
|
||||
# define c3__east c3_s4('e','a','s','t')
|
||||
@ -383,10 +383,10 @@
|
||||
# define c3__emph c3_s4('e','m','p','h')
|
||||
# define c3__end c3_s3('e','n','d')
|
||||
# define c3__eq c3_s2('e','q')
|
||||
# define c3__ex c3_s2('e','x')
|
||||
# define c3__esh c3_s3('e','s','h')
|
||||
# define c3__ergo c3_s4('e','r','g','o')
|
||||
# define c3__esh c3_s3('e','s','h')
|
||||
# define c3__etch c3_s4('e','t','c','h')
|
||||
# define c3__ex c3_s2('e','x')
|
||||
# define c3__exit c3_s4('e','x','i','t')
|
||||
# define c3__eyre c3_s4('e','y','r','e')
|
||||
# define c3__f c3_s1('f')
|
||||
@ -444,13 +444,13 @@
|
||||
# define c3__free c3_s4('f','r','e','e')
|
||||
# define c3__frez c3_s4('f','r','e','z')
|
||||
# define c3__frit c3_s4('f','r','i','t')
|
||||
# define c3__from c3_s4('f','r','o','m')
|
||||
# define c3__frog c3_s4('f','r','o','g')
|
||||
# define c3__from c3_s4('f','r','o','m')
|
||||
# define c3__fron c3_s4('f','r','o','n')
|
||||
# define c3__fry c3_s3('f','r','y')
|
||||
# define c3__fuge c3_s4('f','u','g','e')
|
||||
# define c3__fume c3_s4('f','u','m','e')
|
||||
# define c3__full c3_s4('f','u','l','l')
|
||||
# define c3__fume c3_s4('f','u','m','e')
|
||||
# define c3__fun c3_s3('f','u','n')
|
||||
# define c3__fund c3_s4('f','u','n','d')
|
||||
# define c3__fung c3_s4('f','u','n','g')
|
||||
@ -527,6 +527,7 @@
|
||||
# define c3__head c3_s4('h','e','a','d')
|
||||
# define c3__heal c3_s4('h','e','a','l')
|
||||
# define c3__hear c3_s4('h','e','a','r')
|
||||
# define c3__hela c3_s4('h','e','l','a')
|
||||
# define c3__helm c3_s4('h','e','l','m')
|
||||
# define c3__helo c3_s4('h','e','l','o')
|
||||
# define c3__help c3_s4('h','e','l','p')
|
||||
@ -544,8 +545,8 @@
|
||||
# define c3__hit c3_s3('h','i','t')
|
||||
# define c3__hmal c3_s4('h','m','a','l')
|
||||
# define c3__hold c3_s4('h','o','l','d')
|
||||
# define c3__holt c3_s4('h','o','l','t')
|
||||
# define c3__hole c3_s4('h','o','l','e')
|
||||
# define c3__holt c3_s4('h','o','l','t')
|
||||
# define c3__home c3_s4('h','o','m','e')
|
||||
# define c3__homp c3_s4('h','o','m','p')
|
||||
# define c3__hook c3_s4('h','o','o','k')
|
||||
@ -573,10 +574,10 @@
|
||||
# define c3__http c3_s4('h','t','t','p')
|
||||
# define c3__hume c3_s4('h','u','m','e')
|
||||
# define c3__hunk c3_s4('h','u','n','k')
|
||||
# define c3__hxtr c3_s4('h','x','t','r')
|
||||
# define c3__hxts c3_s4('h','x','t','s')
|
||||
# define c3__hxgl c3_s4('h','x','g','l')
|
||||
# define c3__hxgr c3_s4('h','x','g','r')
|
||||
# define c3__hxtr c3_s4('h','x','t','r')
|
||||
# define c3__hxts c3_s4('h','x','t','s')
|
||||
# define c3__i c3_s1('i')
|
||||
# define c3__ic c3_s2('i','c')
|
||||
# define c3__ice c3_s3('i','c','e')
|
||||
@ -706,8 +707,8 @@
|
||||
# define c3__lt c3_s2('l','t')
|
||||
# define c3__lull c3_s4('l','u','l','l')
|
||||
# define c3__lunt c3_s4('l','u','n','t')
|
||||
# define c3__mack c3_s4('m','a','c','k')
|
||||
# define c3__mach c3_s4('m','a','c','h')
|
||||
# define c3__mack c3_s4('m','a','c','k')
|
||||
# define c3__main c3_s4('m','a','i','n')
|
||||
# define c3__make c3_s4('m','a','k','e')
|
||||
# define c3__malg c3_s4('m','a','l','g')
|
||||
@ -717,9 +718,9 @@
|
||||
# define c3__map c3_s3('m','a','p')
|
||||
# define c3__marg c3_s4('m','a','r','g')
|
||||
# define c3__mark c3_s4('m','a','r','k')
|
||||
# define c3__mass c3_s4('m','a','s','s')
|
||||
# define c3__marn c3_s4('m','a','r','n')
|
||||
# define c3__mash c3_s4('m','a','s','h')
|
||||
# define c3__mass c3_s4('m','a','s','s')
|
||||
# define c3__mast c3_s4('m','a','s','t')
|
||||
# define c3__mate c3_s4('m','a','t','e')
|
||||
# define c3__mave c3_s4('m','a','v','e')
|
||||
@ -741,8 +742,8 @@
|
||||
# define c3__mirt c3_s4('m','i','r','t')
|
||||
# define c3__miss c3_s4('m','i','s','s')
|
||||
# define c3__mix c3_s3('m','i','x')
|
||||
# define c3__mod c3_s3('m','o','d')
|
||||
# define c3__moat c3_s4('m','o','a','t')
|
||||
# define c3__mod c3_s3('m','o','d')
|
||||
# define c3__mold c3_s4('m','o','l','d')
|
||||
# define c3__mong c3_s4('m','o','n','g')
|
||||
# define c3__mono c3_s4('m','o','n','o')
|
||||
@ -775,6 +776,7 @@
|
||||
# define c3__nail c3_s4('n','a','i','l')
|
||||
# define c3__name c3_s4('n','a','m','e')
|
||||
# define c3__nap c3_s3('n','a','p')
|
||||
# define c3__nara c3_s4('n','a','r','a')
|
||||
# define c3__narv c3_s4('n','a','r','v')
|
||||
# define c3__ne c3_s2('n','e')
|
||||
# define c3__need c3_s4('n','e','e','d')
|
||||
@ -793,8 +795,8 @@
|
||||
# define c3__noah c3_s4('n','o','a','h')
|
||||
# define c3__nock c3_s4('n','o','c','k')
|
||||
# define c3__none c3_s4('n','o','n','e')
|
||||
# define c3__nop c3_s3('n','o','p')
|
||||
# define c3__noop c3_s4('n','o','o','p')
|
||||
# define c3__nop c3_s3('n','o','p')
|
||||
# define c3__norm c3_s4('n','o','r','m')
|
||||
# define c3__nost c3_s4('n','o','s','t')
|
||||
# define c3__not c3_s3('n','o','t')
|
||||
@ -873,7 +875,6 @@
|
||||
# define c3__plet c3_s4('p','l','e','t')
|
||||
# define c3__plic c3_s4('p','l','i','c')
|
||||
# define c3__plin c3_s4('p','l','i','n')
|
||||
# define c3__plol c3_s4('p','l','o','m')
|
||||
# define c3__plom c3_s4('p','l','o','m')
|
||||
# define c3__plov c3_s4('p','l','o','v')
|
||||
# define c3__plug c3_s4('p','l','u','g')
|
||||
@ -943,14 +944,14 @@
|
||||
# define c3__ramp c3_s4('r','a','m','p')
|
||||
# define c3__rasp c3_s4('r','a','s','p')
|
||||
# define c3__raw c3_s3('r','a','w')
|
||||
# define c3__ret c3_s3('r','e','t')
|
||||
# define c3__rez c3_s3('r','e','z')
|
||||
# define c3__read c3_s4('r','e','a','d')
|
||||
# define c3__reck c3_s4('r','e','c','k')
|
||||
# define c3__reef c3_s4('r','e','e','f')
|
||||
# define c3__resd c3_s4('r','e','s','d')
|
||||
# define c3__rest c3_s4('r','e','s','t')
|
||||
# define c3__ret c3_s3('r','e','t')
|
||||
# define c3__revo c3_s4('r','e','v','o')
|
||||
# define c3__rez c3_s3('r','e','z')
|
||||
# define c3__rin c3_s3('r','i','n')
|
||||
# define c3__ring c3_s4('r','i','n','g')
|
||||
# define c3__ripe c3_s4('r','i','p','e')
|
||||
@ -1113,11 +1114,6 @@
|
||||
# define c3__term c3_s4('t','e','r','m')
|
||||
# define c3__test c3_s4('t','e','s','t')
|
||||
# define c3__text c3_s4('t','e','x','t')
|
||||
# define c3__that c3_s4('t','h','a','t')
|
||||
# define c3__this c3_s4('t','h','i','s')
|
||||
# define c3__thin c3_s4('t','h','i','n')
|
||||
# define c3__thud c3_s4('t','h','u','d')
|
||||
# define c3__time c3_s4('t','i','m','e')
|
||||
# define c3__tgbn c3_s4('t','g','b','n')
|
||||
# define c3__tgbr c3_s4('t','g','b','r')
|
||||
# define c3__tgdg c3_s4('t','g','d','g')
|
||||
@ -1132,13 +1128,18 @@
|
||||
# define c3__tgpm c3_s4('t','g','p','m')
|
||||
# define c3__tgps c3_s4('t','g','p','s')
|
||||
# define c3__tgsp c3_s4('t','g','s','p')
|
||||
# define c3__that c3_s4('t','h','a','t')
|
||||
# define c3__thee c3_s4('t','h','e','e')
|
||||
# define c3__then c3_s4('t','h','e','n')
|
||||
# define c3__they c3_s4('t','h','e','y')
|
||||
# define c3__tick c3_s4('t','i','c','k')
|
||||
# define c3__thin c3_s4('t','h','i','n')
|
||||
# define c3__this c3_s4('t','h','i','s')
|
||||
# define c3__thou c3_s4('t','h','o','u')
|
||||
# define c3__thud c3_s4('t','h','u','d')
|
||||
# define c3__thuo c3_s4('t','h','u','o')
|
||||
# define c3__thus c3_s4('t','h','u','s')
|
||||
# define c3__tick c3_s4('t','i','c','k')
|
||||
# define c3__time c3_s4('t','i','m','e')
|
||||
# define c3__tip c3_s3('t','i','p')
|
||||
# define c3__tmbn c3_s4('t','m','b','n')
|
||||
# define c3__tmdg c3_s4('t','m','d','g')
|
||||
@ -1217,8 +1218,8 @@
|
||||
# define c3__vamp c3_s4('v','a','m','p')
|
||||
# define c3__vane c3_s4('v','a','n','e')
|
||||
# define c3__var c3_s3('v','a','r')
|
||||
# define c3__veb c3_s3('v','e','b')
|
||||
# define c3__veal c3_s4('v','e','a','l')
|
||||
# define c3__veb c3_s3('v','e','b')
|
||||
# define c3__veck c3_s4('v','e','c','k')
|
||||
# define c3__veer c3_s4('v','e','e','r')
|
||||
# define c3__vega c3_s4('v','e','g','a')
|
||||
@ -1231,7 +1232,6 @@
|
||||
# define c3__vint c3_s4('v','i','n','t')
|
||||
# define c3__void c3_s4('v','o','i','d')
|
||||
# define c3__vorp c3_s4('v','o','r','p')
|
||||
# define c3__way c3_s3('w','a','y')
|
||||
# define c3__wack c3_s4('w','a','c','k')
|
||||
# define c3__wail c3_s4('w','a','i','l')
|
||||
# define c3__wake c3_s4('w','a','k','e')
|
||||
@ -1243,19 +1243,20 @@
|
||||
# define c3__warx c3_s4('w','a','r','x')
|
||||
# define c3__wash c3_s4('w','a','s','h')
|
||||
# define c3__watt c3_s4('w','a','t','t')
|
||||
# define c3__way c3_s3('w','a','y')
|
||||
# define c3__weak c3_s4('w','e','a','k')
|
||||
# define c3__web c3_s3('w','e','b')
|
||||
# define c3__wet c3_s3('w','e','t')
|
||||
# define c3__wend c3_s4('w','e','n','d')
|
||||
# define c3__werp c3_s4('w','e','r','p')
|
||||
# define c3__west c3_s4('w','e','s','t')
|
||||
# define c3__wet c3_s3('w','e','t')
|
||||
# define c3__what c3_s4('w','h','a','t')
|
||||
# define c3__whey c3_s4('w','h','e','y')
|
||||
# define c3__who c3_s3('w','h','o')
|
||||
# define c3__whom c3_s4('w','h','o','m')
|
||||
# define c3__wing c3_s4('w','i','n','g')
|
||||
# define c3__wild c3_s4('w','i','l','d')
|
||||
# define c3__win c3_s3('w','i','n')
|
||||
# define c3__wing c3_s4('w','i','n','g')
|
||||
# define c3__wipe c3_s4('w','i','p','e')
|
||||
# define c3__wise c3_s4('w','i','s','e')
|
||||
# define c3__wish c3_s4('w','i','s','h')
|
||||
@ -1285,10 +1286,9 @@
|
||||
# define c3__wtts c3_s4('w','t','t','s')
|
||||
# define c3__wtzp c3_s4('w','t','z','p')
|
||||
# define c3__wyrd c3_s4('w','y','r','d')
|
||||
# define c3__yew c3_s3('y','a','w')
|
||||
# define c3__yell c3_s4('y','e','l','l')
|
||||
# define c3__z c3_s1('z')
|
||||
# define c3__yelp c3_s4('y','e','l','p')
|
||||
# define c3__z c3_s1('z')
|
||||
# define c3__zact c3_s4('z','a','c','t')
|
||||
# define c3__zalt c3_s4('z','a','l','t')
|
||||
# define c3__zarb c3_s4('z','a','r','b')
|
||||
@ -1309,7 +1309,6 @@
|
||||
# define c3__zpdx c3_s4('z','p','d','x')
|
||||
# define c3__zpfs c3_s4('z','p','f','s')
|
||||
# define c3__zpgr c3_s4('z','p','g','r')
|
||||
# define c3__zphs c3_s4('z','p','h','x')
|
||||
# define c3__zphx c3_s4('z','p','h','x')
|
||||
# define c3__zplc c3_s4('z','p','l','c')
|
||||
# define c3__zpmc c3_s4('z','p','m','c')
|
||||
|
@ -127,12 +127,12 @@
|
||||
|
||||
/* u3i_string(): Produce an LSB-first atom from the C string [a].
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_string(const c3_c* a_c);
|
||||
|
||||
/* u3i_tape(): from a C string, to a list of bytes.
|
||||
*/
|
||||
u3_atom
|
||||
u3_noun
|
||||
u3i_tape(const c3_c* txt_c);
|
||||
|
||||
/* u3i_list(): list from `u3_none`-terminated varargs.
|
||||
|
@ -129,6 +129,30 @@
|
||||
void
|
||||
u3t_boot(void);
|
||||
|
||||
/* u3t_slog_cap(): slog a tank with a caption with
|
||||
** a given priority c3_l (assumed 0-3).
|
||||
*/
|
||||
void
|
||||
u3t_slog_cap(c3_l pri_l, u3_noun cap, u3_noun tan);
|
||||
|
||||
/* u3t_slog_trace(): given a c3_l priority pri and a raw stack tax
|
||||
** flop the order into start-to-end, render, and slog each item
|
||||
** until done.
|
||||
*/
|
||||
void
|
||||
u3t_slog_trace(c3_l pri_l, u3_noun tax);
|
||||
|
||||
/* u3t_slog_nara(): slog only the deepest road's trace with
|
||||
** c3_l priority pri
|
||||
*/
|
||||
void
|
||||
u3t_slog_nara(c3_l pri_l);
|
||||
|
||||
/* u3t_slog_hela(): join all roads' traces together into one tax
|
||||
** and pass it to slog_trace along with the given c3_l priority pri_l
|
||||
*/
|
||||
void
|
||||
u3t_slog_hela(c3_l pri_l);
|
||||
|
||||
/** Globals.
|
||||
**/
|
||||
|
@ -328,7 +328,7 @@
|
||||
void (*bot_f)(); // call when chis is up
|
||||
} u3_host; // host == computer == process
|
||||
|
||||
/** New pier system.
|
||||
/** Pier system.
|
||||
**/
|
||||
/* u3_ovum_news: u3_ovum lifecycle events
|
||||
*/
|
||||
@ -756,7 +756,7 @@
|
||||
c3_d
|
||||
u3_time_gap_ms(u3_noun now, u3_noun wen);
|
||||
|
||||
/** ward: common structure lifecycle
|
||||
/** Common structure lifecycle.
|
||||
**/
|
||||
/* u3_dent_init(): initialize file record.
|
||||
*/
|
||||
@ -841,7 +841,7 @@
|
||||
c3_w
|
||||
u3_mcut_host(c3_c* buf_c, c3_w len_w, u3_noun hot);
|
||||
|
||||
/** New vere
|
||||
/** IO drivers.
|
||||
**/
|
||||
/* u3_auto_init(): initialize all drivers.
|
||||
*/
|
||||
@ -1050,41 +1050,14 @@
|
||||
void
|
||||
u3_lord_peek(u3_lord* god_u, u3_pico* pic_u);
|
||||
|
||||
/** Filesystem (new api).
|
||||
**/
|
||||
/* u3_walk_load(): load file or bail.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk_load(c3_c* pas_c);
|
||||
|
||||
/* u3_walk_safe(): load file or 0.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk_safe(c3_c* pas_c);
|
||||
|
||||
/* u3_walk_save(): save file or bail.
|
||||
*/
|
||||
void
|
||||
u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax);
|
||||
|
||||
/* u3_walk(): traverse `dir_c` to produce an arch, updating `old`.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk(const c3_c* dir_c, u3_noun old);
|
||||
|
||||
/* u3_path(): C unix path in computer for file or directory.
|
||||
*/
|
||||
c3_c*
|
||||
u3_path(c3_o fyl, u3_noun pax);
|
||||
|
||||
/** Filesystem (async)
|
||||
/** Filesystem (async).
|
||||
**/
|
||||
/* u3_foil_folder(): load directory, blockingly. create if nonexistent.
|
||||
*/
|
||||
u3_dire*
|
||||
u3_foil_folder(const c3_c* pax_c); // directory object, or 0
|
||||
|
||||
/** Terminal, new style.
|
||||
/** Terminal.
|
||||
**/
|
||||
/* u3_term_start_spinner(): prepare spinner state. RETAIN.
|
||||
*/
|
||||
@ -1182,8 +1155,18 @@
|
||||
u3_save_io_exit(u3_pier *pir_u);
|
||||
|
||||
|
||||
/** Storage, new school.
|
||||
/** Storage.
|
||||
**/
|
||||
/* u3_unix_save(): save file undir .../.urb/put or bail.
|
||||
*/
|
||||
void
|
||||
u3_unix_save(c3_c* pax_c, u3_atom pad);
|
||||
|
||||
/* u3_unix_cane(): true iff (unix) path is canonical.
|
||||
*/
|
||||
c3_t
|
||||
u3_unix_cane(const c3_c* pax_c);
|
||||
|
||||
/* u3_unix_initial_into_card(): create initial filesystem sync card.
|
||||
*/
|
||||
u3_noun
|
||||
@ -1222,14 +1205,14 @@
|
||||
u3_auto*
|
||||
u3_conn_io_init(u3_pier* pir_u);
|
||||
|
||||
/** fore, first events
|
||||
/** fore, first events.
|
||||
**/
|
||||
/* u3_hind_io_init(): initialize fore
|
||||
*/
|
||||
u3_auto*
|
||||
u3_fore_io_init(u3_pier* pir_u);
|
||||
|
||||
/** hind, defaults
|
||||
/** hind, defaults.
|
||||
**/
|
||||
/* u3_hind_io_init(): initialize hint
|
||||
*/
|
||||
@ -1342,7 +1325,7 @@
|
||||
void
|
||||
u3_pier_slog(u3_pier* pir_u);
|
||||
|
||||
/* u3_pier_boot(): start the new pier system.
|
||||
/* u3_pier_boot(): start the pier.
|
||||
*/
|
||||
u3_pier*
|
||||
u3_pier_boot(c3_w wag_w, // config flags
|
||||
@ -1352,7 +1335,7 @@
|
||||
u3_noun pax, // path to pier
|
||||
u3_weak fed); // extra private keys
|
||||
|
||||
/* u3_pier_stay(): restart the new pier system.
|
||||
/* u3_pier_stay(): restart the pier.
|
||||
*/
|
||||
u3_pier*
|
||||
u3_pier_stay(c3_w wag_w, u3_noun pax);
|
||||
|
@ -31,20 +31,17 @@ u3_noun get_syllable(c3_c** cur_ptr, c3_c* one, c3_c* two, c3_c* three) {
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
u3_noun combine(u3_noun p, u3_noun q)
|
||||
static u3_noun
|
||||
combine(u3_noun p, u3_noun q)
|
||||
{
|
||||
if (_(u3a_is_atom(p))) {
|
||||
if ( (c3y == u3a_is_atom(p)) || (c3y == u3a_is_atom(q)) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_(u3a_is_atom(q))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u3_noun ret = u3nc(0, u3qa_add(u3t(p), u3qa_mul(256, u3t(q))));
|
||||
u3z(p);
|
||||
u3z(q);
|
||||
u3_noun lef = u3qa_mul(256, u3t(q));
|
||||
u3_noun ret = u3nc(0, u3qa_add(u3t(p), lef));
|
||||
u3z(lef);
|
||||
u3z(p); u3z(q);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -239,17 +239,17 @@ _ce_image_open(u3e_image* img_u)
|
||||
c3_c ful_c[8193];
|
||||
|
||||
snprintf(ful_c, 8192, "%s", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c);
|
||||
if ( -1 == (img_u->fid_i = open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno));
|
||||
if ( -1 == (img_u->fid_i = c3_open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno));
|
||||
return c3n;
|
||||
}
|
||||
else {
|
||||
@ -333,20 +333,20 @@ _ce_patch_create(u3_ce_patch* pat_u)
|
||||
c3_c ful_c[8193];
|
||||
|
||||
snprintf(ful_c, 8192, "%s", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
|
||||
if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
|
||||
fprintf(stderr, "loom: patch open control.bin: %s\r\n", strerror(errno));
|
||||
if ( -1 == (pat_u->ctl_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
|
||||
fprintf(stderr, "loom: patch c3_open control.bin: %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
|
||||
if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
|
||||
fprintf(stderr, "loom: patch open memory.bin: %s\r\n", strerror(errno));
|
||||
if ( -1 == (pat_u->mem_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
|
||||
fprintf(stderr, "loom: patch c3_open memory.bin: %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
}
|
||||
@ -359,10 +359,10 @@ _ce_patch_delete(void)
|
||||
c3_c ful_c[8193];
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
|
||||
unlink(ful_c);
|
||||
c3_unlink(ful_c);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
|
||||
unlink(ful_c);
|
||||
c3_unlink(ful_c);
|
||||
}
|
||||
|
||||
/* _ce_patch_verify(): check patch data mug.
|
||||
@ -431,18 +431,18 @@ _ce_patch_open(void)
|
||||
c3_i ctl_i, mem_i;
|
||||
|
||||
snprintf(ful_c, 8192, "%s", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
|
||||
mkdir(ful_c, 0700);
|
||||
c3_mkdir(ful_c, 0700);
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
|
||||
if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) {
|
||||
if ( -1 == (ctl_i = c3_open(ful_c, O_RDWR)) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
|
||||
if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) {
|
||||
if ( -1 == (mem_i = c3_open(ful_c, O_RDWR)) ) {
|
||||
close(ctl_i);
|
||||
|
||||
_ce_patch_delete();
|
||||
@ -838,7 +838,7 @@ _ce_backup(void)
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c);
|
||||
|
||||
if ( mkdir(ful_c, 0700) ) {
|
||||
if ( c3_mkdir(ful_c, 0700) ) {
|
||||
if ( EEXIST != errno ) {
|
||||
fprintf(stderr, "loom: image backup: %s\r\n", strerror(errno));
|
||||
}
|
||||
@ -847,15 +847,15 @@ _ce_backup(void)
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c);
|
||||
|
||||
if ( -1 == (nop_u.fid_i = open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno));
|
||||
if ( -1 == (nop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, sop_u.nam_c);
|
||||
|
||||
if ( -1 == (sop_u.fid_i = open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno));
|
||||
if ( -1 == (sop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) {
|
||||
fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -863,11 +863,11 @@ _ce_backup(void)
|
||||
|| (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) )
|
||||
{
|
||||
|
||||
unlink(ful_c);
|
||||
c3_unlink(ful_c);
|
||||
snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c);
|
||||
unlink(ful_c);
|
||||
c3_unlink(ful_c);
|
||||
snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c);
|
||||
rmdir(ful_c);
|
||||
c3_rmdir(ful_c);
|
||||
}
|
||||
|
||||
close(nop_u.fid_i);
|
||||
|
@ -541,7 +541,7 @@ u3i_qual(u3_noun a, u3_noun b, u3_noun c, u3_noun d)
|
||||
|
||||
/* u3i_string(): Produce an LSB-first atom from the C string [a].
|
||||
*/
|
||||
u3_noun
|
||||
u3_atom
|
||||
u3i_string(const c3_c* a_c)
|
||||
{
|
||||
return u3i_bytes(strlen(a_c), (c3_y *)a_c);
|
||||
@ -549,7 +549,7 @@ u3i_string(const c3_c* a_c)
|
||||
|
||||
/* u3i_tape(): from a C string, to a list of bytes.
|
||||
*/
|
||||
u3_atom
|
||||
u3_noun
|
||||
u3i_tape(const c3_c* txt_c)
|
||||
{
|
||||
if ( !*txt_c ) {
|
||||
|
@ -432,7 +432,7 @@ u3_noun
|
||||
u3m_file(c3_c* pas_c)
|
||||
{
|
||||
struct stat buf_b;
|
||||
c3_i fid_i = open(pas_c, O_RDONLY, 0644);
|
||||
c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644);
|
||||
c3_w fln_w, red_w;
|
||||
c3_y* pad_y;
|
||||
|
||||
|
@ -453,7 +453,7 @@ _n_nock_on(u3_noun bus, u3_noun fol)
|
||||
#define KICS 54
|
||||
#define TICB 55
|
||||
#define TICS 56
|
||||
// nock 11
|
||||
// nock 12
|
||||
#define WILS 57
|
||||
#define WISH 58
|
||||
// hint processing
|
||||
@ -1020,7 +1020,8 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
|
||||
default: {
|
||||
return _n_comp(ops, nef, los_o, tel_o);
|
||||
}
|
||||
|
||||
case c3__nara:
|
||||
case c3__hela:
|
||||
case c3__bout: {
|
||||
u3_noun fen = u3_nul;
|
||||
c3_w nef_w = _n_comp(&fen, nef, los_o, c3n);
|
||||
@ -1055,7 +1056,8 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
|
||||
++tot_w; _n_emit(ops, TOSS);
|
||||
tot_w += _n_comp(ops, nef, los_o, tel_o);
|
||||
} break;
|
||||
|
||||
case c3__nara:
|
||||
case c3__hela:
|
||||
case c3__bout: {
|
||||
u3_noun fen = u3_nul;
|
||||
c3_w nef_w = _n_comp(&fen, nef, los_o, c3n);
|
||||
@ -1696,12 +1698,28 @@ u3n_find(u3_noun key, u3_noun fol)
|
||||
static c3_o
|
||||
_n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out)
|
||||
{
|
||||
if ( c3__bout == u3h(hin) ) {
|
||||
u3_atom now = u3i_chub(u3t_trace_time());
|
||||
*out = u3i_cell(u3h(hin), now);
|
||||
}
|
||||
else {
|
||||
*out = u3_nul;
|
||||
u3_noun tag, fol;
|
||||
u3x_cell(hin, &tag, &fol);
|
||||
|
||||
switch ( tag ) {
|
||||
case c3__bout: {
|
||||
u3_atom now = u3i_chub(u3t_trace_time());
|
||||
*out = u3i_cell(tag, now);
|
||||
} break;
|
||||
|
||||
case c3__nara : {
|
||||
u3t_slog_nara(0);
|
||||
*out = u3_nul;
|
||||
} break;
|
||||
|
||||
case c3__hela : {
|
||||
u3t_slog_hela(0);
|
||||
*out = u3_nul;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
*out = u3_nul;
|
||||
} break;
|
||||
}
|
||||
|
||||
u3z(hin);
|
||||
@ -1742,13 +1760,41 @@ _n_hilt_hind(u3_noun tok, u3_noun pro)
|
||||
static c3_o
|
||||
_n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu)
|
||||
{
|
||||
if ( c3__bout == u3h(hin) ) {
|
||||
u3_atom now = u3i_chub(u3t_trace_time());
|
||||
*clu = u3i_trel(u3h(hin), *clu, now);
|
||||
}
|
||||
else {
|
||||
u3z(*clu);
|
||||
*clu = u3_nul;
|
||||
u3_noun tag, fol;
|
||||
u3x_cell(hin, &tag, &fol);
|
||||
|
||||
switch ( tag ) {
|
||||
case c3__bout: {
|
||||
u3_atom now = u3i_chub(u3t_trace_time());
|
||||
*clu = u3nt(u3k(tag), *clu, now);
|
||||
} break;
|
||||
|
||||
case c3__nara: {
|
||||
u3_noun pri, tan;
|
||||
if ( c3y == u3r_cell(*clu, &pri, &tan) ) {
|
||||
c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0;
|
||||
u3t_slog_cap(pri_l, u3i_string("trace of"), u3k(tan));
|
||||
u3t_slog_nara(pri_l);
|
||||
}
|
||||
u3z(*clu);
|
||||
*clu = u3_nul;
|
||||
} break;
|
||||
|
||||
case c3__hela: {
|
||||
u3_noun pri, tan;
|
||||
if ( c3y == u3r_cell(*clu, &pri, &tan) ) {
|
||||
c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0;
|
||||
u3t_slog_cap(pri_l, u3i_string("trace of"), u3k(tan));
|
||||
u3t_slog_hela(pri_l);
|
||||
}
|
||||
u3z(*clu);
|
||||
*clu = u3_nul;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
u3z(*clu);
|
||||
*clu = u3_nul;
|
||||
} break;
|
||||
}
|
||||
|
||||
u3z(hin);
|
||||
@ -1763,9 +1809,7 @@ static void
|
||||
_n_hint_hind(u3_noun tok, u3_noun pro)
|
||||
{
|
||||
u3_noun p_tok, q_tok, r_tok;
|
||||
if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok))
|
||||
&& (c3__bout == p_tok) )
|
||||
{
|
||||
if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok)) && (c3__bout == p_tok) ) {
|
||||
// get the microseconds elapsed
|
||||
u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok));
|
||||
|
||||
@ -1782,17 +1826,8 @@ _n_hint_hind(u3_noun tok, u3_noun pro)
|
||||
// "q_q_tok: report"
|
||||
// prepend the priority to form a cell of the same shape q_tok
|
||||
// send this to ut3_slog so that it can be logged out
|
||||
u3t_slog(
|
||||
u3nc(
|
||||
u3k(p_q_tok),
|
||||
u3nt(
|
||||
c3__rose,
|
||||
u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul),
|
||||
u3nt(u3k(q_q_tok), u3i_string(str_c), u3_nul)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
c3_l pri_l = c3y == u3a_is_cat(p_q_tok) ? p_q_tok : 0;
|
||||
u3t_slog_cap(pri_l, u3k(q_q_tok), u3i_string(str_c));
|
||||
u3z(delta);
|
||||
}
|
||||
else {
|
||||
|
@ -282,13 +282,13 @@ u3t_trace_open(c3_c* dir_c)
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(fil_c, &st) ) {
|
||||
mkdir(fil_c, 0700);
|
||||
c3_mkdir(fil_c, 0700);
|
||||
}
|
||||
|
||||
c3_c lif_c[2056];
|
||||
snprintf(lif_c, 2056, "%s/%d.json", fil_c, u3_Host.tra_u.fun_w);
|
||||
|
||||
u3_Host.tra_u.fil_u = fopen(lif_c, "w");
|
||||
u3_Host.tra_u.fil_u = c3_fopen(lif_c, "w");
|
||||
u3_Host.tra_u.nid_w = (int)getpid();
|
||||
|
||||
fprintf(u3_Host.tra_u.fil_u, "[ ");
|
||||
@ -589,3 +589,87 @@ u3t_boff(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* u3t_slog_cap(): slog a tank with a caption with
|
||||
** a given priority c3_l (assumed 0-3).
|
||||
*/
|
||||
void
|
||||
u3t_slog_cap(c3_l pri_l, u3_noun cap, u3_noun tan)
|
||||
{
|
||||
u3t_slog(
|
||||
u3nc(
|
||||
pri_l,
|
||||
u3nt(
|
||||
c3__rose,
|
||||
u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul),
|
||||
u3nt(cap, tan, u3_nul)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* u3t_slog_trace(): given a c3_l priority pri and a raw stack tax
|
||||
** flop the order into start-to-end, render, and slog each item
|
||||
** until done.
|
||||
*/
|
||||
void
|
||||
u3t_slog_trace(c3_l pri_l, u3_noun tax)
|
||||
{
|
||||
// render the stack
|
||||
// Note: ton is a reference to a data struct
|
||||
// we have just allocated
|
||||
// lit is a used as a moving cursor pointer through
|
||||
// that allocated struct
|
||||
// once we finish lit will be null, but ton will still
|
||||
// point to the whole valid allocated data structure
|
||||
// and thus we can free it safely at the end of the func
|
||||
// to clean up after ourselves.
|
||||
// Note: flop reverses the stack trace list 'tax'
|
||||
u3_noun ton = u3dc("mook", 2, u3kb_flop(tax));
|
||||
u3_noun lit = u3t(ton);
|
||||
|
||||
// print the stack one stack item at a time
|
||||
while ( u3_nul != lit ) {
|
||||
u3t_slog(u3nc(pri_l, u3k(u3h(lit)) ));
|
||||
lit = u3t(lit);
|
||||
}
|
||||
|
||||
u3z(ton);
|
||||
}
|
||||
|
||||
|
||||
/* u3t_slog_nara(): slog only the deepest road's trace with
|
||||
** c3_l priority pri
|
||||
*/
|
||||
void
|
||||
u3t_slog_nara(c3_l pri_l)
|
||||
{
|
||||
u3_noun tax = u3k(u3R->bug.tax);
|
||||
u3t_slog_trace(pri_l, tax);
|
||||
}
|
||||
|
||||
|
||||
/* u3t_slog_hela(): join all roads' traces together into one tax
|
||||
** and pass it to slog_trace along with the given c3_l priority pri_l
|
||||
*/
|
||||
void
|
||||
u3t_slog_hela(c3_l pri_l)
|
||||
{
|
||||
// rod_u protects us from mutating the global state
|
||||
u3_road* rod_u = u3R;
|
||||
|
||||
// inits to the the current road's trace
|
||||
u3_noun tax = u3k(rod_u->bug.tax);
|
||||
|
||||
// while there is a parent road ref ...
|
||||
while ( &(u3H->rod_u) != rod_u ) {
|
||||
// ... point at the next road and append its stack to tax
|
||||
rod_u = u3tn(u3_road, rod_u->par_p);
|
||||
tax = u3kb_weld(tax, u3k(rod_u->bug.tax));
|
||||
}
|
||||
|
||||
u3t_slog_trace(pri_l, tax);
|
||||
}
|
||||
|
||||
|
@ -509,7 +509,7 @@ _cu_rock_path_make(c3_c* dir_c, c3_d eve_d, c3_c** out_c)
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( mkdir(nam_c, 0700)
|
||||
if ( c3_mkdir(nam_c, 0700)
|
||||
&& (EEXIST != errno) )
|
||||
{
|
||||
fprintf(stderr, "rock: directory create failed (%s, %" PRIu64 "): %s\r\n",
|
||||
@ -552,8 +552,8 @@ _cu_rock_save(c3_c* dir_c, c3_d eve_d, c3_d len_d, c3_y* byt_y)
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( -1 == (fid_i = open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) {
|
||||
fprintf(stderr, "rock: open failed (%s, %" PRIu64 "): %s\r\n",
|
||||
if ( -1 == (fid_i = c3_open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) {
|
||||
fprintf(stderr, "rock: c3_open failed (%s, %" PRIu64 "): %s\r\n",
|
||||
dir_c, eve_d, strerror(errno));
|
||||
c3_free(nam_c);
|
||||
return c3n;
|
||||
@ -691,8 +691,8 @@ u3u_mmap_read(c3_c* cap_c, c3_c* pat_c, c3_d* out_d, c3_y** out_y)
|
||||
|
||||
// open file
|
||||
//
|
||||
if ( -1 == (fid_i = open(pat_c, O_RDONLY, 0644)) ) {
|
||||
fprintf(stderr, "%s: open failed (%s): %s\r\n",
|
||||
if ( -1 == (fid_i = c3_open(pat_c, O_RDONLY, 0644)) ) {
|
||||
fprintf(stderr, "%s: c3_open failed (%s): %s\r\n",
|
||||
cap_c, pat_c, strerror(errno));
|
||||
return c3n;
|
||||
}
|
||||
@ -744,8 +744,8 @@ u3u_mmap(c3_c* cap_c, c3_c* pat_c, c3_d len_d, c3_y** out_y)
|
||||
|
||||
// open file
|
||||
//
|
||||
if ( -1 == (fid_i = open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) {
|
||||
fprintf(stderr, "%s: open failed (%s): %s\r\n",
|
||||
if ( -1 == (fid_i = c3_open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) {
|
||||
fprintf(stderr, "%s: c3_open failed (%s): %s\r\n",
|
||||
cap_c, pat_c, strerror(errno));
|
||||
return c3n;
|
||||
}
|
||||
@ -895,7 +895,7 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d)
|
||||
|
||||
// leave rocks on disk
|
||||
//
|
||||
// if ( 0 != unlink(nam_c) ) {
|
||||
// if ( 0 != c3_unlink(nam_c) ) {
|
||||
// fprintf(stderr, "uncram: failed to delete rock (%s, %" PRIu64 "): %s\r\n",
|
||||
// dir_c, eve_d, strerror(errno));
|
||||
// c3_free(nam_c);
|
||||
|
65
pkg/urbit/tests/unix_tests.c
Normal file
65
pkg/urbit/tests/unix_tests.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include "all.h"
|
||||
#include "vere/vere.h"
|
||||
|
||||
/* _setup(): prepare for tests.
|
||||
*/
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* _test_safe():
|
||||
*/
|
||||
static c3_i
|
||||
_test_safe()
|
||||
{
|
||||
c3_i ret_i = 1;
|
||||
|
||||
if ( !u3_unix_cane("/") ||
|
||||
!u3_unix_cane("~.") ||
|
||||
!u3_unix_cane("a") ||
|
||||
!u3_unix_cane("a/b") ||
|
||||
!u3_unix_cane("a/b/c/defg/h/ijklmnop") )
|
||||
{
|
||||
fprintf(stderr, "_safe fail 1\n");
|
||||
ret_i = 0;
|
||||
}
|
||||
|
||||
if ( u3_unix_cane("") ||
|
||||
u3_unix_cane(".") ||
|
||||
u3_unix_cane("..") ||
|
||||
u3_unix_cane("/.") ||
|
||||
u3_unix_cane("a/b/c//") ||
|
||||
u3_unix_cane("a/b/.") ||
|
||||
u3_unix_cane("/././../.") ||
|
||||
u3_unix_cane("/../etc") )
|
||||
{
|
||||
fprintf(stderr, "_safe fail 2\r\n");
|
||||
ret_i = 0;
|
||||
}
|
||||
|
||||
if ( !u3_unix_cane(".a") ||
|
||||
!u3_unix_cane("/.a.b.c/..c") )
|
||||
{
|
||||
fprintf(stderr, "_safe fail 3\r\n");
|
||||
ret_i = 0;
|
||||
}
|
||||
|
||||
return ret_i;
|
||||
}
|
||||
|
||||
/* main(): run all test cases.
|
||||
*/
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
_setup();
|
||||
|
||||
if ( !_test_safe() ) {
|
||||
fprintf(stderr, "test unix: failed\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "test unix: ok\r\n");
|
||||
return 0;
|
||||
}
|
@ -462,7 +462,7 @@ _dawn_come(u3_noun stars)
|
||||
c3_c pat_c[64];
|
||||
snprintf(pat_c, 64, "%s.key", who_c + 1);
|
||||
|
||||
FILE* fil_u = fopen(pat_c, "w");
|
||||
FILE* fil_u = c3_fopen(pat_c, "w");
|
||||
fprintf(fil_u, "%s\n", key_c);
|
||||
fclose(fil_u);
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ u3_lmdb_init(const c3_c* pax_c, size_t siz_i)
|
||||
MDB_env* env_u;
|
||||
c3_w ret_w;
|
||||
|
||||
c3_assert(u3_unix_cane(pax_c));
|
||||
|
||||
if ( (ret_w = mdb_env_create(&env_u)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: init fail");
|
||||
return 0;
|
||||
|
@ -585,6 +585,94 @@ u3_disk_read_meta(u3_disk* log_u,
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* _disk_lock(): lockfile path.
|
||||
*/
|
||||
static c3_c*
|
||||
_disk_lock(c3_c* pax_c)
|
||||
{
|
||||
c3_w len_w = strlen(pax_c) + sizeof("/.vere.lock");
|
||||
c3_c* paf_c = c3_malloc(len_w);
|
||||
c3_i wit_i;
|
||||
|
||||
wit_i = snprintf(paf_c, len_w, "%s/.vere.lock", pax_c);
|
||||
c3_assert(wit_i + 1 == len_w);
|
||||
return paf_c;
|
||||
}
|
||||
|
||||
/* u3_disk_acquire(): acquire a lockfile, killing anything that holds it.
|
||||
*/
|
||||
static void
|
||||
u3_disk_acquire(c3_c* pax_c)
|
||||
{
|
||||
c3_c* paf_c = _disk_lock(pax_c);
|
||||
c3_w pid_w;
|
||||
FILE* loq_u;
|
||||
|
||||
if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) {
|
||||
if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) {
|
||||
u3l_log("lockfile %s is corrupt!\n", paf_c);
|
||||
kill(getpid(), SIGTERM);
|
||||
sleep(1); c3_assert(0);
|
||||
}
|
||||
else if (pid_w != getpid()) {
|
||||
c3_w i_w;
|
||||
|
||||
if ( -1 != kill(pid_w, SIGTERM) ) {
|
||||
u3l_log("disk: stopping process %d, live in %s...\n",
|
||||
pid_w, pax_c);
|
||||
|
||||
for ( i_w = 0; i_w < 16; i_w++ ) {
|
||||
sleep(1);
|
||||
if ( -1 == kill(pid_w, SIGTERM) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( 16 == i_w ) {
|
||||
for ( i_w = 0; i_w < 16; i_w++ ) {
|
||||
if ( -1 == kill(pid_w, SIGKILL) ) {
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
if ( 16 == i_w ) {
|
||||
u3l_log("disk: process %d seems unkillable!\n", pid_w);
|
||||
c3_assert(0);
|
||||
}
|
||||
u3l_log("disk: stopped old process %u\n", pid_w);
|
||||
}
|
||||
}
|
||||
fclose(loq_u);
|
||||
c3_unlink(paf_c);
|
||||
}
|
||||
|
||||
if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) {
|
||||
u3l_log("disk: unable to open %s\n", paf_c);
|
||||
c3_assert(0);
|
||||
}
|
||||
|
||||
fprintf(loq_u, "%u\n", getpid());
|
||||
|
||||
{
|
||||
c3_i fid_i = fileno(loq_u);
|
||||
c3_sync(fid_i);
|
||||
}
|
||||
|
||||
fclose(loq_u);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
/* u3_disk_release(): release a lockfile.
|
||||
*/
|
||||
static void
|
||||
u3_disk_release(c3_c* pax_c)
|
||||
{
|
||||
c3_c* paf_c = _disk_lock(pax_c);
|
||||
|
||||
c3_unlink(paf_c);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
/* u3_disk_exit(): close the log.
|
||||
*/
|
||||
void
|
||||
@ -633,6 +721,8 @@ u3_disk_exit(u3_disk* log_u)
|
||||
}
|
||||
}
|
||||
|
||||
u3_disk_release(log_u->dir_u->pax_c);
|
||||
|
||||
u3_dire_free(log_u->dir_u);
|
||||
u3_dire_free(log_u->urb_u);
|
||||
u3_dire_free(log_u->com_u);
|
||||
@ -734,6 +824,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u)
|
||||
}
|
||||
}
|
||||
|
||||
// acquire lockfile.
|
||||
//
|
||||
u3_disk_acquire(pax_c);
|
||||
|
||||
// create/load $pier/.urb
|
||||
//
|
||||
{
|
||||
@ -758,11 +852,11 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u)
|
||||
|
||||
strcpy(dir_c, pax_c);
|
||||
strcat(dir_c, "/.urb/put");
|
||||
mkdir(dir_c, 0700);
|
||||
c3_mkdir(dir_c, 0700);
|
||||
|
||||
strcpy(dir_c, pax_c);
|
||||
strcat(dir_c, "/.urb/get");
|
||||
mkdir(dir_c, 0700);
|
||||
c3_mkdir(dir_c, 0700);
|
||||
|
||||
c3_free(dir_c);
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ u3_foil_folder(const c3_c* pax_c)
|
||||
uv_dirent_t den_u;
|
||||
c3_i err_i;
|
||||
|
||||
c3_assert(u3_unix_cane(pax_c));
|
||||
|
||||
/* open directory, synchronously
|
||||
*/
|
||||
{
|
||||
|
@ -1608,7 +1608,7 @@ _http_write_ports_file(u3_httd* htd_u, c3_c *pax_c)
|
||||
c3_c* paf_c = c3_malloc(len_w);
|
||||
snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c);
|
||||
|
||||
c3_i por_i = open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_i por_i = c3_open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_free(paf_c);
|
||||
|
||||
u3_http* htp_u = htd_u->htp_u;
|
||||
@ -1651,7 +1651,7 @@ _http_release_ports_file(c3_c *pax_c)
|
||||
c3_assert(wit_i > 0);
|
||||
c3_assert(len_w == (c3_w)wit_i + 1);
|
||||
|
||||
unlink(paf_c);
|
||||
c3_unlink(paf_c);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
|
@ -549,14 +549,13 @@ _term_it_show_more(u3_utty* uty_u)
|
||||
/* _term_it_path(): path for console file.
|
||||
*/
|
||||
static c3_c*
|
||||
_term_it_path(c3_o fyl, u3_noun pax)
|
||||
_term_it_path(u3_noun pax)
|
||||
{
|
||||
c3_w len_w;
|
||||
c3_w len_w = 0;
|
||||
c3_c *pas_c;
|
||||
|
||||
// measure
|
||||
//
|
||||
len_w = strlen(u3_Host.dir_c);
|
||||
{
|
||||
u3_noun wiz = pax;
|
||||
|
||||
@ -569,7 +568,6 @@ _term_it_path(c3_o fyl, u3_noun pax)
|
||||
// cut
|
||||
//
|
||||
pas_c = c3_malloc(len_w + 1);
|
||||
strncpy(pas_c, u3_Host.dir_c, len_w);
|
||||
pas_c[len_w] = '\0';
|
||||
{
|
||||
u3_noun wiz = pax;
|
||||
@ -578,7 +576,7 @@ _term_it_path(c3_o fyl, u3_noun pax)
|
||||
while ( u3_nul != wiz ) {
|
||||
c3_w tis_w = u3r_met(3, u3h(wiz));
|
||||
|
||||
if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) {
|
||||
if ( (u3_nul == u3t(wiz)) ) {
|
||||
*waq_c++ = '.';
|
||||
} else *waq_c++ = '/';
|
||||
|
||||
@ -598,27 +596,10 @@ _term_it_path(c3_o fyl, u3_noun pax)
|
||||
static void
|
||||
_term_it_save(u3_noun pax, u3_noun pad)
|
||||
{
|
||||
c3_c* pax_c;
|
||||
c3_c* bas_c = 0;
|
||||
c3_w xap_w = u3kb_lent(u3k(pax));
|
||||
u3_noun xap = u3_nul;
|
||||
u3_noun urb = c3_s4('.','u','r','b');
|
||||
u3_noun put = c3_s3('p','u','t');
|
||||
|
||||
// directory base and relative path
|
||||
if ( 2 < xap_w ) {
|
||||
u3_noun bas = u3nt(urb, put, u3_nul);
|
||||
bas_c = _term_it_path(c3n, bas);
|
||||
xap = u3qb_scag(xap_w - 2, pax);
|
||||
}
|
||||
|
||||
pax = u3nt(urb, put, pax);
|
||||
pax_c = _term_it_path(c3y, pax);
|
||||
|
||||
u3_walk_save(pax_c, 0, pad, bas_c, xap);
|
||||
c3_c* pax_c = _term_it_path(pax);
|
||||
|
||||
u3_unix_save(pax_c, pad);
|
||||
c3_free(pax_c);
|
||||
c3_free(bas_c);
|
||||
}
|
||||
|
||||
/* _term_ovum_plan(): plan term ovums, configuring spinner.
|
||||
|
@ -1,5 +1,36 @@
|
||||
/* vere/unix.c
|
||||
**
|
||||
** this file is responsible for maintaining a bidirectional
|
||||
** mapping between the contents of a clay desk and a directory
|
||||
** in a unix filesystem.
|
||||
**
|
||||
** TODO this driver is crufty and overdue for a rewrite.
|
||||
** aspirationally, the rewrite should do sanity checking and
|
||||
** transformations at the noun level to convert messages from
|
||||
** arvo into sets of fs operations on trusted inputs, and
|
||||
** inverse transformations and checks for fs contents to arvo
|
||||
** messages.
|
||||
**
|
||||
** the two relevant transformations to apply are:
|
||||
**
|
||||
** 1. bidirectionally map file contents to atoms
|
||||
** 2. bidirectionally map arvo $path <-> unix relative paths
|
||||
**
|
||||
** the first transform is trivial. the second poses some
|
||||
** challenges: an arvo $path is a list of $knot, and the $knot
|
||||
** space intersects with invalid unix paths in the three cases
|
||||
** of: %$ (the empty knot), '.', and '..'. we escape these by
|
||||
** prepending a '!' to the filename corresponding to the $knot,
|
||||
** yielding unix files named '!', '!.', and '!..'.
|
||||
**
|
||||
** there is also the case of the empty path. we elide empty
|
||||
** paths from this wrapper, which always uses the last path
|
||||
** component as the file extension/mime-type.
|
||||
**
|
||||
** these transforms are implemented, but they ought to be
|
||||
** implemented in one place, prior to any fs calls; as-is, they
|
||||
** are sprinkled throughout the file updating code.
|
||||
**
|
||||
*/
|
||||
#include "all.h"
|
||||
#include <ftw.h>
|
||||
@ -58,6 +89,7 @@ struct _u3_ufil;
|
||||
c3_c* pax_c; // pier directory
|
||||
c3_o alm; // timer set
|
||||
c3_o dyr; // ready to update
|
||||
u3_noun sat; // (sane %ta) handle
|
||||
#ifdef SYNCLOG
|
||||
c3_w lot_w; // sync-slot
|
||||
struct _u3_sylo {
|
||||
@ -72,6 +104,50 @@ struct _u3_ufil;
|
||||
void
|
||||
u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all);
|
||||
|
||||
/* u3_unix_cane(): true iff (unix) path is canonical.
|
||||
*/
|
||||
c3_t
|
||||
u3_unix_cane(const c3_c* pax_c)
|
||||
{
|
||||
if ( 0 == pax_c ) {
|
||||
return 0;
|
||||
}
|
||||
// allow absolute paths.
|
||||
//
|
||||
if ( '/' == *pax_c ) {
|
||||
pax_c++;
|
||||
// allow root.
|
||||
//
|
||||
if ( 0 == *pax_c ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
do {
|
||||
if ( 0 == *pax_c
|
||||
|| 0 == strcmp(".", pax_c)
|
||||
|| 0 == strcmp("..", pax_c)
|
||||
|| 0 == strncmp("/", pax_c, 1)
|
||||
|| 0 == strncmp("./", pax_c, 2)
|
||||
|| 0 == strncmp("../", pax_c, 3) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
pax_c = strchr(pax_c, '/');
|
||||
} while ( 0 != pax_c++ );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* _unix_sane_ta(): true iff pat is a valid @ta
|
||||
**
|
||||
** %ta is parsed by:
|
||||
** (star ;~(pose nud low hep dot sig cab))
|
||||
*/
|
||||
static c3_t
|
||||
_unix_sane_ta(u3_unix* unx_u, u3_atom pat)
|
||||
{
|
||||
return _(u3n_slam_on(u3k(unx_u->sat), pat));
|
||||
}
|
||||
|
||||
/* u3_readdir_r():
|
||||
*/
|
||||
c3_w
|
||||
@ -91,6 +167,56 @@ u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* _unix_string_to_knot(): convert c unix path component to $knot
|
||||
*/
|
||||
static u3_atom
|
||||
_unix_string_to_knot(c3_c* pax_c)
|
||||
{
|
||||
c3_assert(pax_c);
|
||||
// XX this can happen if we encounter a file without an extension.
|
||||
//
|
||||
// c3_assert(*pax_c);
|
||||
c3_assert(!strchr(pax_c, '/'));
|
||||
// XX horrible
|
||||
//
|
||||
# ifdef _WIN32
|
||||
c3_assert(!strchr(pax_c, '\\'));
|
||||
# endif
|
||||
if ( '!' == *pax_c ) {
|
||||
pax_c++;
|
||||
}
|
||||
return u3i_string(pax_c);
|
||||
}
|
||||
|
||||
/* _unix_knot_to_string(): convert $knot to c unix path component. RETAIN.
|
||||
*/
|
||||
static c3_c*
|
||||
_unix_knot_to_string(u3_atom pon)
|
||||
{
|
||||
c3_c* ret_c;
|
||||
|
||||
if ( u3_nul != pon
|
||||
&& c3_s1('.') != pon
|
||||
&& c3_s2('.','.') != pon
|
||||
&& '!' != u3r_byte(0, pon) )
|
||||
{
|
||||
ret_c = u3r_string(pon);
|
||||
}
|
||||
else {
|
||||
c3_w met_w = u3r_met(3, pon);
|
||||
|
||||
ret_c = c3_malloc(met_w + 2);
|
||||
*ret_c = '!';
|
||||
u3r_bytes(0, met_w, (c3_y*)ret_c + 1, pon);
|
||||
ret_c[met_w + 1] = 0;
|
||||
}
|
||||
c3_assert(!strchr(ret_c, '/'));
|
||||
# ifdef _WIN32
|
||||
c3_assert(!strchr(ret_c, '\\'));
|
||||
# endif
|
||||
return ret_c;
|
||||
}
|
||||
|
||||
/* _unix_down(): descend path.
|
||||
*/
|
||||
static c3_c*
|
||||
@ -108,29 +234,34 @@ _unix_down(c3_c* pax_c, c3_c* sub_c)
|
||||
return don_c;
|
||||
}
|
||||
|
||||
/* _unix_string_to_path(): convert c string to u3_noun path
|
||||
*
|
||||
* c string must begin with the pier path plus mountpoint
|
||||
/* _unix_string_to_path(): convert c string to u3_noun $path
|
||||
**
|
||||
** c string must begin with the pier path plus mountpoint
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_string_to_path_helper(c3_c* pax_c)
|
||||
{
|
||||
u3_noun not;
|
||||
|
||||
c3_assert(pax_c[-1] == '/');
|
||||
c3_c* end_w = strchr(pax_c, '/');
|
||||
if ( !end_w ) {
|
||||
end_w = strrchr(pax_c, '.');
|
||||
if ( !end_w ) {
|
||||
return u3nc(u3i_string(pax_c), u3_nul);
|
||||
c3_c* end_c = strchr(pax_c, '/');
|
||||
if ( !end_c ) {
|
||||
end_c = strrchr(pax_c, '.');
|
||||
if ( !end_c ) {
|
||||
return u3nc(_unix_string_to_knot(pax_c), u3_nul);
|
||||
}
|
||||
else {
|
||||
return u3nt(u3i_bytes(end_w - pax_c, (c3_y*) pax_c),
|
||||
u3i_string(end_w + 1),
|
||||
u3_nul);
|
||||
*end_c = 0;
|
||||
not = _unix_string_to_knot(pax_c);
|
||||
*end_c = '.';
|
||||
return u3nt(not, _unix_string_to_knot(end_c + 1), u3_nul);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return u3nc(u3i_bytes(end_w - pax_c, (c3_y*) pax_c),
|
||||
_unix_string_to_path_helper(end_w + 1));
|
||||
*end_c = 0;
|
||||
not = _unix_string_to_knot(pax_c);
|
||||
*end_c = '/';
|
||||
return u3nc(not, _unix_string_to_path_helper(end_c + 1));
|
||||
}
|
||||
}
|
||||
static u3_noun
|
||||
@ -144,7 +275,7 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c)
|
||||
return u3_nul;
|
||||
}
|
||||
else {
|
||||
return u3nc(u3i_string(pox_c + 1), u3_nul);
|
||||
return u3nc(_unix_string_to_knot(pox_c + 1), u3_nul);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -152,6 +283,77 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c)
|
||||
}
|
||||
}
|
||||
|
||||
/* _unix_mkdirp(): recursive mkdir of dirname of pax_c.
|
||||
*/
|
||||
static void
|
||||
_unix_mkdirp(c3_c* pax_c)
|
||||
{
|
||||
c3_c* fas_c = strchr(pax_c + 1, '/');
|
||||
|
||||
while ( fas_c ) {
|
||||
*fas_c = 0;
|
||||
if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) {
|
||||
u3l_log("unix: mkdir %s: %s\n", pax_c, strerror(errno));
|
||||
u3m_bail(c3__fail);
|
||||
}
|
||||
*fas_c++ = '/';
|
||||
fas_c = strchr(fas_c, '/');
|
||||
}
|
||||
}
|
||||
|
||||
/* u3_unix_save(): save file under .../.urb/put or bail.
|
||||
**
|
||||
** XX this is quite bad, and doesn't share much in common with
|
||||
** the rest of unix.c. a refactor would probably share common
|
||||
** logic with _unix_sync_change, perhaps using openat, making
|
||||
** unx_u optional, and/or having a flag to not track the file
|
||||
** for future changes.
|
||||
*/
|
||||
void
|
||||
u3_unix_save(c3_c* pax_c, u3_atom pad)
|
||||
{
|
||||
c3_i fid_i;
|
||||
c3_w lod_w, len_w, fln_w, rit_w;
|
||||
c3_y* pad_y;
|
||||
c3_c* ful_c;
|
||||
|
||||
if ( !u3_unix_cane(pax_c) ) {
|
||||
u3l_log("%s: non-canonical path\n", pax_c);
|
||||
u3z(pad); u3m_bail(c3__fail);
|
||||
}
|
||||
if ( '/' == *pax_c) {
|
||||
pax_c++;
|
||||
}
|
||||
lod_w = strlen(u3_Host.dir_c);
|
||||
len_w = lod_w + sizeof("/.urb/put/") + strlen(pax_c);
|
||||
ful_c = c3_malloc(len_w);
|
||||
rit_w = snprintf(ful_c, len_w, "%s/.urb/put/%s", u3_Host.dir_c, pax_c);
|
||||
c3_assert(len_w == rit_w + 1);
|
||||
|
||||
_unix_mkdirp(ful_c);
|
||||
fid_i = c3_open(ful_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if ( fid_i < 0 ) {
|
||||
u3l_log("%s: %s\n", ful_c, strerror(errno));
|
||||
c3_free(ful_c);
|
||||
u3z(pad); u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
fln_w = u3r_met(3, pad);
|
||||
pad_y = c3_malloc(fln_w);
|
||||
u3r_bytes(0, fln_w, pad_y, pad);
|
||||
u3z(pad);
|
||||
rit_w = write(fid_i, pad_y, fln_w);
|
||||
close(fid_i);
|
||||
c3_free(pad_y);
|
||||
|
||||
if ( rit_w != fln_w ) {
|
||||
u3l_log("%s: %s\n", ful_c, strerror(errno));
|
||||
c3_free(ful_c);
|
||||
u3m_bail(c3__fail);
|
||||
}
|
||||
c3_free(ful_c);
|
||||
}
|
||||
|
||||
/* _unix_rm_r_cb(): callback to delete individual files/directories
|
||||
*/
|
||||
static c3_i
|
||||
@ -165,7 +367,7 @@ _unix_rm_r_cb(const c3_c* pax_c,
|
||||
u3l_log("bad file type in rm_r: %s\r\n", pax_c);
|
||||
break;
|
||||
case FTW_F:
|
||||
if ( 0 != unlink(pax_c) && ENOENT != errno ) {
|
||||
if ( 0 != c3_unlink(pax_c) && ENOENT != errno ) {
|
||||
u3l_log("error unlinking (in rm_r) %s: %s\n",
|
||||
pax_c, strerror(errno));
|
||||
c3_assert(0);
|
||||
@ -181,7 +383,7 @@ _unix_rm_r_cb(const c3_c* pax_c,
|
||||
u3l_log("couldn't stat path: %s\r\n", pax_c);
|
||||
break;
|
||||
case FTW_DP:
|
||||
if ( 0 != rmdir(pax_c) && ENOENT != errno ) {
|
||||
if ( 0 != c3_rmdir(pax_c) && ENOENT != errno ) {
|
||||
u3l_log("error rmdiring %s: %s\n", pax_c, strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
@ -213,7 +415,7 @@ _unix_rm_r(c3_c* pax_c)
|
||||
static void
|
||||
_unix_mkdir(c3_c* pax_c)
|
||||
{
|
||||
if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno) {
|
||||
if ( 0 != c3_mkdir(pax_c, 0755) && EEXIST != errno) {
|
||||
u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
@ -224,7 +426,7 @@ _unix_mkdir(c3_c* pax_c)
|
||||
static c3_w
|
||||
_unix_write_file_hard(c3_c* pax_c, u3_noun mim)
|
||||
{
|
||||
c3_i fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_i fid_i = c3_open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_w len_w, rit_w, siz_w, mug_w = 0;
|
||||
c3_y* dat_y;
|
||||
|
||||
@ -267,7 +469,7 @@ static void
|
||||
_unix_write_file_soft(u3_ufil* fil_u, u3_noun mim)
|
||||
{
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_w old_w;
|
||||
c3_y* old_y;
|
||||
@ -339,7 +541,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c3_c* nam_c = u3r_string(mon);
|
||||
c3_c* nam_c = _unix_knot_to_string(mon);
|
||||
u3_umon* mon_u;
|
||||
|
||||
for ( mon_u = unx_u->mon_u;
|
||||
@ -374,7 +576,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon)
|
||||
static void
|
||||
_unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u)
|
||||
{
|
||||
DIR* rid_u = opendir(mon_u->dir_u.pax_c);
|
||||
DIR* rid_u = c3_opendir(mon_u->dir_u.pax_c);
|
||||
if ( !rid_u ) {
|
||||
u3l_log("error opening pier directory: %s: %s\r\n",
|
||||
mon_u->dir_u.pax_c, strerror(errno));
|
||||
@ -425,12 +627,11 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( '.' != out_u->d_name[len_w]
|
||||
|| '\0' == out_u->d_name[len_w + 1]
|
||||
|| '~' == out_u->d_name[strlen(out_u->d_name) - 1]
|
||||
|| ('#' == out_u->d_name[0] &&
|
||||
'#' == out_u->d_name[strlen(out_u->d_name) - 1])
|
||||
) {
|
||||
if ( '.' != out_u->d_name[len_w]
|
||||
|| '\0' == out_u->d_name[len_w + 1]
|
||||
|| '~' == out_u->d_name[strlen(out_u->d_name) - 1]
|
||||
|| !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) )
|
||||
{
|
||||
c3_free(pax_c);
|
||||
continue;
|
||||
}
|
||||
@ -452,7 +653,7 @@ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u);
|
||||
static void
|
||||
_unix_free_file(u3_ufil *fil_u)
|
||||
{
|
||||
if ( 0 != unlink(fil_u->pax_c) && ENOENT != errno ) {
|
||||
if ( 0 != c3_unlink(fil_u->pax_c) && ENOENT != errno ) {
|
||||
u3l_log("error unlinking %s: %s\n", fil_u->pax_c, strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
@ -482,8 +683,8 @@ _unix_free_dir(u3_udir *dir_u)
|
||||
}
|
||||
|
||||
/* _unix_free_node(): free node, deleting everything within
|
||||
*
|
||||
* also deletes from parent list if in it
|
||||
**
|
||||
** also deletes from parent list if in it
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_free_node(u3_unix* unx_u, u3_unod* nod_u)
|
||||
@ -526,12 +727,12 @@ _unix_free_node(u3_unix* unx_u, u3_unod* nod_u)
|
||||
}
|
||||
|
||||
/* _unix_free_mount_point(): free mount point
|
||||
*
|
||||
* this process needs to happen in a very careful order. in particular,
|
||||
* we must recurse before we get to the callback, so that libuv does all
|
||||
* the child directories before it does us.
|
||||
*
|
||||
* tread carefully
|
||||
**
|
||||
** this process needs to happen in a very careful order. in
|
||||
** particular, we must recurse before we get to the callback, so
|
||||
** that libuv does all the child directories before it does us.
|
||||
**
|
||||
** tread carefully
|
||||
*/
|
||||
static void
|
||||
_unix_free_mount_point(u3_unix* unx_u, u3_umon* mon_u)
|
||||
@ -559,7 +760,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon)
|
||||
return;
|
||||
}
|
||||
|
||||
c3_c* nam_c = u3r_string(mon);
|
||||
c3_c* nam_c = _unix_knot_to_string(mon);
|
||||
u3_umon* mon_u;
|
||||
u3_umon* tem_u;
|
||||
|
||||
@ -651,7 +852,7 @@ _unix_watch_dir(u3_udir* dir_u, u3_udir* par_u, c3_c* pax_c)
|
||||
static void
|
||||
_unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam)
|
||||
{
|
||||
c3_c* nam_c = u3r_string(nam);
|
||||
c3_c* nam_c = _unix_knot_to_string(nam);
|
||||
c3_w nam_w = strlen(nam_c);
|
||||
c3_w pax_w = strlen(par_u->pax_c);
|
||||
c3_c* pax_c = c3_malloc(pax_w + 1 + nam_w + 1);
|
||||
@ -671,12 +872,13 @@ _unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam)
|
||||
static u3_noun _unix_update_node(u3_unix* unx_u, u3_unod* nod_u);
|
||||
|
||||
/* _unix_update_file(): update file, producing list of changes
|
||||
*
|
||||
* when scanning through files, if dry, do nothing. otherwise, mark as
|
||||
* dry, then check if file exists. if not, remove self from node list
|
||||
* and add path plus sig to %into event. otherwise, read the file and
|
||||
* get a mug checksum. if same as gum_w, move on. otherwise, overwrite
|
||||
* add path plus data to %into event.
|
||||
**
|
||||
** when scanning through files, if dry, do nothing. otherwise,
|
||||
** mark as dry, then check if file exists. if not, remove
|
||||
** self from node list and add path plus sig to %into event.
|
||||
** otherwise, read the file and get a mug checksum. if same as
|
||||
** gum_w, move on. otherwise, overwrite add path plus data to
|
||||
** %into event.
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_update_file(u3_unix* unx_u, u3_ufil* fil_u)
|
||||
@ -690,7 +892,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u)
|
||||
fil_u->dry = c3n;
|
||||
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_y* dat_y;
|
||||
|
||||
@ -745,9 +947,9 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u)
|
||||
}
|
||||
|
||||
/* _unix_update_dir(): update directory, producing list of changes
|
||||
*
|
||||
* when changing this, consider whether to also change
|
||||
* _unix_initial_update_dir()
|
||||
**
|
||||
** when changing this, consider whether to also change
|
||||
** _unix_initial_update_dir()
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_update_dir(u3_unix* unx_u, u3_udir* dir_u)
|
||||
@ -773,7 +975,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u)
|
||||
}
|
||||
else {
|
||||
if ( c3y == nod_u->dir ) {
|
||||
DIR* red_u = opendir(nod_u->pax_c);
|
||||
DIR* red_u = c3_opendir(nod_u->pax_c);
|
||||
if ( 0 == red_u ) {
|
||||
u3_unod* nex_u = nod_u->nex_u;
|
||||
can = u3kb_weld(_unix_free_node(unx_u, nod_u), can);
|
||||
@ -786,7 +988,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u)
|
||||
}
|
||||
else {
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = open(nod_u->pax_c, O_RDONLY, 0644);
|
||||
c3_i fid_i = c3_open(nod_u->pax_c, O_RDONLY, 0644);
|
||||
|
||||
if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) {
|
||||
if ( ENOENT != errno ) {
|
||||
@ -813,7 +1015,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u)
|
||||
|
||||
// Check for new nodes
|
||||
|
||||
DIR* rid_u = opendir(dir_u->pax_c);
|
||||
DIR* rid_u = c3_opendir(dir_u->pax_c);
|
||||
if ( !rid_u ) {
|
||||
u3l_log("error opening directory %s: %s\r\n",
|
||||
dir_u->pax_c, strerror(errno));
|
||||
@ -869,11 +1071,10 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u)
|
||||
|
||||
if ( !nod_u ) {
|
||||
if ( !S_ISDIR(buf_u.st_mode) ) {
|
||||
if ( !strchr(out_u->d_name,'.')
|
||||
|| '~' == out_u->d_name[strlen(out_u->d_name) - 1]
|
||||
|| ('#' == out_u->d_name[0] &&
|
||||
'#' == out_u->d_name[strlen(out_u->d_name) - 1])
|
||||
) {
|
||||
if ( !strchr(out_u->d_name,'.')
|
||||
|| '~' == out_u->d_name[strlen(out_u->d_name) - 1]
|
||||
|| !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) )
|
||||
{
|
||||
c3_free(pax_c);
|
||||
continue;
|
||||
}
|
||||
@ -942,7 +1143,8 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all)
|
||||
u3_noun wir = u3nt(c3__sync,
|
||||
u3dc("scot", c3__uv, unx_u->sev_l),
|
||||
u3_nul);
|
||||
u3_noun cad = u3nq(c3__into, u3i_string(mon_u->nam_c), all, can);
|
||||
u3_noun cad = u3nq(c3__into, _unix_string_to_knot(mon_u->nam_c), all,
|
||||
can);
|
||||
|
||||
u3_auto_plan(&unx_u->car_u, u3_ovum_init(0, c3__c, wir, cad));
|
||||
}
|
||||
@ -950,13 +1152,13 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all)
|
||||
}
|
||||
|
||||
/* _unix_initial_update_file(): read file, but don't watch
|
||||
** XX deduplicate with _unix_update_file()
|
||||
** XX deduplicate with _unix_update_file()
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_initial_update_file(c3_c* pax_c, c3_c* bas_c)
|
||||
{
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = open(pax_c, O_RDONLY, 0644);
|
||||
c3_i fid_i = c3_open(pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_y* dat_y;
|
||||
|
||||
@ -1006,14 +1208,14 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c)
|
||||
}
|
||||
|
||||
/* _unix_initial_update_dir(): read directory, but don't watch
|
||||
** XX deduplicate with _unix_update_dir()
|
||||
** XX deduplicate with _unix_update_dir()
|
||||
*/
|
||||
static u3_noun
|
||||
_unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c)
|
||||
{
|
||||
u3_noun can = u3_nul;
|
||||
|
||||
DIR* rid_u = opendir(pax_c);
|
||||
DIR* rid_u = c3_opendir(pax_c);
|
||||
if ( !rid_u ) {
|
||||
u3l_log("error opening initial directory: %s: %s\r\n",
|
||||
pax_c, strerror(errno));
|
||||
@ -1089,8 +1291,8 @@ _unix_sync_file(u3_unix* unx_u, u3_udir* par_u, u3_noun nam, u3_noun ext, u3_nou
|
||||
|
||||
// form file path
|
||||
|
||||
c3_c* nam_c = u3r_string(nam);
|
||||
c3_c* ext_c = u3r_string(ext);
|
||||
c3_c* nam_c = _unix_knot_to_string(nam);
|
||||
c3_c* ext_c = _unix_knot_to_string(ext);
|
||||
c3_w par_w = strlen(par_u->pax_c);
|
||||
c3_w nam_w = strlen(nam_c);
|
||||
c3_w ext_w = strlen(ext_c);
|
||||
@ -1174,7 +1376,7 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim)
|
||||
_unix_sync_file(unx_u, dir_u, u3k(i_pax), u3k(it_pax), mim);
|
||||
}
|
||||
else {
|
||||
c3_c* nam_c = u3r_string(i_pax);
|
||||
c3_c* nam_c = _unix_knot_to_string(i_pax);
|
||||
c3_w pax_w = strlen(dir_u->pax_c);
|
||||
u3_unod* nod_u;
|
||||
|
||||
@ -1207,7 +1409,7 @@ static void
|
||||
_unix_sync_ergo(u3_unix* unx_u, u3_umon* mon_u, u3_noun can)
|
||||
{
|
||||
u3_noun nac = can;
|
||||
u3_noun nam = u3i_string(mon_u->nam_c);
|
||||
u3_noun nam = _unix_string_to_knot(mon_u->nam_c);
|
||||
|
||||
while ( u3_nul != nac) {
|
||||
_unix_sync_change(unx_u, &mon_u->dir_u,
|
||||
@ -1263,98 +1465,24 @@ u3_unix_ef_hill(u3_unix* unx_u, u3_noun hil)
|
||||
u3z(hil);
|
||||
}
|
||||
|
||||
/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it.
|
||||
*/
|
||||
static void
|
||||
u3_unix_acquire(c3_c* pax_c)
|
||||
{
|
||||
c3_c* paf_c = _unix_down(pax_c, ".vere.lock");
|
||||
c3_w pid_w;
|
||||
FILE* loq_u;
|
||||
|
||||
if ( NULL != (loq_u = fopen(paf_c, "r")) ) {
|
||||
if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) {
|
||||
u3l_log("lockfile %s is corrupt!\n", paf_c);
|
||||
kill(getpid(), SIGTERM);
|
||||
sleep(1); c3_assert(0);
|
||||
}
|
||||
else if (pid_w != getpid()) {
|
||||
c3_w i_w;
|
||||
|
||||
if ( -1 != kill(pid_w, SIGTERM) ) {
|
||||
u3l_log("unix: stopping process %d, live in %s...\n",
|
||||
pid_w, pax_c);
|
||||
|
||||
for ( i_w = 0; i_w < 16; i_w++ ) {
|
||||
sleep(1);
|
||||
if ( -1 == kill(pid_w, SIGTERM) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( 16 == i_w ) {
|
||||
for ( i_w = 0; i_w < 16; i_w++ ) {
|
||||
if ( -1 == kill(pid_w, SIGKILL) ) {
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
if ( 16 == i_w ) {
|
||||
u3l_log("unix: process %d seems unkillable!\n", pid_w);
|
||||
c3_assert(0);
|
||||
}
|
||||
u3l_log("unix: stopped old process %u\n", pid_w);
|
||||
}
|
||||
}
|
||||
fclose(loq_u);
|
||||
unlink(paf_c);
|
||||
}
|
||||
|
||||
if ( NULL == (loq_u = fopen(paf_c, "w")) ) {
|
||||
u3l_log("unix: unable to open %s\n", paf_c);
|
||||
c3_assert(0);
|
||||
}
|
||||
|
||||
fprintf(loq_u, "%u\n", getpid());
|
||||
|
||||
{
|
||||
c3_i fid_i = fileno(loq_u);
|
||||
c3_sync(fid_i);
|
||||
}
|
||||
|
||||
fclose(loq_u);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
/* u3_unix_release(): release a lockfile.
|
||||
*/
|
||||
static void
|
||||
u3_unix_release(c3_c* pax_c)
|
||||
{
|
||||
c3_c* paf_c = _unix_down(pax_c, ".vere.lock");
|
||||
|
||||
unlink(paf_c);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
/* u3_unix_ef_look(): update the root of a specific mount point.
|
||||
*/
|
||||
void
|
||||
u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all)
|
||||
{
|
||||
if ( c3y == unx_u->dyr ) {
|
||||
c3_c* nam_c = _unix_knot_to_string(mon);
|
||||
|
||||
unx_u->dyr = c3n;
|
||||
u3_umon* mon_u = unx_u->mon_u;
|
||||
|
||||
while ( mon_u && ( c3n == u3r_sing_c(mon_u->nam_c, mon) ) ) {
|
||||
while ( mon_u && 0 != strcmp(nam_c, mon_u->nam_c) ) {
|
||||
mon_u = mon_u->nex_u;
|
||||
}
|
||||
|
||||
c3_free(nam_c);
|
||||
if ( mon_u ) {
|
||||
_unix_update_mount(unx_u, mon_u, all);
|
||||
}
|
||||
}
|
||||
|
||||
u3z(mon);
|
||||
}
|
||||
|
||||
@ -1431,10 +1559,7 @@ _unix_io_exit(u3_auto* car_u)
|
||||
{
|
||||
u3_unix* unx_u = (u3_unix*)car_u;
|
||||
|
||||
// XX move to disk.c?
|
||||
//
|
||||
u3_unix_release(unx_u->pax_c);
|
||||
|
||||
u3z(unx_u->sat);
|
||||
c3_free(unx_u->pax_c);
|
||||
c3_free(unx_u);
|
||||
}
|
||||
@ -1449,10 +1574,7 @@ u3_unix_io_init(u3_pier* pir_u)
|
||||
unx_u->pax_c = strdup(pir_u->pax_c);
|
||||
unx_u->alm = c3n;
|
||||
unx_u->dyr = c3n;
|
||||
|
||||
// XX move to disk.c?
|
||||
//
|
||||
u3_unix_acquire(unx_u->pax_c);
|
||||
unx_u->sat = u3do("sane", c3__ta);
|
||||
|
||||
u3_auto* car_u = &unx_u->car_u;
|
||||
car_u->nam_m = c3__unix;
|
||||
|
@ -923,13 +923,13 @@ u3_king_grab(void* vod_p)
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(nam_c, &st) ) {
|
||||
mkdir(nam_c, 0700);
|
||||
c3_mkdir(nam_c, 0700);
|
||||
}
|
||||
|
||||
c3_c man_c[2048];
|
||||
snprintf(man_c, 2048, "%s/%s-daemon.txt", nam_c, wen_c);
|
||||
|
||||
fil_u = fopen(man_c, "w");
|
||||
fil_u = c3_fopen(man_c, "w");
|
||||
fprintf(fil_u, "%s\r\n", wen_c);
|
||||
|
||||
c3_free(wen_c);
|
||||
|
@ -526,12 +526,11 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun)
|
||||
// if serialization and export path succeeded, write to disk
|
||||
//
|
||||
if ( (u3_none != out) && (u3_none != pad) ) {
|
||||
c3_c fil_c[2048];
|
||||
snprintf(fil_c, 2048, "%s/.urb/put/%s.%s",
|
||||
pir_u->pax_c, pac_c+1, ext_c);
|
||||
c3_c fil_c[256];
|
||||
snprintf(fil_c, 256, "%s.%s", pac_c + 1, ext_c);
|
||||
|
||||
u3_walk_save(fil_c, 0, out, pir_u->pax_c, pad);
|
||||
u3l_log("pier: scry result in %s\n", fil_c);
|
||||
u3_unix_save(fil_c, pad);
|
||||
u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,326 +0,0 @@
|
||||
/* vere/walk.c
|
||||
**
|
||||
*/
|
||||
#include "all.h"
|
||||
#include "vere/vere.h"
|
||||
|
||||
/* |%
|
||||
** ++ arch :: fs node
|
||||
** $% [& p=@uvI q=*] :: file, hash/data
|
||||
** [| p=(map ,@ta arch)] :: directory
|
||||
** == ::
|
||||
** --
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static u3_noun
|
||||
_walk_ok(u3_noun nod)
|
||||
{
|
||||
u3_noun don = u3n_mung(u3k(u2A->toy.arch), u3k(nod));
|
||||
|
||||
if ( c3n == u3_sing(nod, don) ) {
|
||||
c3_assert(0);
|
||||
}
|
||||
u3z(don);
|
||||
return nod;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* u3_walk_safe(): load file or 0.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk_safe(c3_c* pas_c)
|
||||
{
|
||||
struct stat buf_b;
|
||||
c3_i fid_i = open(pas_c, O_RDONLY, 0644);
|
||||
c3_w fln_w, red_w;
|
||||
c3_y* pad_y;
|
||||
|
||||
if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) {
|
||||
// u3l_log("%s: %s\n", pas_c, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
fln_w = buf_b.st_size;
|
||||
pad_y = c3_malloc(buf_b.st_size);
|
||||
|
||||
red_w = read(fid_i, pad_y, fln_w);
|
||||
close(fid_i);
|
||||
|
||||
if ( fln_w != red_w ) {
|
||||
c3_free(pad_y);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y);
|
||||
c3_free(pad_y);
|
||||
|
||||
return pad;
|
||||
}
|
||||
}
|
||||
|
||||
/* u3_walk_load(): load file or bail.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk_load(c3_c* pas_c)
|
||||
{
|
||||
struct stat buf_b;
|
||||
c3_i fid_i = open(pas_c, O_RDONLY, 0644);
|
||||
c3_w fln_w, red_w;
|
||||
c3_y* pad_y;
|
||||
|
||||
if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) {
|
||||
u3l_log("%s: %s\n", pas_c, strerror(errno));
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
fln_w = buf_b.st_size;
|
||||
pad_y = c3_malloc(buf_b.st_size);
|
||||
|
||||
red_w = read(fid_i, pad_y, fln_w);
|
||||
close(fid_i);
|
||||
|
||||
if ( fln_w != red_w ) {
|
||||
c3_free(pad_y);
|
||||
u3l_log("u3_walk_load failed");
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
else {
|
||||
u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y);
|
||||
c3_free(pad_y);
|
||||
|
||||
return pad;
|
||||
}
|
||||
}
|
||||
|
||||
/* _walk_mkdirp(): recursively make directories in pax at bas_c (RETAIN)
|
||||
*/
|
||||
static void
|
||||
_walk_mkdirp(c3_c* bas_c, u3_noun pax)
|
||||
{
|
||||
c3_c* pax_c;
|
||||
c3_y* waq_y;
|
||||
c3_w pax_w, fas_w, len_w;
|
||||
|
||||
if ( u3_nul == pax ) {
|
||||
return;
|
||||
}
|
||||
|
||||
pax_w = u3r_met(3, u3h(pax));
|
||||
fas_w = strlen(bas_c);
|
||||
len_w = 1 + fas_w + pax_w;
|
||||
|
||||
pax_c = c3_malloc(1 + len_w);
|
||||
strcpy(pax_c, bas_c);
|
||||
|
||||
pax_c[fas_w] = '/';
|
||||
waq_y = (void*)(1 + pax_c + fas_w);
|
||||
u3r_bytes(0, pax_w, waq_y, u3h(pax));
|
||||
pax_c[len_w] = '\0';
|
||||
|
||||
if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno ) {
|
||||
u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno));
|
||||
u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
_walk_mkdirp(pax_c, u3t(pax));
|
||||
c3_free(pax_c);
|
||||
}
|
||||
|
||||
/* u3_walk_save(): save file or bail.
|
||||
*/
|
||||
void
|
||||
u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax)
|
||||
{
|
||||
c3_i fid_i = open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_w fln_w, rit_w;
|
||||
c3_y* pad_y;
|
||||
|
||||
if ( fid_i < 0 ) {
|
||||
if ( ENOENT == errno && u3_nul != pax ) {
|
||||
_walk_mkdirp(bas_c, pax);
|
||||
return u3_walk_save(pas_c, tim, pad, 0, u3_nul);
|
||||
}
|
||||
|
||||
u3l_log("%s: %s\n", pas_c, strerror(errno));
|
||||
u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
fln_w = u3r_met(3, pad);
|
||||
pad_y = c3_malloc(fln_w);
|
||||
u3r_bytes(0, fln_w, pad_y, pad);
|
||||
u3z(pad);
|
||||
u3z(pax);
|
||||
|
||||
rit_w = write(fid_i, pad_y, fln_w);
|
||||
close(fid_i);
|
||||
c3_free(pad_y);
|
||||
|
||||
if ( rit_w != fln_w ) {
|
||||
u3l_log("%s: %s\n", pas_c, strerror(errno));
|
||||
u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
if ( 0 != tim ) {
|
||||
struct timeval tim_tv[2];
|
||||
|
||||
u3_time_out_tv(&tim_tv[0], u3k(tim));
|
||||
u3_time_out_tv(&tim_tv[1], tim);
|
||||
|
||||
utimes(pas_c, tim_tv);
|
||||
}
|
||||
}
|
||||
|
||||
/* _walk_in(): inner loop of _walk(), producing map.
|
||||
*/
|
||||
static u3_noun
|
||||
_walk_in(const c3_c* dir_c, c3_w len_w)
|
||||
{
|
||||
DIR* dir_d = opendir(dir_c);
|
||||
u3_noun map = u3_nul;
|
||||
|
||||
if ( !dir_d ) {
|
||||
return u3_nul;
|
||||
}
|
||||
else while ( 1 ) {
|
||||
struct dirent ent_n;
|
||||
struct dirent* out_n;
|
||||
|
||||
if ( u3_readdir_r(dir_d, &ent_n, &out_n) != 0 ) {
|
||||
u3l_log("%s: %s\n", dir_c, strerror(errno));
|
||||
break;
|
||||
}
|
||||
else if ( !out_n ) {
|
||||
break;
|
||||
}
|
||||
else if ( !strcmp(out_n->d_name, ".") ||
|
||||
!strcmp(out_n->d_name, "..") ||
|
||||
('~' == out_n->d_name[0]) ||
|
||||
('.' == out_n->d_name[0]) ) // XX restricts some spans
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
c3_c* fil_c = out_n->d_name;
|
||||
c3_w lef_w = len_w + 1 + strlen(fil_c);
|
||||
c3_c* pat_c = c3_malloc(lef_w + 1);
|
||||
struct stat buf_b;
|
||||
|
||||
strncpy(pat_c, dir_c, lef_w);
|
||||
pat_c[len_w] = '/';
|
||||
strncpy(pat_c + len_w + 1, fil_c, lef_w);
|
||||
pat_c[lef_w] = '\0';
|
||||
|
||||
if ( 0 != stat(pat_c, &buf_b) ) {
|
||||
c3_free(pat_c);
|
||||
} else {
|
||||
u3_noun tim = c3_stat_mtime(&buf_b);
|
||||
|
||||
if ( !S_ISDIR(buf_b.st_mode) ) {
|
||||
c3_c* dot_c = strrchr(fil_c, '.');
|
||||
c3_c* nam_c = strdup(fil_c);
|
||||
c3_c* ext_c = strdup(dot_c + 1);
|
||||
|
||||
nam_c[dot_c - fil_c] = 0;
|
||||
{
|
||||
u3_noun nam = u3i_string(nam_c);
|
||||
u3_noun ext = u3i_string(ext_c);
|
||||
u3_noun get = u3kdb_get(u3k(map), u3k(nam));
|
||||
u3_noun dat = u3_walk_load(pat_c);
|
||||
u3_noun hax;
|
||||
|
||||
if ( !strcmp("noun", ext_c) ) {
|
||||
dat = u3ke_cue(dat);
|
||||
}
|
||||
hax = u3do("sham", u3k(dat));
|
||||
if ( u3_none == get ) { get = u3_nul; }
|
||||
|
||||
get = u3kdb_put(get, ext, u3nt(c3y, hax, dat));
|
||||
map = u3kdb_put(map, nam, u3nc(c3n, get));
|
||||
}
|
||||
c3_free(nam_c);
|
||||
c3_free(ext_c);
|
||||
}
|
||||
else {
|
||||
u3_noun dir = _walk_in(pat_c, lef_w);
|
||||
|
||||
if ( u3_nul != dir ) {
|
||||
map = u3kdb_put
|
||||
(map, u3i_string(fil_c), u3nc(c3n, dir));
|
||||
}
|
||||
else u3z(tim);
|
||||
}
|
||||
c3_free(pat_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir_d);
|
||||
return map;
|
||||
}
|
||||
|
||||
/* u3_walk(): traverse `dir_c` to produce an arch, updating `old`.
|
||||
*/
|
||||
u3_noun
|
||||
u3_walk(const c3_c* dir_c, u3_noun old)
|
||||
{
|
||||
// XX - obviously, cheaper to update old data.
|
||||
u3z(old);
|
||||
{
|
||||
struct stat buf_b;
|
||||
|
||||
if ( 0 != stat(dir_c, &buf_b) ) {
|
||||
u3l_log("can't stat %s\n", dir_c);
|
||||
// return u3m_bail(c3__fail);
|
||||
c3_assert(0);
|
||||
}
|
||||
else {
|
||||
return u3nc(c3n,
|
||||
_walk_in(dir_c, strlen(dir_c)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* u3_path(): C unix path in computer for file or directory.
|
||||
*/
|
||||
c3_c*
|
||||
u3_path(c3_o fyl, u3_noun pax)
|
||||
{
|
||||
c3_w len_w;
|
||||
c3_c *pas_c;
|
||||
|
||||
// measure
|
||||
//
|
||||
len_w = strlen(u3_Local);
|
||||
{
|
||||
u3_noun wiz = pax;
|
||||
|
||||
while ( u3_nul != wiz ) {
|
||||
len_w += (1 + u3r_met(3, u3h(wiz)));
|
||||
wiz = u3t(wiz);
|
||||
}
|
||||
}
|
||||
|
||||
// cut
|
||||
//
|
||||
pas_c = c3_malloc(len_w + 1);
|
||||
strncpy(pas_c, u3_Local, len_w);
|
||||
pas_c[len_w] = '\0';
|
||||
{
|
||||
u3_noun wiz = pax;
|
||||
c3_c* waq_c = (pas_c + strlen(pas_c));
|
||||
|
||||
while ( u3_nul != wiz ) {
|
||||
c3_w tis_w = u3r_met(3, u3h(wiz));
|
||||
|
||||
if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) {
|
||||
*waq_c++ = '.';
|
||||
} else *waq_c++ = '/';
|
||||
|
||||
u3r_bytes(0, tis_w, (c3_y*)waq_c, u3h(wiz));
|
||||
waq_c += tis_w;
|
||||
|
||||
wiz = u3t(wiz);
|
||||
}
|
||||
*waq_c = 0;
|
||||
}
|
||||
u3z(pax);
|
||||
return pas_c;
|
||||
}
|
@ -131,7 +131,7 @@ _cw_serf_stdio(c3_i* inn_i, c3_i* out_i)
|
||||
// we replace [FD 0] (stdin) with a fd pointing to /dev/null
|
||||
// we replace [FD 1] (stdout) with a dup of [FD 2] (stderr)
|
||||
//
|
||||
c3_i nul_i = open(c3_dev_null, O_RDWR, 0);
|
||||
c3_i nul_i = c3_open(c3_dev_null, O_RDWR, 0);
|
||||
|
||||
*inn_i = dup(0);
|
||||
*out_i = dup(1);
|
||||
|
@ -204,13 +204,13 @@ _serf_grab(u3_noun sac)
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(nam_c, &st) ) {
|
||||
mkdir(nam_c, 0700);
|
||||
c3_mkdir(nam_c, 0700);
|
||||
}
|
||||
|
||||
c3_c man_c[2054];
|
||||
snprintf(man_c, 2053, "%s/%s-serf.txt", nam_c, wen_c);
|
||||
|
||||
fil_u = fopen(man_c, "w");
|
||||
fil_u = c3_fopen(man_c, "w");
|
||||
fprintf(fil_u, "%s\r\n", wen_c);
|
||||
|
||||
c3_free(wen_c);
|
||||
@ -835,13 +835,13 @@ _serf_writ_live_exit(u3_serf* sef_u, c3_w cod_w)
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(nam_c, &st) ) {
|
||||
mkdir(nam_c, 0700);
|
||||
c3_mkdir(nam_c, 0700);
|
||||
}
|
||||
|
||||
c3_c man_c[2054];
|
||||
snprintf(man_c, 2053, "%s/%s.txt", nam_c, wen_c);
|
||||
|
||||
fil_u = fopen(man_c, "w");
|
||||
fil_u = c3_fopen(man_c, "w");
|
||||
|
||||
c3_free(wen_c);
|
||||
u3z(wen);
|
||||
|
Loading…
Reference in New Issue
Block a user