Browse Source

Plan 9 from Bell Labs 2005-12-30

David du Colombier 18 years ago
parent
commit
c8feb49e42
100 changed files with 13559 additions and 639 deletions
  1. 490 178
      dist/replica/_plan9.db
  2. 490 178
      dist/replica/plan9.db
  3. 619 0
      dist/replica/plan9.log
  4. 29 50
      sys/man/8/drawterm
  5. 1 0
      sys/src/cmd/aquarela/COPYRIGHT
  6. 69 0
      sys/src/cmd/aquarela/addname.c
  7. 126 0
      sys/src/cmd/aquarela/alarm.c
  8. 17 0
      sys/src/cmd/aquarela/alloc.c
  9. 308 0
      sys/src/cmd/aquarela/aquarela.c
  10. 239 0
      sys/src/cmd/aquarela/cifscmd.c
  11. 147 0
      sys/src/cmd/aquarela/client.c
  12. 137 0
      sys/src/cmd/aquarela/dump.c
  13. 73 0
      sys/src/cmd/aquarela/findname.c
  14. 10 0
      sys/src/cmd/aquarela/headers.h
  15. 55 0
      sys/src/cmd/aquarela/message.c
  16. 114 0
      sys/src/cmd/aquarela/mkfile
  17. 25 0
      sys/src/cmd/aquarela/nb.c
  18. 216 0
      sys/src/cmd/aquarela/nbdgram.c
  19. 116 0
      sys/src/cmd/aquarela/nbdgramconv.c
  20. 19 0
      sys/src/cmd/aquarela/nbdgramdump.c
  21. 35 0
      sys/src/cmd/aquarela/nblistener.c
  22. 299 0
      sys/src/cmd/aquarela/nbname.c
  23. 156 0
      sys/src/cmd/aquarela/nbns.c
  24. 314 0
      sys/src/cmd/aquarela/nbnsconv.c
  25. 33 0
      sys/src/cmd/aquarela/nbresolve.c
  26. 428 0
      sys/src/cmd/aquarela/nbss.c
  27. 251 0
      sys/src/cmd/aquarela/netbios.h
  28. 387 0
      sys/src/cmd/aquarela/smb.h
  29. 43 0
      sys/src/cmd/aquarela/smballoc.c
  30. 56 0
      sys/src/cmd/aquarela/smbbrowse.c
  31. 579 0
      sys/src/cmd/aquarela/smbbuffer.c
  32. 53 0
      sys/src/cmd/aquarela/smbclientopen.c
  33. 24 0
      sys/src/cmd/aquarela/smbcomclose.c
  34. 25 0
      sys/src/cmd/aquarela/smbcomcreatedir.c
  35. 76 0
      sys/src/cmd/aquarela/smbcomdelete.c
  36. 24 0
      sys/src/cmd/aquarela/smbcomdeletedir.c
  37. 49 0
      sys/src/cmd/aquarela/smbcomdir.c
  38. 25 0
      sys/src/cmd/aquarela/smbcomecho.c
  39. 12 0
      sys/src/cmd/aquarela/smbcomfindclose2.c
  40. 28 0
      sys/src/cmd/aquarela/smbcomflush.c
  41. 132 0
      sys/src/cmd/aquarela/smbcomlocking.c
  42. 335 0
      sys/src/cmd/aquarela/smbcommon.c
  43. 617 0
      sys/src/cmd/aquarela/smbcomopen.c
  44. 95 0
      sys/src/cmd/aquarela/smbcomquery.c
  45. 84 0
      sys/src/cmd/aquarela/smbcomread.c
  46. 45 0
      sys/src/cmd/aquarela/smbcomrename.c
  47. 186 0
      sys/src/cmd/aquarela/smbcomsessionsetupandx.c
  48. 107 0
      sys/src/cmd/aquarela/smbcomsetinfo.c
  49. 137 0
      sys/src/cmd/aquarela/smbcomtransaction.c
  50. 116 0
      sys/src/cmd/aquarela/smbcomtreeconnectandx.c
  51. 10 0
      sys/src/cmd/aquarela/smbcomtreedisconnect.c
  52. 155 0
      sys/src/cmd/aquarela/smbcomwrite.c
  53. 275 0
      sys/src/cmd/aquarela/smbconnect.c
  54. 42 0
      sys/src/cmd/aquarela/smbconv.c
  55. 325 0
      sys/src/cmd/aquarela/smbdat.h
  56. 43 0
      sys/src/cmd/aquarela/smbdircache.c
  57. 25 0
      sys/src/cmd/aquarela/smbfile.c
  58. 256 0
      sys/src/cmd/aquarela/smbfns.h
  59. 43 0
      sys/src/cmd/aquarela/smbglobals.c
  60. 128 0
      sys/src/cmd/aquarela/smbidmap.c
  61. 155 0
      sys/src/cmd/aquarela/smblisten.c
  62. 107 0
      sys/src/cmd/aquarela/smblog.c
  63. 89 0
      sys/src/cmd/aquarela/smbnegotiate.c
  64. 98 0
      sys/src/cmd/aquarela/smboptable.c
  65. 22 0
      sys/src/cmd/aquarela/smbpath.c
  66. 467 0
      sys/src/cmd/aquarela/smbrap2.c
  67. 100 0
      sys/src/cmd/aquarela/smbrap2client.c
  68. 67 0
      sys/src/cmd/aquarela/smbrep.c
  69. 135 0
      sys/src/cmd/aquarela/smbresponse.c
  70. 115 0
      sys/src/cmd/aquarela/smbservice.c
  71. 271 0
      sys/src/cmd/aquarela/smbsharedfile.c
  72. 201 0
      sys/src/cmd/aquarela/smbstring.c
  73. 63 0
      sys/src/cmd/aquarela/smbtime.c
  74. 108 0
      sys/src/cmd/aquarela/smbtrans2client.c
  75. 333 0
      sys/src/cmd/aquarela/smbtrans2find.c
  76. 235 0
      sys/src/cmd/aquarela/smbtrans2query.c
  77. 100 0
      sys/src/cmd/aquarela/smbtrans2set.c
  78. 507 0
      sys/src/cmd/aquarela/smbtransaction.c
  79. 73 0
      sys/src/cmd/aquarela/smbtree.c
  80. 56 0
      sys/src/cmd/aquarela/testconnect.c
  81. 114 0
      sys/src/cmd/aquarela/testnbdgram.c
  82. 23 0
      sys/src/cmd/aquarela/testtime.c
  83. 330 0
      sys/src/cmd/tcs/html.c
  84. BIN
      sys/src/cmd/unix/drawterm/9ball.ico
  85. 1 0
      sys/src/cmd/unix/drawterm/9ball.rc
  86. 245 0
      sys/src/cmd/unix/drawterm/LICENSE
  87. 1 0
      sys/src/cmd/unix/drawterm/Make.config
  88. 21 0
      sys/src/cmd/unix/drawterm/Make.unix
  89. 42 0
      sys/src/cmd/unix/drawterm/Make.win32
  90. 71 0
      sys/src/cmd/unix/drawterm/Makefile
  91. 36 8
      sys/src/cmd/unix/drawterm/README
  92. 0 2
      sys/src/cmd/unix/drawterm/README.MACOSX
  93. 0 17
      sys/src/cmd/unix/drawterm/_asrdfile.c
  94. 0 37
      sys/src/cmd/unix/drawterm/_asrdresp.c
  95. 0 15
      sys/src/cmd/unix/drawterm/_asreadn.c
  96. 20 0
      sys/src/cmd/unix/drawterm/args.h
  97. 0 3
      sys/src/cmd/unix/drawterm/argv0.c
  98. 0 60
      sys/src/cmd/unix/drawterm/asm-Solaris-386.s
  99. 0 21
      sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s
  100. 0 70
      sys/src/cmd/unix/drawterm/atexit.c

+ 490 - 178
dist/replica/_plan9.db

@@ -37,6 +37,7 @@
 386/bin/ape/stty - 775 sys sys 1130384232 41057
 386/bin/ape/stty - 775 sys sys 1130384232 41057
 386/bin/ape/tar - 775 sys sys 1135570769 61941
 386/bin/ape/tar - 775 sys sys 1135570769 61941
 386/bin/ape/uname - 775 sys sys 1134151328 132699
 386/bin/ape/uname - 775 sys sys 1134151328 132699
+386/bin/aquarela - 775 sys sys 1135914849 331831
 386/bin/ar - 775 sys sys 1135570769 111942
 386/bin/ar - 775 sys sys 1135570769 111942
 386/bin/archfs - 775 sys sys 1135570769 146849
 386/bin/archfs - 775 sys sys 1135570769 146849
 386/bin/ascii - 775 sys sys 1135570770 64641
 386/bin/ascii - 775 sys sys 1135570770 64641
@@ -176,6 +177,7 @@
 386/bin/cfs - 775 sys sys 1135570797 128025
 386/bin/cfs - 775 sys sys 1135570797 128025
 386/bin/chgrp - 775 sys sys 1135570798 59279
 386/bin/chgrp - 775 sys sys 1135570798 59279
 386/bin/chmod - 775 sys sys 1135570798 62275
 386/bin/chmod - 775 sys sys 1135570798 62275
+386/bin/cifscmd - 775 sys sys 1135914850 342709
 386/bin/cleanname - 775 sys sys 1135570798 58298
 386/bin/cleanname - 775 sys sys 1135570798 58298
 386/bin/clock - 775 sys sys 1135570798 158281
 386/bin/clock - 775 sys sys 1135570798 158281
 386/bin/cmp - 775 sys sys 1130384270 40583
 386/bin/cmp - 775 sys sys 1130384270 40583
@@ -7685,7 +7687,7 @@ sys/man/8/checkarenas - 664 sys sys 1019866709 669
 sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cron - 664 sys sys 1063858596 1867
 sys/man/8/cron - 664 sys sys 1063858596 1867
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
-sys/man/8/drawterm - 664 sys sys 958419689 2458
+sys/man/8/drawterm - 664 sys sys 1135901219 1741
 sys/man/8/fossilcons - 664 sys sys 1127560168 17789
 sys/man/8/fossilcons - 664 sys sys 1127560168 17789
 sys/man/8/fs - 664 sys sys 1055701170 15029
 sys/man/8/fs - 664 sys sys 1055701170 15029
 sys/man/8/fsconfig - 664 sys sys 1045501600 8142
 sys/man/8/fsconfig - 664 sys sys 1045501600 8142
@@ -9307,6 +9309,85 @@ sys/src/cmd/acme/time.c - 664 sys sys 1014926095 1783
 sys/src/cmd/acme/util.c - 664 sys sys 1107154483 7984
 sys/src/cmd/acme/util.c - 664 sys sys 1107154483 7984
 sys/src/cmd/acme/wind.c - 664 sys sys 1122526112 11233
 sys/src/cmd/acme/wind.c - 664 sys sys 1122526112 11233
 sys/src/cmd/acme/xfid.c - 664 sys sys 1125314186 19766
 sys/src/cmd/acme/xfid.c - 664 sys sys 1125314186 19766
+sys/src/cmd/aquarela - 20000000775 sys sys 1135892145 0
+sys/src/cmd/aquarela/COPYRIGHT - 664 sys sys 1135892145 43
+sys/src/cmd/aquarela/addname.c - 664 sys sys 1135892108 1281
+sys/src/cmd/aquarela/alarm.c - 664 sys sys 1135892108 2194
+sys/src/cmd/aquarela/alloc.c - 664 sys sys 1135892108 245
+sys/src/cmd/aquarela/aquarela.c - 664 sys sys 1135892108 6986
+sys/src/cmd/aquarela/cifscmd.c - 664 sys sys 1135892108 4430
+sys/src/cmd/aquarela/client.c - 664 sys sys 1135892108 2724
+sys/src/cmd/aquarela/dump.c - 664 sys sys 1135892108 2864
+sys/src/cmd/aquarela/findname.c - 664 sys sys 1135892108 1351
+sys/src/cmd/aquarela/headers.h - 664 sys sys 1135892108 185
+sys/src/cmd/aquarela/message.c - 664 sys sys 1135892108 1260
+sys/src/cmd/aquarela/mkfile - 664 sys sys 1135892109 1487
+sys/src/cmd/aquarela/nb.c - 664 sys sys 1135892109 538
+sys/src/cmd/aquarela/nbdgram.c - 664 sys sys 1135892109 4364
+sys/src/cmd/aquarela/nbdgramconv.c - 664 sys sys 1135892109 2339
+sys/src/cmd/aquarela/nbdgramdump.c - 664 sys sys 1135892109 506
+sys/src/cmd/aquarela/nblistener.c - 664 sys sys 1135892109 738
+sys/src/cmd/aquarela/nbname.c - 664 sys sys 1135892109 5457
+sys/src/cmd/aquarela/nbns.c - 664 sys sys 1135892109 2747
+sys/src/cmd/aquarela/nbnsconv.c - 664 sys sys 1135892109 6257
+sys/src/cmd/aquarela/nbresolve.c - 664 sys sys 1135892109 672
+sys/src/cmd/aquarela/nbss.c - 664 sys sys 1135892110 8126
+sys/src/cmd/aquarela/netbios.h - 664 sys sys 1135892110 5967
+sys/src/cmd/aquarela/smb.h - 664 sys sys 1135892110 9492
+sys/src/cmd/aquarela/smballoc.c - 664 sys sys 1135892110 508
+sys/src/cmd/aquarela/smbbrowse.c - 664 sys sys 1135892110 1473
+sys/src/cmd/aquarela/smbbuffer.c - 664 sys sys 1135892110 9717
+sys/src/cmd/aquarela/smbclientopen.c - 664 sys sys 1135892110 1428
+sys/src/cmd/aquarela/smbcomclose.c - 664 sys sys 1135892110 578
+sys/src/cmd/aquarela/smbcomcreatedir.c - 664 sys sys 1135892110 692
+sys/src/cmd/aquarela/smbcomdelete.c - 664 sys sys 1135892110 1575
+sys/src/cmd/aquarela/smbcomdeletedir.c - 664 sys sys 1135892111 659
+sys/src/cmd/aquarela/smbcomdir.c - 664 sys sys 1135892111 1113
+sys/src/cmd/aquarela/smbcomecho.c - 664 sys sys 1135892111 819
+sys/src/cmd/aquarela/smbcomfindclose2.c - 664 sys sys 1135892111 319
+sys/src/cmd/aquarela/smbcomflush.c - 664 sys sys 1135892111 707
+sys/src/cmd/aquarela/smbcomlocking.c - 664 sys sys 1135892111 3701
+sys/src/cmd/aquarela/smbcommon.c - 664 sys sys 1135892111 8652
+sys/src/cmd/aquarela/smbcomopen.c - 664 sys sys 1135892111 18350
+sys/src/cmd/aquarela/smbcomquery.c - 664 sys sys 1135892111 2715
+sys/src/cmd/aquarela/smbcomread.c - 664 sys sys 1135892112 2601
+sys/src/cmd/aquarela/smbcomrename.c - 664 sys sys 1135892112 1259
+sys/src/cmd/aquarela/smbcomsessionsetupandx.c - 664 sys sys 1135892112 6175
+sys/src/cmd/aquarela/smbcomsetinfo.c - 664 sys sys 1135892112 2985
+sys/src/cmd/aquarela/smbcomtransaction.c - 664 sys sys 1135892112 4041
+sys/src/cmd/aquarela/smbcomtreeconnectandx.c - 664 sys sys 1135892112 3269
+sys/src/cmd/aquarela/smbcomtreedisconnect.c - 664 sys sys 1135892112 290
+sys/src/cmd/aquarela/smbcomwrite.c - 664 sys sys 1135892112 3312
+sys/src/cmd/aquarela/smbconnect.c - 664 sys sys 1135892112 9040
+sys/src/cmd/aquarela/smbconv.c - 664 sys sys 1135892112 531
+sys/src/cmd/aquarela/smbdat.h - 664 sys sys 1135892113 6649
+sys/src/cmd/aquarela/smbdircache.c - 664 sys sys 1135892113 631
+sys/src/cmd/aquarela/smbfile.c - 664 sys sys 1135892113 438
+sys/src/cmd/aquarela/smbfns.h - 664 sys sys 1135892113 12190
+sys/src/cmd/aquarela/smbglobals.c - 664 sys sys 1135892113 1096
+sys/src/cmd/aquarela/smbidmap.c - 664 sys sys 1135892113 2178
+sys/src/cmd/aquarela/smblisten.c - 664 sys sys 1135892113 2592
+sys/src/cmd/aquarela/smblog.c - 664 sys sys 1135892113 1841
+sys/src/cmd/aquarela/smbnegotiate.c - 664 sys sys 1135892113 2933
+sys/src/cmd/aquarela/smboptable.c - 664 sys sys 1135892113 5826
+sys/src/cmd/aquarela/smbpath.c - 664 sys sys 1135892114 393
+sys/src/cmd/aquarela/smbrap2.c - 664 sys sys 1135892114 11628
+sys/src/cmd/aquarela/smbrap2client.c - 664 sys sys 1135892114 3082
+sys/src/cmd/aquarela/smbrep.c - 664 sys sys 1135892114 1033
+sys/src/cmd/aquarela/smbresponse.c - 664 sys sys 1135892114 2820
+sys/src/cmd/aquarela/smbservice.c - 664 sys sys 1135892114 2335
+sys/src/cmd/aquarela/smbsharedfile.c - 664 sys sys 1135892114 6006
+sys/src/cmd/aquarela/smbstring.c - 664 sys sys 1135892114 4152
+sys/src/cmd/aquarela/smbtime.c - 664 sys sys 1135892114 1232
+sys/src/cmd/aquarela/smbtrans2client.c - 664 sys sys 1135892114 3726
+sys/src/cmd/aquarela/smbtrans2find.c - 664 sys sys 1135892115 9041
+sys/src/cmd/aquarela/smbtrans2query.c - 664 sys sys 1135892115 8215
+sys/src/cmd/aquarela/smbtrans2set.c - 664 sys sys 1135892115 2440
+sys/src/cmd/aquarela/smbtransaction.c - 664 sys sys 1135892115 16684
+sys/src/cmd/aquarela/smbtree.c - 664 sys sys 1135892115 1314
+sys/src/cmd/aquarela/testconnect.c - 664 sys sys 1135892115 1533
+sys/src/cmd/aquarela/testnbdgram.c - 664 sys sys 1135892115 2919
+sys/src/cmd/aquarela/testtime.c - 664 sys sys 1135892115 446
 sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
 sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
 sys/src/cmd/archfs.c - 664 sys sys 1014925694 3871
 sys/src/cmd/archfs.c - 664 sys sys 1014925694 3871
 sys/src/cmd/ascii.c - 664 sys sys 1134233061 3980
 sys/src/cmd/ascii.c - 664 sys sys 1134233061 3980
@@ -13010,6 +13091,7 @@ sys/src/cmd/tcs/font/qbits.c - 664 sys sys 944961251 2037
 sys/src/cmd/tcs/gb.c - 664 sys sys 944961288 62707
 sys/src/cmd/tcs/gb.c - 664 sys sys 944961288 62707
 sys/src/cmd/tcs/gb.h - 664 sys sys 944961287 183
 sys/src/cmd/tcs/gb.h - 664 sys sys 944961287 183
 sys/src/cmd/tcs/hdr.h - 664 sys sys 944961287 1213
 sys/src/cmd/tcs/hdr.h - 664 sys sys 944961287 1213
+sys/src/cmd/tcs/html.c - 664 sys sys 1135893400 5237
 sys/src/cmd/tcs/jis.h - 664 sys sys 944961287 2873
 sys/src/cmd/tcs/jis.h - 664 sys sys 944961287 2873
 sys/src/cmd/tcs/ksc.c - 664 sys sys 944961289 72413
 sys/src/cmd/tcs/ksc.c - 664 sys sys 944961289 72413
 sys/src/cmd/tcs/ksc.h - 664 sys sys 944961287 112
 sys/src/cmd/tcs/ksc.h - 664 sys sys 944961287 112
@@ -13085,185 +13167,415 @@ sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.8 - 664 sys sys 960684604 10864
 sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.c - 664 sys sys 960684605 25118
 sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.c - 664 sys sys 960684605 25118
 sys/src/cmd/unix/README - 664 sys sys 1128520385 1735
 sys/src/cmd/unix/README - 664 sys sys 1128520385 1735
 sys/src/cmd/unix/drawterm - 20000000775 sys sys 964488190 0
 sys/src/cmd/unix/drawterm - 20000000775 sys sys 964488190 0
-sys/src/cmd/unix/drawterm/README - 664 sys sys 1128520449 373
-sys/src/cmd/unix/drawterm/README.MACOSX - 664 sys sys 1020578504 57
-sys/src/cmd/unix/drawterm/_asgetticket.c - 664 sys sys 954098597 285
-sys/src/cmd/unix/drawterm/_asrdfile.c - 664 sys sys 954098597 245
-sys/src/cmd/unix/drawterm/_asrdresp.c - 664 sys sys 954098598 545
-sys/src/cmd/unix/drawterm/_asreadn.c - 664 sys sys 954098599 200
-sys/src/cmd/unix/drawterm/argv0.c - 664 sys sys 954098599 32
-sys/src/cmd/unix/drawterm/asm-Solaris-386.s - 664 sys sys 954098600 885
-sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s - 664 sys sys 954098600 312
-sys/src/cmd/unix/drawterm/atexit.c - 664 sys sys 954098601 818
-sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 1077480264 2218
-sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 1077480264 2992
-sys/src/cmd/unix/drawterm/authaux.c - 664 sys sys 954098602 11934
-sys/src/cmd/unix/drawterm/authdial.c - 664 sys sys 954098603 145
-sys/src/cmd/unix/drawterm/authlocal.h - 664 sys sys 954098603 162
+sys/src/cmd/unix/drawterm/9ball.ico - 664 sys sys 1135900533 9326
+sys/src/cmd/unix/drawterm/9ball.rc - 664 sys sys 1135900533 39
+sys/src/cmd/unix/drawterm/LICENSE - 664 sys sys 1135900534 12184
+sys/src/cmd/unix/drawterm/Make.config - 664 sys sys 1135900534 29
+sys/src/cmd/unix/drawterm/Make.unix - 664 sys sys 1135900534 429
+sys/src/cmd/unix/drawterm/Make.win32 - 664 sys sys 1135900534 816
+sys/src/cmd/unix/drawterm/Makefile - 664 sys sys 1135900534 1112
+sys/src/cmd/unix/drawterm/README - 664 sys sys 1135900534 925
+sys/src/cmd/unix/drawterm/args.h - 664 sys sys 1135900534 709
 sys/src/cmd/unix/drawterm/bin - 20000000775 sys sys 959090509 0
 sys/src/cmd/unix/drawterm/bin - 20000000775 sys sys 959090509 0
-sys/src/cmd/unix/drawterm/bin/README - 664 sys sys 1113252460 106
-sys/src/cmd/unix/drawterm/canlock-power-gcc.c - 664 sys sys 1019839861 985
-sys/src/cmd/unix/drawterm/canlock-x86-gcc.c - 664 sys sys 1020313486 308
-sys/src/cmd/unix/drawterm/canlock.c - 664 sys sys 954098604 92
-sys/src/cmd/unix/drawterm/chan.c - 664 sys sys 954098604 10678
-sys/src/cmd/unix/drawterm/conv.c - 664 sys sys 954098605 8138
-sys/src/cmd/unix/drawterm/convD2M.c - 664 sys sys 954098606 703
-sys/src/cmd/unix/drawterm/convM2D.c - 664 sys sys 954098606 646
-sys/src/cmd/unix/drawterm/convM2S.c - 664 sys sys 954098607 2978
-sys/src/cmd/unix/drawterm/convM2T.c - 664 sys sys 954098607 557
-sys/src/cmd/unix/drawterm/convM2TR.c - 664 sys sys 954098608 269
-sys/src/cmd/unix/drawterm/convS2M.c - 664 sys sys 954098608 2984
-sys/src/cmd/unix/drawterm/convTR2M.c - 664 sys sys 954098609 529
-sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 1077480266 963
-sys/src/cmd/unix/drawterm/dev.c - 664 sys sys 954098610 5006
-sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 1077480267 7105
-sys/src/cmd/unix/drawterm/devdraw.c - 664 sys sys 958504757 39499
-sys/src/cmd/unix/drawterm/devip-unix.c - 664 sys sys 1046970237 15063
-sys/src/cmd/unix/drawterm/devip-win.c - 664 sys sys 1015701212 15055
-sys/src/cmd/unix/drawterm/devmnt.c - 664 sys sys 954098613 14492
-sys/src/cmd/unix/drawterm/devmouse.c - 664 sys sys 954098613 3982
-sys/src/cmd/unix/drawterm/devntfs.c - 664 sys sys 954098614 10545
-sys/src/cmd/unix/drawterm/devpipe.c - 664 sys sys 954098614 4958
-sys/src/cmd/unix/drawterm/devroot.c - 664 sys sys 954098615 1534
-sys/src/cmd/unix/drawterm/devssl.c - 664 sys sys 1077480268 25283
-sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 1077480268 2113
-sys/src/cmd/unix/drawterm/devunixfs.c - 664 sys sys 954098616 9548
-sys/src/cmd/unix/drawterm/dial.c - 664 sys sys 954098617 3640
-sys/src/cmd/unix/drawterm/dirfstat.c - 664 sys sys 954098617 179
-sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 1077480269 11757
-sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1077480270 12639
-sys/src/cmd/unix/drawterm/error.c - 664 sys sys 954098619 2515
-sys/src/cmd/unix/drawterm/error.h - 664 sys sys 954098619 3075
-sys/src/cmd/unix/drawterm/exportfs.c - 664 sys sys 964798439 13405
-sys/src/cmd/unix/drawterm/fcall.h - 664 sys sys 954098620 1675
-sys/src/cmd/unix/drawterm/fcallconv.c - 664 sys sys 954098621 4376
-sys/src/cmd/unix/drawterm/getcallerpc.c - 664 sys sys 954098622 89
-sys/src/cmd/unix/drawterm/getuser.c - 664 sys sys 954098622 274
-sys/src/cmd/unix/drawterm/glyph.c - 664 sys sys 954098624 4081
-sys/src/cmd/unix/drawterm/ip.h - 664 sys sys 954098625 560
-sys/src/cmd/unix/drawterm/irix.c - 664 sys sys 954098626 7552
-sys/src/cmd/unix/drawterm/kbd.c - 664 sys sys 954098627 8210
-sys/src/cmd/unix/drawterm/keyboard.h - 664 sys sys 1080159172 380
-sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1077480272 7808
-sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 1077480272 7930
+sys/src/cmd/unix/drawterm/cpu-bl.c - 644 sys sys 1135900534 14118
+sys/src/cmd/unix/drawterm/cpu.c - 664 sys sys 1135900534 13988
+sys/src/cmd/unix/drawterm/drawterm.h - 664 sys sys 1135900535 472
+sys/src/cmd/unix/drawterm/drawterm.ico - 664 sys sys 1135900535 1662
+sys/src/cmd/unix/drawterm/drawterm.rc - 664 sys sys 1135900535 1713
+sys/src/cmd/unix/drawterm/drawterm.res - 664 sys sys 1135900535 1756
+sys/src/cmd/unix/drawterm/exportfs - 20000000775 sys sys 1135900552 0
+sys/src/cmd/unix/drawterm/exportfs/Makefile - 664 sys sys 1135900552 200
+sys/src/cmd/unix/drawterm/exportfs/exportfs.c - 664 sys sys 1135900552 8412
+sys/src/cmd/unix/drawterm/exportfs/exportfs.h - 664 sys sys 1135900552 2738
+sys/src/cmd/unix/drawterm/exportfs/exportsrv.c - 664 sys sys 1135900552 10966
+sys/src/cmd/unix/drawterm/gui-win32 - 20000000775 sys sys 1135900547 0
+sys/src/cmd/unix/drawterm/gui-win32/Makefile - 664 sys sys 1135900546 220
+sys/src/cmd/unix/drawterm/gui-win32/alloc.c - 664 sys sys 1135900546 286
+sys/src/cmd/unix/drawterm/gui-win32/cload.c - 664 sys sys 1135900546 188
+sys/src/cmd/unix/drawterm/gui-win32/draw.c - 664 sys sys 1135900546 365
+sys/src/cmd/unix/drawterm/gui-win32/load.c - 664 sys sys 1135900546 186
+sys/src/cmd/unix/drawterm/gui-win32/screen.c - 664 sys sys 1135900547 11539
+sys/src/cmd/unix/drawterm/gui-win32/wstrtoutf.c - 664 sys sys 1135900547 408
+sys/src/cmd/unix/drawterm/gui-x11 - 20000000775 sys sys 1135900548 0
+sys/src/cmd/unix/drawterm/gui-x11/Makefile - 664 sys sys 1135900547 207
+sys/src/cmd/unix/drawterm/gui-x11/alloc.c - 664 sys sys 1135900547 3941
+sys/src/cmd/unix/drawterm/gui-x11/cload.c - 664 sys sys 1135900547 260
+sys/src/cmd/unix/drawterm/gui-x11/draw.c - 664 sys sys 1135900547 3896
+sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs-x11.c - 664 sys sys 1135900547 67008
+sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs.h - 664 sys sys 1135900548 244
+sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h - 664 sys sys 1135900548 13549
+sys/src/cmd/unix/drawterm/gui-x11/load.c - 664 sys sys 1135900548 258
+sys/src/cmd/unix/drawterm/gui-x11/screen.c - 664 sys sys 1135900548 24932
+sys/src/cmd/unix/drawterm/gui-x11/xmem.h - 664 sys sys 1135900548 1508
+sys/src/cmd/unix/drawterm/include - 20000000775 sys sys 1135900799 0
+sys/src/cmd/unix/drawterm/include/9windows.h - 664 sys sys 1135900761 420
+sys/src/cmd/unix/drawterm/include/a.out - 664 sys sys 1135900761 4522
+sys/src/cmd/unix/drawterm/include/auth.h - 664 sys sys 1135900761 3536
+sys/src/cmd/unix/drawterm/include/authsrv.h - 664 sys sys 1135900762 4562
+sys/src/cmd/unix/drawterm/include/cursor.h - 664 sys sys 1135900762 70
+sys/src/cmd/unix/drawterm/include/draw.h - 664 sys sys 1135900762 16052
+sys/src/cmd/unix/drawterm/include/dtos.h - 664 sys sys 1135900762 358
+sys/src/cmd/unix/drawterm/include/fcall.h - 664 sys sys 1135900762 2676
+sys/src/cmd/unix/drawterm/include/keyboard.h - 664 sys sys 1135900762 920
+sys/src/cmd/unix/drawterm/include/lib.h - 664 sys sys 1135900763 7449
+sys/src/cmd/unix/drawterm/include/libc.h - 664 sys sys 1135900763 36
+sys/src/cmd/unix/drawterm/include/libsec.h - 664 sys sys 1135900763 8861
+sys/src/cmd/unix/drawterm/include/memdraw.h - 664 sys sys 1135900763 6306
+sys/src/cmd/unix/drawterm/include/memlayer.h - 664 sys sys 1135900763 1871
+sys/src/cmd/unix/drawterm/include/mp.h - 664 sys sys 1135900763 4524
+sys/src/cmd/unix/drawterm/include/u.h - 664 sys sys 1135900763 336
+sys/src/cmd/unix/drawterm/include/unix.h - 664 sys sys 1135900763 263
+sys/src/cmd/unix/drawterm/include/user.h - 664 sys sys 1135900764 2532
+sys/src/cmd/unix/drawterm/kern - 20000000775 sys sys 1135900801 0
+sys/src/cmd/unix/drawterm/kern/Makefile - 664 sys sys 1135900764 571
+sys/src/cmd/unix/drawterm/kern/allocb.c - 664 sys sys 1135900764 3172
+sys/src/cmd/unix/drawterm/kern/cache.c - 664 sys sys 1135900764 466
+sys/src/cmd/unix/drawterm/kern/chan.c - 664 sys sys 1135900764 29593
+sys/src/cmd/unix/drawterm/kern/dat.h - 664 sys sys 1135900765 10716
+sys/src/cmd/unix/drawterm/kern/data.c - 664 sys sys 1135900765 423
+sys/src/cmd/unix/drawterm/kern/dev.c - 664 sys sys 1135900765 8523
+sys/src/cmd/unix/drawterm/kern/devcons.c - 664 sys sys 1135900765 19526
+sys/src/cmd/unix/drawterm/kern/devdraw.c - 664 sys sys 1135900765 42481
+sys/src/cmd/unix/drawterm/kern/devfs-posix.c - 664 sys sys 1135900765 9772
+sys/src/cmd/unix/drawterm/kern/devfs-win32.c - 664 sys sys 1135900766 10723
+sys/src/cmd/unix/drawterm/kern/devip-posix.c - 664 sys sys 1135900766 3488
+sys/src/cmd/unix/drawterm/kern/devip-win32.c - 664 sys sys 1135900766 3534
+sys/src/cmd/unix/drawterm/kern/devip.c - 664 sys sys 1135900766 16045
+sys/src/cmd/unix/drawterm/kern/devip.h - 664 sys sys 1135900766 469
+sys/src/cmd/unix/drawterm/kern/devlfd.c - 664 sys sys 1135900766 1534
+sys/src/cmd/unix/drawterm/kern/devmnt.c - 664 sys sys 1135900767 21739
+sys/src/cmd/unix/drawterm/kern/devmouse.c - 664 sys sys 1135900767 3799
+sys/src/cmd/unix/drawterm/kern/devpipe.c - 664 sys sys 1135900767 5927
+sys/src/cmd/unix/drawterm/kern/devroot.c - 664 sys sys 1135900767 4717
+sys/src/cmd/unix/drawterm/kern/devssl.c - 664 sys sys 1135900767 26455
+sys/src/cmd/unix/drawterm/kern/devtab.c - 664 sys sys 1135900767 470
+sys/src/cmd/unix/drawterm/kern/error.c - 664 sys sys 1135900767 2100
+sys/src/cmd/unix/drawterm/kern/error.h - 664 sys sys 1135900768 2583
+sys/src/cmd/unix/drawterm/kern/exportfs.c - 664 sys sys 1135900768 13444
+sys/src/cmd/unix/drawterm/kern/fns.h - 664 sys sys 1135900768 10731
+sys/src/cmd/unix/drawterm/kern/netif.h - 664 sys sys 1135900768 2950
+sys/src/cmd/unix/drawterm/kern/parse.c - 664 sys sys 1135900768 1993
+sys/src/cmd/unix/drawterm/kern/pgrp.c - 664 sys sys 1135900768 4017
+sys/src/cmd/unix/drawterm/kern/posix.c - 664 sys sys 1135900768 3149
+sys/src/cmd/unix/drawterm/kern/procinit.c - 664 sys sys 1135900769 1039
+sys/src/cmd/unix/drawterm/kern/qio.c - 664 sys sys 1135900769 23496
+sys/src/cmd/unix/drawterm/kern/qlock.c - 664 sys sys 1135900769 1119
+sys/src/cmd/unix/drawterm/kern/rendez.c - 664 sys sys 1135900769 1293
+sys/src/cmd/unix/drawterm/kern/rwlock.c - 664 sys sys 1135900769 634
+sys/src/cmd/unix/drawterm/kern/screen.h - 664 sys sys 1135900769 1151
+sys/src/cmd/unix/drawterm/kern/sleep.c - 664 sys sys 1135900769 1293
+sys/src/cmd/unix/drawterm/kern/smalloc.c - 664 sys sys 1135900769 187
+sys/src/cmd/unix/drawterm/kern/stub.c - 664 sys sys 1135900770 1273
+sys/src/cmd/unix/drawterm/kern/syscall.c - 664 sys sys 1135900770 12876
+sys/src/cmd/unix/drawterm/kern/sysfile.c - 664 sys sys 1135900770 18035
+sys/src/cmd/unix/drawterm/kern/sysproc.c - 664 sys sys 1135900770 498
+sys/src/cmd/unix/drawterm/kern/term.c - 664 sys sys 1135900770 3962
+sys/src/cmd/unix/drawterm/kern/todo.c - 664 sys sys 1135900770 0
+sys/src/cmd/unix/drawterm/kern/uart.c - 664 sys sys 1135900771 178
+sys/src/cmd/unix/drawterm/kern/waserror.c - 664 sys sys 1135900771 382
+sys/src/cmd/unix/drawterm/kern/win32.c - 664 sys sys 1135900771 7800
+sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1135900535 7806
+sys/src/cmd/unix/drawterm/libauth - 20000000775 sys sys 1135900560 0
+sys/src/cmd/unix/drawterm/libauth/Makefile - 664 sys sys 1135900556 306
+sys/src/cmd/unix/drawterm/libauth/attr.c - 664 sys sys 1135900556 2857
+sys/src/cmd/unix/drawterm/libauth/auth_attr.c - 664 sys sys 1135900556 217
+sys/src/cmd/unix/drawterm/libauth/auth_challenge.c - 664 sys sys 1135900556 1976
+sys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c - 664 sys sys 1135900556 1363
+sys/src/cmd/unix/drawterm/libauth/auth_proxy.c - 664 sys sys 1135900557 3606
+sys/src/cmd/unix/drawterm/libauth/auth_respond.c - 664 sys sys 1135900560 1420
+sys/src/cmd/unix/drawterm/libauth/auth_rpc.c - 664 sys sys 1135900560 2064
+sys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c - 664 sys sys 1135900560 1097
+sys/src/cmd/unix/drawterm/libauth/authlocal.h - 664 sys sys 1135900560 87
+sys/src/cmd/unix/drawterm/libauth/httpauth.c - 664 sys sys 1135900560 1059
+sys/src/cmd/unix/drawterm/libauthsrv - 20000000775 sys sys 1135900562 0
+sys/src/cmd/unix/drawterm/libauthsrv/Makefile - 664 sys sys 1135900560 355
+sys/src/cmd/unix/drawterm/libauthsrv/_asgetticket.c - 664 sys sys 1135900560 280
+sys/src/cmd/unix/drawterm/libauthsrv/_asrdresp.c - 664 sys sys 1135900560 874
+sys/src/cmd/unix/drawterm/libauthsrv/authdial.c - 664 sys sys 1135900561 711
+sys/src/cmd/unix/drawterm/libauthsrv/convA2M.c - 664 sys sys 1135900561 501
+sys/src/cmd/unix/drawterm/libauthsrv/convM2A.c - 664 sys sys 1135900561 470
+sys/src/cmd/unix/drawterm/libauthsrv/convM2PR.c - 664 sys sys 1135900561 610
+sys/src/cmd/unix/drawterm/libauthsrv/convM2T.c - 664 sys sys 1135900561 579
+sys/src/cmd/unix/drawterm/libauthsrv/convM2TR.c - 664 sys sys 1135900561 617
+sys/src/cmd/unix/drawterm/libauthsrv/convPR2M.c - 664 sys sys 1135900561 563
+sys/src/cmd/unix/drawterm/libauthsrv/convT2M.c - 664 sys sys 1135900561 558
+sys/src/cmd/unix/drawterm/libauthsrv/convTR2M.c - 664 sys sys 1135900561 562
+sys/src/cmd/unix/drawterm/libauthsrv/nvcsum.c - 664 sys sys 1135900562 192
+sys/src/cmd/unix/drawterm/libauthsrv/opasstokey.c - 664 sys sys 1135900562 448
+sys/src/cmd/unix/drawterm/libauthsrv/passtokey.c - 664 sys sys 1135900562 517
+sys/src/cmd/unix/drawterm/libauthsrv/readnvram.c - 664 sys sys 1135900562 8446
+sys/src/cmd/unix/drawterm/libc - 20000000775 sys sys 1135900573 0
+sys/src/cmd/unix/drawterm/libc/Makefile - 664 sys sys 1135900562 1097
+sys/src/cmd/unix/drawterm/libc/charstod.c - 664 sys sys 1135900562 1661
+sys/src/cmd/unix/drawterm/libc/cleanname.c - 664 sys sys 1135900562 1199
+sys/src/cmd/unix/drawterm/libc/convD2M.c - 664 sys sys 1135900562 1398
+sys/src/cmd/unix/drawterm/libc/convM2D.c - 664 sys sys 1135900563 1419
+sys/src/cmd/unix/drawterm/libc/convM2S.c - 664 sys sys 1135900563 4969
+sys/src/cmd/unix/drawterm/libc/convS2M.c - 664 sys sys 1135900563 5014
+sys/src/cmd/unix/drawterm/libc/crypt.c - 664 sys sys 1135900563 1045
+sys/src/cmd/unix/drawterm/libc/dial.c - 664 sys sys 1135900563 3703
+sys/src/cmd/unix/drawterm/libc/dirfstat.c - 664 sys sys 1135900563 676
+sys/src/cmd/unix/drawterm/libc/dirfwstat.c - 664 sys sys 1135900563 242
+sys/src/cmd/unix/drawterm/libc/dirmodefmt.c - 664 sys sys 1135900563 581
+sys/src/cmd/unix/drawterm/libc/dirstat.c - 664 sys sys 1135900563 688
+sys/src/cmd/unix/drawterm/libc/dirwstat.c - 664 sys sys 1135900564 246
+sys/src/cmd/unix/drawterm/libc/dofmt.c - 664 sys sys 1135900564 8626
+sys/src/cmd/unix/drawterm/libc/dorfmt.c - 664 sys sys 1135900564 777
+sys/src/cmd/unix/drawterm/libc/errfmt.c - 664 sys sys 1135900564 175
+sys/src/cmd/unix/drawterm/libc/fcallfmt.c - 664 sys sys 1135900564 5740
+sys/src/cmd/unix/drawterm/libc/fltfmt.c - 664 sys sys 1135900564 4345
+sys/src/cmd/unix/drawterm/libc/fmt.c - 664 sys sys 1135900564 2940
+sys/src/cmd/unix/drawterm/libc/fmt.h - 664 sys sys 1135900565 3075
+sys/src/cmd/unix/drawterm/libc/fmtdef.h - 664 sys sys 1135900565 1808
+sys/src/cmd/unix/drawterm/libc/fmtfd.c - 664 sys sys 1135900565 508
+sys/src/cmd/unix/drawterm/libc/fmtlock.c - 664 sys sys 1135900565 134
+sys/src/cmd/unix/drawterm/libc/fmtprint.c - 664 sys sys 1135900565 465
+sys/src/cmd/unix/drawterm/libc/fmtquote.c - 664 sys sys 1135900565 4732
+sys/src/cmd/unix/drawterm/libc/fmtrune.c - 664 sys sys 1135900565 314
+sys/src/cmd/unix/drawterm/libc/fmtstr.c - 664 sys sys 1135900565 140
+sys/src/cmd/unix/drawterm/libc/fmtvprint.c - 664 sys sys 1135900565 449
+sys/src/cmd/unix/drawterm/libc/fprint.c - 664 sys sys 1135900566 174
+sys/src/cmd/unix/drawterm/libc/frand.c - 664 sys sys 1135900566 210
+sys/src/cmd/unix/drawterm/libc/getfields.c - 664 sys sys 1135900566 516
+sys/src/cmd/unix/drawterm/libc/getpid.c - 664 sys sys 1135900566 198
+sys/src/cmd/unix/drawterm/libc/lnrand.c - 664 sys sys 1135900566 194
+sys/src/cmd/unix/drawterm/libc/lock.c - 664 sys sys 1135900566 774
+sys/src/cmd/unix/drawterm/libc/lrand.c - 664 sys sys 1135900566 1109
+sys/src/cmd/unix/drawterm/libc/mallocz.c - 664 sys sys 1135900566 141
+sys/src/cmd/unix/drawterm/libc/nan.h - 664 sys sys 1135900566 114
+sys/src/cmd/unix/drawterm/libc/nan64.c - 664 sys sys 1135900567 921
+sys/src/cmd/unix/drawterm/libc/netmkaddr.c - 664 sys sys 1135900567 863
+sys/src/cmd/unix/drawterm/libc/nrand.c - 664 sys sys 1135900567 191
+sys/src/cmd/unix/drawterm/libc/nsec.c - 664 sys sys 1135900567 1196
+sys/src/cmd/unix/drawterm/libc/pow10.c - 664 sys sys 1135900567 1946
+sys/src/cmd/unix/drawterm/libc/print.c - 664 sys sys 1135900567 164
+sys/src/cmd/unix/drawterm/libc/pushssl.c - 664 sys sys 1135900567 905
+sys/src/cmd/unix/drawterm/libc/rand.c - 664 sys sys 1135900567 79
+sys/src/cmd/unix/drawterm/libc/read9pmsg.c - 664 sys sys 1135900567 462
+sys/src/cmd/unix/drawterm/libc/readn.c - 664 sys sys 1135900568 234
+sys/src/cmd/unix/drawterm/libc/rune.c - 664 sys sys 1135900568 2306
+sys/src/cmd/unix/drawterm/libc/runefmtstr.c - 664 sys sys 1135900568 144
+sys/src/cmd/unix/drawterm/libc/runeseprint.c - 664 sys sys 1135900568 204
+sys/src/cmd/unix/drawterm/libc/runesmprint.c - 664 sys sys 1135900568 176
+sys/src/cmd/unix/drawterm/libc/runesnprint.c - 664 sys sys 1135900568 203
+sys/src/cmd/unix/drawterm/libc/runesprint.c - 664 sys sys 1135900568 192
+sys/src/cmd/unix/drawterm/libc/runestrcat.c - 664 sys sys 1135900568 124
+sys/src/cmd/unix/drawterm/libc/runestrchr.c - 664 sys sys 1135900568 207
+sys/src/cmd/unix/drawterm/libc/runestrcmp.c - 664 sys sys 1135900569 221
+sys/src/cmd/unix/drawterm/libc/runestrcpy.c - 664 sys sys 1135900569 138
+sys/src/cmd/unix/drawterm/libc/runestrdup.c - 664 sys sys 1135900569 180
+sys/src/cmd/unix/drawterm/libc/runestrecpy.c - 664 sys sys 1135900569 202
+sys/src/cmd/unix/drawterm/libc/runestrlen.c - 664 sys sys 1135900569 94
+sys/src/cmd/unix/drawterm/libc/runestrncat.c - 664 sys sys 1135900569 213
+sys/src/cmd/unix/drawterm/libc/runestrncmp.c - 664 sys sys 1135900569 250
+sys/src/cmd/unix/drawterm/libc/runestrncpy.c - 664 sys sys 1135900569 234
+sys/src/cmd/unix/drawterm/libc/runestrrchr.c - 664 sys sys 1135900569 182
+sys/src/cmd/unix/drawterm/libc/runestrstr.c - 664 sys sys 1135900570 397
+sys/src/cmd/unix/drawterm/libc/runetype.c - 664 sys sys 1135900570 29655
+sys/src/cmd/unix/drawterm/libc/runevseprint.c - 664 sys sys 1135900570 313
+sys/src/cmd/unix/drawterm/libc/runevsmprint.c - 664 sys sys 1135900570 1043
+sys/src/cmd/unix/drawterm/libc/runevsnprint.c - 664 sys sys 1135900570 330
+sys/src/cmd/unix/drawterm/libc/seprint.c - 664 sys sys 1135900570 196
+sys/src/cmd/unix/drawterm/libc/smprint.c - 664 sys sys 1135900570 168
+sys/src/cmd/unix/drawterm/libc/snprint.c - 664 sys sys 1135900570 195
+sys/src/cmd/unix/drawterm/libc/sprint.c - 664 sys sys 1135900570 236
+sys/src/cmd/unix/drawterm/libc/strecpy.c - 664 sys sys 1135900571 223
+sys/src/cmd/unix/drawterm/libc/strtod.c - 664 sys sys 1135900571 8558
+sys/src/cmd/unix/drawterm/libc/strtod.h - 664 sys sys 1135900571 120
+sys/src/cmd/unix/drawterm/libc/strtoll.c - 664 sys sys 1135900571 1302
+sys/src/cmd/unix/drawterm/libc/sysfatal.c - 664 sys sys 1135900571 479
+sys/src/cmd/unix/drawterm/libc/time.c - 664 sys sys 1135900571 878
+sys/src/cmd/unix/drawterm/libc/tokenize.c - 664 sys sys 1135900571 1691
+sys/src/cmd/unix/drawterm/libc/truerand.c - 664 sys sys 1135900571 306
+sys/src/cmd/unix/drawterm/libc/u16.c - 664 sys sys 1135900571 823
+sys/src/cmd/unix/drawterm/libc/u32.c - 664 sys sys 1135900572 2414
+sys/src/cmd/unix/drawterm/libc/u64.c - 664 sys sys 1135900572 3282
+sys/src/cmd/unix/drawterm/libc/utf.h - 664 sys sys 1135900572 1442
+sys/src/cmd/unix/drawterm/libc/utfdef.h - 664 sys sys 1135900572 335
+sys/src/cmd/unix/drawterm/libc/utfecpy.c - 664 sys sys 1135900572 284
+sys/src/cmd/unix/drawterm/libc/utflen.c - 664 sys sys 1135900572 242
+sys/src/cmd/unix/drawterm/libc/utfnlen.c - 664 sys sys 1135900572 317
+sys/src/cmd/unix/drawterm/libc/utfrrune.c - 664 sys sys 1135900572 414
+sys/src/cmd/unix/drawterm/libc/utfrune.c - 664 sys sys 1135900572 401
+sys/src/cmd/unix/drawterm/libc/utfutf.c - 664 sys sys 1135900573 391
+sys/src/cmd/unix/drawterm/libc/vfprint.c - 664 sys sys 1135900573 518
+sys/src/cmd/unix/drawterm/libc/vseprint.c - 664 sys sys 1135900573 309
+sys/src/cmd/unix/drawterm/libc/vsmprint.c - 664 sys sys 1135900573 997
+sys/src/cmd/unix/drawterm/libc/vsnprint.c - 664 sys sys 1135900573 326
 sys/src/cmd/unix/drawterm/libdraw - 20000000775 sys sys 954098713 0
 sys/src/cmd/unix/drawterm/libdraw - 20000000775 sys sys 954098713 0
-sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 954098710 111
-sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 954098710 2043
-sys/src/cmd/unix/drawterm/libdraw/bytesperline.c - 664 sys sys 954098711 538
-sys/src/cmd/unix/drawterm/libdraw/chan.c - 664 sys sys 954098711 1017
-sys/src/cmd/unix/drawterm/libdraw/defont.c - 664 sys sys 954098711 30537
-sys/src/cmd/unix/drawterm/libdraw/draw.h - 664 sys sys 954098712 13589
-sys/src/cmd/unix/drawterm/libdraw/icossin.c - 664 sys sys 954098712 2116
-sys/src/cmd/unix/drawterm/libdraw/icossin2.c - 664 sys sys 954098713 4586
-sys/src/cmd/unix/drawterm/libdraw/rectclip.c - 664 sys sys 954098713 571
-sys/src/cmd/unix/drawterm/libdraw/rgb.c - 664 sys sys 954098713 814
+sys/src/cmd/unix/drawterm/libdraw/Makefile - 664 sys sys 1135900573 293
+sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 1135900573 4095
+sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 1135900574 2839
+sys/src/cmd/unix/drawterm/libdraw/bytesperline.c - 664 sys sys 1135900574 617
+sys/src/cmd/unix/drawterm/libdraw/chan.c - 664 sys sys 1135900574 1151
+sys/src/cmd/unix/drawterm/libdraw/defont.c - 664 sys sys 1135900574 30537
+sys/src/cmd/unix/drawterm/libdraw/drawrepl.c - 664 sys sys 1135900574 314
+sys/src/cmd/unix/drawterm/libdraw/icossin.c - 664 sys sys 1135900574 2117
+sys/src/cmd/unix/drawterm/libdraw/icossin2.c - 664 sys sys 1135900574 4587
+sys/src/cmd/unix/drawterm/libdraw/rectclip.c - 664 sys sys 1135900575 571
+sys/src/cmd/unix/drawterm/libdraw/rgb.c - 664 sys sys 1135900575 1679
 sys/src/cmd/unix/drawterm/libmemdraw - 20000000775 sys sys 954098724 0
 sys/src/cmd/unix/drawterm/libmemdraw - 20000000775 sys sys 954098724 0
-sys/src/cmd/unix/drawterm/libmemdraw/alloc-win.c - 664 sys sys 954098714 300
-sys/src/cmd/unix/drawterm/libmemdraw/alloc-x11.c - 664 sys sys 954098714 4080
-sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 775 sys sys 964488227 3139
-sys/src/cmd/unix/drawterm/libmemdraw/arc.c - 664 sys sys 954098715 2612
-sys/src/cmd/unix/drawterm/libmemdraw/arctest.c - 664 sys sys 954098715 886
-sys/src/cmd/unix/drawterm/libmemdraw/cload-win.c - 664 sys sys 954098716 202
-sys/src/cmd/unix/drawterm/libmemdraw/cload-x11.c - 664 sys sys 954098716 274
-sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 775 sys sys 954098716 1352
-sys/src/cmd/unix/drawterm/libmemdraw/cmap.c - 664 sys sys 954098717 542
-sys/src/cmd/unix/drawterm/libmemdraw/cread.c - 664 sys sys 954098717 2281
-sys/src/cmd/unix/drawterm/libmemdraw/defont.c - 664 sys sys 954098718 1113
-sys/src/cmd/unix/drawterm/libmemdraw/draw-win.c - 664 sys sys 954098718 367
-sys/src/cmd/unix/drawterm/libmemdraw/draw-x11.c - 664 sys sys 954098718 4030
-sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 775 sys sys 964488227 43422
-sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c - 664 sys sys 964488226 4841
-sys/src/cmd/unix/drawterm/libmemdraw/fillpoly.c - 664 sys sys 954098720 9897
-sys/src/cmd/unix/drawterm/libmemdraw/hwdraw.c - 664 sys sys 954098720 169
-sys/src/cmd/unix/drawterm/libmemdraw/iprint.c - 664 sys sys 954098720 296
-sys/src/cmd/unix/drawterm/libmemdraw/line.c - 664 sys sys 954098721 10636
-sys/src/cmd/unix/drawterm/libmemdraw/load-win.c - 664 sys sys 954098721 200
-sys/src/cmd/unix/drawterm/libmemdraw/load-x11.c - 664 sys sys 954098721 272
-sys/src/cmd/unix/drawterm/libmemdraw/load.c - 775 sys sys 954098722 1510
-sys/src/cmd/unix/drawterm/libmemdraw/memdraw.h - 664 sys sys 954098722 5880
-sys/src/cmd/unix/drawterm/libmemdraw/poly.c - 664 sys sys 954098723 667
-sys/src/cmd/unix/drawterm/libmemdraw/read.c - 664 sys sys 954098723 2052
-sys/src/cmd/unix/drawterm/libmemdraw/string.c - 664 sys sys 954098723 1080
-sys/src/cmd/unix/drawterm/libmemdraw/subfont.c - 664 sys sys 954098724 575
-sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 775 sys sys 954098724 449
-sys/src/cmd/unix/drawterm/libmemdraw/xmem.h - 664 sys sys 954098725 1508
+sys/src/cmd/unix/drawterm/libmemdraw/Makefile - 664 sys sys 1135900575 391
+sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 664 sys sys 1135900575 3309
+sys/src/cmd/unix/drawterm/libmemdraw/alpha.hoc - 664 sys sys 1135900575 220
+sys/src/cmd/unix/drawterm/libmemdraw/arc.c - 664 sys sys 1135900575 2608
+sys/src/cmd/unix/drawterm/libmemdraw/arctest.c - 664 sys sys 1135900575 865
+sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 664 sys sys 1135900576 1338
+sys/src/cmd/unix/drawterm/libmemdraw/cmap.c - 664 sys sys 1135900576 25150
+sys/src/cmd/unix/drawterm/libmemdraw/cread.c - 664 sys sys 1135900576 1982
+sys/src/cmd/unix/drawterm/libmemdraw/defont.c - 664 sys sys 1135900576 1293
+sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 664 sys sys 1135900576 54684
+sys/src/cmd/unix/drawterm/libmemdraw/drawtest.c - 664 sys sys 1135900576 23441
+sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c - 664 sys sys 1135900576 4864
+sys/src/cmd/unix/drawterm/libmemdraw/fillpoly.c - 664 sys sys 1135900576 9973
+sys/src/cmd/unix/drawterm/libmemdraw/hwdraw.c - 664 sys sys 1135900577 159
+sys/src/cmd/unix/drawterm/libmemdraw/iprint.c - 664 sys sys 1135900577 128
+sys/src/cmd/unix/drawterm/libmemdraw/line.c - 664 sys sys 1135900577 11059
+sys/src/cmd/unix/drawterm/libmemdraw/load.c - 664 sys sys 1135900577 1496
+sys/src/cmd/unix/drawterm/libmemdraw/mkcmap.c - 664 sys sys 1135900577 1394
+sys/src/cmd/unix/drawterm/libmemdraw/openmemsubfont.c - 664 sys sys 1135900577 900
+sys/src/cmd/unix/drawterm/libmemdraw/poly.c - 664 sys sys 1135900577 484
+sys/src/cmd/unix/drawterm/libmemdraw/read.c - 664 sys sys 1135900577 2159
+sys/src/cmd/unix/drawterm/libmemdraw/string.c - 664 sys sys 1135900577 1081
+sys/src/cmd/unix/drawterm/libmemdraw/subfont.c - 664 sys sys 1135900578 561
+sys/src/cmd/unix/drawterm/libmemdraw/times - 664 sys sys 1135900578 586
+sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 664 sys sys 1135900578 435
+sys/src/cmd/unix/drawterm/libmemdraw/write.c - 664 sys sys 1135900578 4375
 sys/src/cmd/unix/drawterm/libmemlayer - 20000000775 sys sys 954098729 0
 sys/src/cmd/unix/drawterm/libmemlayer - 20000000775 sys sys 954098729 0
-sys/src/cmd/unix/drawterm/libmemlayer/draw.c - 664 sys sys 954098725 3913
-sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 775 sys sys 954098725 1799
-sys/src/cmd/unix/drawterm/libmemlayer/layerop.c - 664 sys sys 954098726 2587
-sys/src/cmd/unix/drawterm/libmemlayer/ldelete.c - 664 sys sys 954098726 1208
-sys/src/cmd/unix/drawterm/libmemlayer/lhide.c - 664 sys sys 954098726 1689
-sys/src/cmd/unix/drawterm/libmemlayer/line.c - 664 sys sys 954098727 2561
-sys/src/cmd/unix/drawterm/libmemlayer/load.c - 664 sys sys 954098727 1058
-sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c - 664 sys sys 954098727 2530
-sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 954098728 732
-sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 954098728 1179
-sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 954098729 1089
-sys/src/cmd/unix/drawterm/libmemlayer/memlayer.h - 664 sys sys 954098729 1691
+sys/src/cmd/unix/drawterm/libmemlayer/Makefile - 664 sys sys 1135900578 319
+sys/src/cmd/unix/drawterm/libmemlayer/draw.c - 664 sys sys 1135900578 4064
+sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 664 sys sys 1135900578 1794
+sys/src/cmd/unix/drawterm/libmemlayer/layerop.c - 664 sys sys 1135900578 2641
+sys/src/cmd/unix/drawterm/libmemlayer/ldelete.c - 664 sys sys 1135900579 1183
+sys/src/cmd/unix/drawterm/libmemlayer/lhide.c - 664 sys sys 1135900579 1675
+sys/src/cmd/unix/drawterm/libmemlayer/line.c - 664 sys sys 1135900579 2587
+sys/src/cmd/unix/drawterm/libmemlayer/load.c - 664 sys sys 1135900579 1032
+sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c - 664 sys sys 1135900579 2507
+sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 1135900579 703
+sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 1135900579 1289
+sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 1135900579 1062
+sys/src/cmd/unix/drawterm/libmemlayer/unload.c - 664 sys sys 1135900579 1007
+sys/src/cmd/unix/drawterm/libmp - 20000000775 sys sys 1135900584 0
+sys/src/cmd/unix/drawterm/libmp/Makefile - 664 sys sys 1135900580 602
+sys/src/cmd/unix/drawterm/libmp/betomp.c - 664 sys sys 1135900580 577
+sys/src/cmd/unix/drawterm/libmp/crt.c - 664 sys sys 1135900580 2050
+sys/src/cmd/unix/drawterm/libmp/crttest.c - 664 sys sys 1135900580 813
+sys/src/cmd/unix/drawterm/libmp/dat.h - 664 sys sys 1135900580 464
+sys/src/cmd/unix/drawterm/libmp/letomp.c - 664 sys sys 1135900581 455
+sys/src/cmd/unix/drawterm/libmp/mpadd.c - 664 sys sys 1135900581 783
+sys/src/cmd/unix/drawterm/libmp/mpaux.c - 664 sys sys 1135900581 2564
+sys/src/cmd/unix/drawterm/libmp/mpcmp.c - 664 sys sys 1135900581 462
+sys/src/cmd/unix/drawterm/libmp/mpdigdiv.c - 664 sys sys 1135900581 732
+sys/src/cmd/unix/drawterm/libmp/mpdiv.c - 664 sys sys 1135900581 2423
+sys/src/cmd/unix/drawterm/libmp/mpeuclid.c - 664 sys sys 1135900581 1226
+sys/src/cmd/unix/drawterm/libmp/mpexp.c - 664 sys sys 1135900581 1149
+sys/src/cmd/unix/drawterm/libmp/mpextendedgcd.c - 664 sys sys 1135900581 1613
+sys/src/cmd/unix/drawterm/libmp/mpfmt.c - 664 sys sys 1135900582 2729
+sys/src/cmd/unix/drawterm/libmp/mpinvert.c - 664 sys sys 1135900582 394
+sys/src/cmd/unix/drawterm/libmp/mpleft.c - 664 sys sys 1135900582 838
+sys/src/cmd/unix/drawterm/libmp/mpmod.c - 664 sys sys 1135900582 247
+sys/src/cmd/unix/drawterm/libmp/mpmul.c - 664 sys sys 1135900582 3110
+sys/src/cmd/unix/drawterm/libmp/mprand.c - 664 sys sys 1135900582 584
+sys/src/cmd/unix/drawterm/libmp/mpright.c - 664 sys sys 1135900582 695
+sys/src/cmd/unix/drawterm/libmp/mpsub.c - 664 sys sys 1135900582 792
+sys/src/cmd/unix/drawterm/libmp/mptobe.c - 664 sys sys 1135900582 879
+sys/src/cmd/unix/drawterm/libmp/mptoi.c - 664 sys sys 1135900582 553
+sys/src/cmd/unix/drawterm/libmp/mptole.c - 664 sys sys 1135900583 786
+sys/src/cmd/unix/drawterm/libmp/mptoui.c - 664 sys sys 1135900583 413
+sys/src/cmd/unix/drawterm/libmp/mptouv.c - 664 sys sys 1135900583 727
+sys/src/cmd/unix/drawterm/libmp/mptov.c - 664 sys sys 1135900583 995
+sys/src/cmd/unix/drawterm/libmp/mpvecadd.c - 664 sys sys 1135900583 519
+sys/src/cmd/unix/drawterm/libmp/mpveccmp.c - 664 sys sys 1135900583 402
+sys/src/cmd/unix/drawterm/libmp/mpvecdigmuladd.c - 664 sys sys 1135900583 1582
+sys/src/cmd/unix/drawterm/libmp/mpvecsub.c - 664 sys sys 1135900583 523
+sys/src/cmd/unix/drawterm/libmp/os.h - 664 sys sys 1135900583 34
+sys/src/cmd/unix/drawterm/libmp/reduce - 664 sys sys 1135900584 306
+sys/src/cmd/unix/drawterm/libmp/strtomp.c - 664 sys sys 1135900584 3026
 sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
 sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
-sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1077480282 17511
-sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1077480282 1078
-sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1077480282 860
-sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1077480283 662
-sys/src/cmd/unix/drawterm/libsec/libsec.h - 664 sys sys 1077480283 8912
-sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1077480283 4275
-sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1077480283 3313
-sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1077480283 5030
-sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1077480284 1430
-sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1077480284 2294
-sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1077480284 4678
-sys/src/cmd/unix/drawterm/libsec/u64.c - 664 sys sys 1077480285 3270
-sys/src/cmd/unix/drawterm/linux.c - 664 sys sys 963353235 9886
-sys/src/cmd/unix/drawterm/lock-irix.s - 664 sys sys 954098631 290
-sys/src/cmd/unix/drawterm/lock-osf1.s - 664 sys sys 954098631 887
-sys/src/cmd/unix/drawterm/lock.c - 664 sys sys 954098632 627
-sys/src/cmd/unix/drawterm/mallocz.c - 664 sys sys 954098632 104
-sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1077480273 2572
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 1077480274 555
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1077480274 549
-sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 1077480275 542
-sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1080159060 539
-sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 1077480276 553
-sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 1077480276 594
-sys/src/cmd/unix/drawterm/mkfile-Solaris-386 - 664 sys sys 954098636 25
-sys/src/cmd/unix/drawterm/mkfile-Solaris-sparc - 664 sys sys 954098637 27
-sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 1077480277 1353
-sys/src/cmd/unix/drawterm/nan.c - 664 sys sys 954098638 718
-sys/src/cmd/unix/drawterm/ndrawterm.mdp - 664 sys sys 954098639 33792
-sys/src/cmd/unix/drawterm/netmkaddr.c - 664 sys sys 954098639 784
-sys/src/cmd/unix/drawterm/new.bat - 664 sys sys 954098640 33
-sys/src/cmd/unix/drawterm/ns.c - 664 sys sys 954098641 2885
-sys/src/cmd/unix/drawterm/os.h - 664 sys sys 1019839871 303
-sys/src/cmd/unix/drawterm/passtokey.c - 664 sys sys 954098642 526
-sys/src/cmd/unix/drawterm/pipe.c - 664 sys sys 954098642 200
-sys/src/cmd/unix/drawterm/posix.c - 664 sys sys 964470494 8065
-sys/src/cmd/unix/drawterm/pow10.c - 664 sys sys 954098643 1121
-sys/src/cmd/unix/drawterm/print.c - 664 sys sys 954098644 1069
-sys/src/cmd/unix/drawterm/proc.c - 664 sys sys 954098645 3355
-sys/src/cmd/unix/drawterm/pushssl.c - 664 sys sys 1077480278 897
-sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 1077480279 14729
-sys/src/cmd/unix/drawterm/readn.c - 664 sys sys 954098646 219
-sys/src/cmd/unix/drawterm/ref.c - 664 sys sys 954098646 216
-sys/src/cmd/unix/drawterm/rune.c - 664 sys sys 954098647 2085
-sys/src/cmd/unix/drawterm/rwlock.c - 664 sys sys 954098647 580
-sys/src/cmd/unix/drawterm/screen-win.c - 664 sys sys 954098648 11441
-sys/src/cmd/unix/drawterm/screen-x11.c - 664 sys sys 964470495 21726
-sys/src/cmd/unix/drawterm/screen.h - 664 sys sys 954098649 1083
-sys/src/cmd/unix/drawterm/solaris.c - 664 sys sys 954098649 7927
-sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 1077480280 13888
-sys/src/cmd/unix/drawterm/syscall.c - 664 sys sys 954098651 12813
-sys/src/cmd/unix/drawterm/tabs.c - 664 sys sys 954098651 56506
-sys/src/cmd/unix/drawterm/tabs.h - 664 sys sys 954098652 681
-sys/src/cmd/unix/drawterm/term.c - 664 sys sys 954098652 3897
-sys/src/cmd/unix/drawterm/tokenize.c - 664 sys sys 954098653 598
-sys/src/cmd/unix/drawterm/unix.h - 664 sys sys 954098653 263
-sys/src/cmd/unix/drawterm/utflen.c - 664 sys sys 954098654 228
-sys/src/cmd/unix/drawterm/utfrune.c - 664 sys sys 954098654 386
-sys/src/cmd/unix/drawterm/werrstr.c - 664 sys sys 954098655 168
-sys/src/cmd/unix/drawterm/windows.c - 664 sys sys 954098655 8315
-sys/src/cmd/unix/drawterm/windows.h - 664 sys sys 954098656 401
-sys/src/cmd/unix/drawterm/winscreen.c - 664 sys sys 954098657 11393
-sys/src/cmd/unix/drawterm/wstrtoutf.c - 664 sys sys 954098657 393
+sys/src/cmd/unix/drawterm/libsec/Makefile - 664 sys sys 1135900584 771
+sys/src/cmd/unix/drawterm/libsec/aes.c - 664 sys sys 1135900584 64145
+sys/src/cmd/unix/drawterm/libsec/blowfish.c - 664 sys sys 1135900584 19676
+sys/src/cmd/unix/drawterm/libsec/decodepem.c - 664 sys sys 1135900584 1371
+sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1135900584 17496
+sys/src/cmd/unix/drawterm/libsec/des3CBC.c - 664 sys sys 1135900584 1135
+sys/src/cmd/unix/drawterm/libsec/des3ECB.c - 664 sys sys 1135900585 917
+sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1135900585 1079
+sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1135900585 861
+sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1135900585 647
+sys/src/cmd/unix/drawterm/libsec/dsaalloc.c - 664 sys sys 1135900585 864
+sys/src/cmd/unix/drawterm/libsec/dsagen.c - 664 sys sys 1135900585 1237
+sys/src/cmd/unix/drawterm/libsec/dsaprimes.c - 664 sys sys 1135900585 1881
+sys/src/cmd/unix/drawterm/libsec/dsaprivtopub.c - 664 sys sys 1135900585 279
+sys/src/cmd/unix/drawterm/libsec/dsasign.c - 664 sys sys 1135900586 934
+sys/src/cmd/unix/drawterm/libsec/dsaverify.c - 664 sys sys 1135900586 909
+sys/src/cmd/unix/drawterm/libsec/egalloc.c - 664 sys sys 1135900586 778
+sys/src/cmd/unix/drawterm/libsec/egdecrypt.c - 664 sys sys 1135900586 564
+sys/src/cmd/unix/drawterm/libsec/egencrypt.c - 664 sys sys 1135900586 806
+sys/src/cmd/unix/drawterm/libsec/eggen.c - 664 sys sys 1135900586 413
+sys/src/cmd/unix/drawterm/libsec/egprivtopub.c - 664 sys sys 1135900586 273
+sys/src/cmd/unix/drawterm/libsec/egsign.c - 664 sys sys 1135900586 807
+sys/src/cmd/unix/drawterm/libsec/egtest.c - 664 sys sys 1135900587 655
+sys/src/cmd/unix/drawterm/libsec/egverify.c - 664 sys sys 1135900587 519
+sys/src/cmd/unix/drawterm/libsec/fastrand.c - 664 sys sys 1135900587 258
+sys/src/cmd/unix/drawterm/libsec/genprime.c - 664 sys sys 1135900587 535
+sys/src/cmd/unix/drawterm/libsec/genrandom.c - 664 sys sys 1135900587 1171
+sys/src/cmd/unix/drawterm/libsec/gensafeprime.c - 664 sys sys 1135900587 741
+sys/src/cmd/unix/drawterm/libsec/genstrongprime.c - 664 sys sys 1135900587 1039
+sys/src/cmd/unix/drawterm/libsec/hmac.c - 664 sys sys 1135900587 1167
+sys/src/cmd/unix/drawterm/libsec/hmactest.c - 664 sys sys 1135900588 344
+sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1135900588 4260
+sys/src/cmd/unix/drawterm/libsec/md4test.c - 664 sys sys 1135900588 537
+sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1135900588 3254
+sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1135900588 5015
+sys/src/cmd/unix/drawterm/libsec/md5pickle.c - 664 sys sys 1135900588 657
+sys/src/cmd/unix/drawterm/libsec/nfastrand.c - 664 sys sys 1135900588 327
+sys/src/cmd/unix/drawterm/libsec/os.h - 664 sys sys 1135900588 33
+sys/src/cmd/unix/drawterm/libsec/primetest.c - 664 sys sys 1135900589 2486
+sys/src/cmd/unix/drawterm/libsec/prng.c - 664 sys sys 1135900589 187
+sys/src/cmd/unix/drawterm/libsec/probably_prime.c - 664 sys sys 1135900589 1567
+sys/src/cmd/unix/drawterm/libsec/ranlib.core - 664 sys sys 1135900590 430080
+sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1135900590 1415
+sys/src/cmd/unix/drawterm/libsec/readcert.c - 664 sys sys 1135900590 759
+sys/src/cmd/unix/drawterm/libsec/rsaalloc.c - 664 sys sys 1135900590 657
+sys/src/cmd/unix/drawterm/libsec/rsadecrypt.c - 664 sys sys 1135900590 749
+sys/src/cmd/unix/drawterm/libsec/rsaencrypt.c - 664 sys sys 1135900590 192
+sys/src/cmd/unix/drawterm/libsec/rsafill.c - 664 sys sys 1135900590 1104
+sys/src/cmd/unix/drawterm/libsec/rsagen.c - 664 sys sys 1135900591 1451
+sys/src/cmd/unix/drawterm/libsec/rsaprivtopub.c - 664 sys sys 1135900591 237
+sys/src/cmd/unix/drawterm/libsec/rsatest.c - 664 sys sys 1135900591 1095
+sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1135900591 2279
+sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1135900591 4673
+sys/src/cmd/unix/drawterm/libsec/sha1pickle.c - 664 sys sys 1135900591 717
+sys/src/cmd/unix/drawterm/libsec/smallprimes.c - 664 sys sys 1135900591 6851
+sys/src/cmd/unix/drawterm/libsec/smallprimetest.c - 664 sys sys 1135900591 70640
+sys/src/cmd/unix/drawterm/libsec/thumb.c - 664 sys sys 1135900592 1891
+sys/src/cmd/unix/drawterm/libsec/tlshand.c - 664 sys sys 1135900592 53926
+sys/src/cmd/unix/drawterm/libsec/x509.c - 664 sys sys 1135900592 50237
+sys/src/cmd/unix/drawterm/main.c - 664 sys sys 1135900536 2440
+sys/src/cmd/unix/drawterm/posix-386 - 20000000775 sys sys 1135900540 0
+sys/src/cmd/unix/drawterm/posix-386/Makefile - 664 sys sys 1135900540 378
+sys/src/cmd/unix/drawterm/posix-386/getcallerpc.c - 664 sys sys 1135900540 90
+sys/src/cmd/unix/drawterm/posix-386/md5block.spp - 664 sys sys 1135900540 6472
+sys/src/cmd/unix/drawterm/posix-386/sha1block.spp - 664 sys sys 1135900540 4749
+sys/src/cmd/unix/drawterm/posix-386/tas.c - 664 sys sys 1135900540 270
+sys/src/cmd/unix/drawterm/posix-factotum.c - 664 sys sys 1135900536 1880
+sys/src/cmd/unix/drawterm/posix-mips - 20000000775 sys sys 1135900037 0
+sys/src/cmd/unix/drawterm/posix-power - 20000000775 sys sys 1135900541 0
+sys/src/cmd/unix/drawterm/posix-power/Makefile - 664 sys sys 1135900541 291
+sys/src/cmd/unix/drawterm/posix-power/getcallerpc.c - 664 sys sys 1135900541 90
+sys/src/cmd/unix/drawterm/posix-power/md5block.c - 664 sys sys 1135900541 5032
+sys/src/cmd/unix/drawterm/posix-power/sha1block.c - 664 sys sys 1135900541 4710
+sys/src/cmd/unix/drawterm/posix-power/tas.c - 664 sys sys 1135900541 943
+sys/src/cmd/unix/drawterm/readcons.c - 664 sys sys 1135900536 1842
+sys/src/cmd/unix/drawterm/resource.h - 664 sys sys 1135900536 457
+sys/src/cmd/unix/drawterm/secstore.c - 664 sys sys 1135900536 15742
+sys/src/cmd/unix/drawterm/win32-386 - 20000000775 sys sys 1135900544 0
+sys/src/cmd/unix/drawterm/win32-386/Makefile - 664 sys sys 1135900544 291
+sys/src/cmd/unix/drawterm/win32-386/getcallerpc.c - 664 sys sys 1135900544 90
+sys/src/cmd/unix/drawterm/win32-386/md5block.spp - 664 sys sys 1135900544 6591
+sys/src/cmd/unix/drawterm/win32-386/sha1block.spp - 664 sys sys 1135900544 4912
+sys/src/cmd/unix/drawterm/win32-386/tas.c - 664 sys sys 1135900544 270
+sys/src/cmd/unix/drawterm/win32-factotum.c - 664 sys sys 1135900536 238
 sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs/LICENSE - 664 sys sys 1132498433 735
 sys/src/cmd/unix/u9fs/LICENSE - 664 sys sys 1132498433 735
@@ -13445,7 +13757,7 @@ sys/src/cmd/usb/audio/usbaudioctl.c - 664 sys sys 1101906325 17266
 sys/src/cmd/usb/audio/usbaudioctl.h - 664 sys sys 1100568597 600
 sys/src/cmd/usb/audio/usbaudioctl.h - 664 sys sys 1100568597 600
 sys/src/cmd/usb/lib - 20000000775 sys sys 1018369393 0
 sys/src/cmd/usb/lib - 20000000775 sys sys 1018369393 0
 sys/src/cmd/usb/lib/device.c - 664 sys sys 1099760882 2968
 sys/src/cmd/usb/lib/device.c - 664 sys sys 1099760882 2968
-sys/src/cmd/usb/lib/dump.c - 664 sys sys 1103381265 12921
+sys/src/cmd/usb/lib/dump.c - 664 sys sys 1135896862 12915
 sys/src/cmd/usb/lib/fmt.c - 664 sys sys 1091204978 291
 sys/src/cmd/usb/lib/fmt.c - 664 sys sys 1091204978 291
 sys/src/cmd/usb/lib/mkfile - 664 sys sys 1091204979 204
 sys/src/cmd/usb/lib/mkfile - 664 sys sys 1091204979 204
 sys/src/cmd/usb/lib/setup.c - 664 sys sys 1091204978 1953
 sys/src/cmd/usb/lib/setup.c - 664 sys sys 1091204978 1953
@@ -14601,14 +14913,14 @@ sys/src/libmach/vcodas.c - 664 sys sys 1131289385 10258
 sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
 sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
 sys/src/libmach/vobj.c - 664 sys sys 1091732625 2206
 sys/src/libmach/vobj.c - 664 sys sys 1091732625 2206
 sys/src/libmemdraw - 20000000775 sys sys 985020762 0
 sys/src/libmemdraw - 20000000775 sys sys 985020762 0
-sys/src/libmemdraw/alloc.c - 664 sys sys 1135394719 3332
+sys/src/libmemdraw/alloc.c - 664 sys sys 1135895512 3334
 sys/src/libmemdraw/alpha.hoc - 664 sys sys 944961741 220
 sys/src/libmemdraw/alpha.hoc - 664 sys sys 944961741 220
 sys/src/libmemdraw/arc.c - 664 sys sys 1039752932 2608
 sys/src/libmemdraw/arc.c - 664 sys sys 1039752932 2608
 sys/src/libmemdraw/arctest.c - 664 sys sys 1045502219 865
 sys/src/libmemdraw/arctest.c - 664 sys sys 1045502219 865
 sys/src/libmemdraw/cload.c - 664 sys sys 944961741 1337
 sys/src/libmemdraw/cload.c - 664 sys sys 944961741 1337
 sys/src/libmemdraw/cmap.c - 664 sys sys 1029430942 25150
 sys/src/libmemdraw/cmap.c - 664 sys sys 1029430942 25150
 sys/src/libmemdraw/cread.c - 664 sys sys 1014930216 1982
 sys/src/libmemdraw/cread.c - 664 sys sys 1014930216 1982
-sys/src/libmemdraw/defont.c - 664 sys sys 944961741 1288
+sys/src/libmemdraw/defont.c - 664 sys sys 1135895512 1290
 sys/src/libmemdraw/draw.c - 664 sys sys 1114867396 55720
 sys/src/libmemdraw/draw.c - 664 sys sys 1114867396 55720
 sys/src/libmemdraw/drawtest.c - 664 sys sys 1045502228 23441
 sys/src/libmemdraw/drawtest.c - 664 sys sys 1045502228 23441
 sys/src/libmemdraw/ellipse.c - 664 sys sys 1039752933 4866
 sys/src/libmemdraw/ellipse.c - 664 sys sys 1039752933 4866

+ 490 - 178
dist/replica/plan9.db

@@ -37,6 +37,7 @@
 386/bin/ape/stty - 775 sys sys 1130384232 41057
 386/bin/ape/stty - 775 sys sys 1130384232 41057
 386/bin/ape/tar - 775 sys sys 1135570769 61941
 386/bin/ape/tar - 775 sys sys 1135570769 61941
 386/bin/ape/uname - 775 sys sys 1134151328 132699
 386/bin/ape/uname - 775 sys sys 1134151328 132699
+386/bin/aquarela - 775 sys sys 1135914849 331831
 386/bin/ar - 775 sys sys 1135570769 111942
 386/bin/ar - 775 sys sys 1135570769 111942
 386/bin/archfs - 775 sys sys 1135570769 146849
 386/bin/archfs - 775 sys sys 1135570769 146849
 386/bin/ascii - 775 sys sys 1135570770 64641
 386/bin/ascii - 775 sys sys 1135570770 64641
@@ -176,6 +177,7 @@
 386/bin/cfs - 775 sys sys 1135570797 128025
 386/bin/cfs - 775 sys sys 1135570797 128025
 386/bin/chgrp - 775 sys sys 1135570798 59279
 386/bin/chgrp - 775 sys sys 1135570798 59279
 386/bin/chmod - 775 sys sys 1135570798 62275
 386/bin/chmod - 775 sys sys 1135570798 62275
+386/bin/cifscmd - 775 sys sys 1135914850 342709
 386/bin/cleanname - 775 sys sys 1135570798 58298
 386/bin/cleanname - 775 sys sys 1135570798 58298
 386/bin/clock - 775 sys sys 1135570798 158281
 386/bin/clock - 775 sys sys 1135570798 158281
 386/bin/cmp - 775 sys sys 1130384270 40583
 386/bin/cmp - 775 sys sys 1130384270 40583
@@ -7685,7 +7687,7 @@ sys/man/8/checkarenas - 664 sys sys 1019866709 669
 sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cron - 664 sys sys 1063858596 1867
 sys/man/8/cron - 664 sys sys 1063858596 1867
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
-sys/man/8/drawterm - 664 sys sys 958419689 2458
+sys/man/8/drawterm - 664 sys sys 1135901219 1741
 sys/man/8/fossilcons - 664 sys sys 1127560168 17789
 sys/man/8/fossilcons - 664 sys sys 1127560168 17789
 sys/man/8/fs - 664 sys sys 1055701170 15029
 sys/man/8/fs - 664 sys sys 1055701170 15029
 sys/man/8/fsconfig - 664 sys sys 1045501600 8142
 sys/man/8/fsconfig - 664 sys sys 1045501600 8142
@@ -9307,6 +9309,85 @@ sys/src/cmd/acme/time.c - 664 sys sys 1014926095 1783
 sys/src/cmd/acme/util.c - 664 sys sys 1107154483 7984
 sys/src/cmd/acme/util.c - 664 sys sys 1107154483 7984
 sys/src/cmd/acme/wind.c - 664 sys sys 1122526112 11233
 sys/src/cmd/acme/wind.c - 664 sys sys 1122526112 11233
 sys/src/cmd/acme/xfid.c - 664 sys sys 1125314186 19766
 sys/src/cmd/acme/xfid.c - 664 sys sys 1125314186 19766
+sys/src/cmd/aquarela - 20000000775 sys sys 1135892145 0
+sys/src/cmd/aquarela/COPYRIGHT - 664 sys sys 1135892145 43
+sys/src/cmd/aquarela/addname.c - 664 sys sys 1135892108 1281
+sys/src/cmd/aquarela/alarm.c - 664 sys sys 1135892108 2194
+sys/src/cmd/aquarela/alloc.c - 664 sys sys 1135892108 245
+sys/src/cmd/aquarela/aquarela.c - 664 sys sys 1135892108 6986
+sys/src/cmd/aquarela/cifscmd.c - 664 sys sys 1135892108 4430
+sys/src/cmd/aquarela/client.c - 664 sys sys 1135892108 2724
+sys/src/cmd/aquarela/dump.c - 664 sys sys 1135892108 2864
+sys/src/cmd/aquarela/findname.c - 664 sys sys 1135892108 1351
+sys/src/cmd/aquarela/headers.h - 664 sys sys 1135892108 185
+sys/src/cmd/aquarela/message.c - 664 sys sys 1135892108 1260
+sys/src/cmd/aquarela/mkfile - 664 sys sys 1135892109 1487
+sys/src/cmd/aquarela/nb.c - 664 sys sys 1135892109 538
+sys/src/cmd/aquarela/nbdgram.c - 664 sys sys 1135892109 4364
+sys/src/cmd/aquarela/nbdgramconv.c - 664 sys sys 1135892109 2339
+sys/src/cmd/aquarela/nbdgramdump.c - 664 sys sys 1135892109 506
+sys/src/cmd/aquarela/nblistener.c - 664 sys sys 1135892109 738
+sys/src/cmd/aquarela/nbname.c - 664 sys sys 1135892109 5457
+sys/src/cmd/aquarela/nbns.c - 664 sys sys 1135892109 2747
+sys/src/cmd/aquarela/nbnsconv.c - 664 sys sys 1135892109 6257
+sys/src/cmd/aquarela/nbresolve.c - 664 sys sys 1135892109 672
+sys/src/cmd/aquarela/nbss.c - 664 sys sys 1135892110 8126
+sys/src/cmd/aquarela/netbios.h - 664 sys sys 1135892110 5967
+sys/src/cmd/aquarela/smb.h - 664 sys sys 1135892110 9492
+sys/src/cmd/aquarela/smballoc.c - 664 sys sys 1135892110 508
+sys/src/cmd/aquarela/smbbrowse.c - 664 sys sys 1135892110 1473
+sys/src/cmd/aquarela/smbbuffer.c - 664 sys sys 1135892110 9717
+sys/src/cmd/aquarela/smbclientopen.c - 664 sys sys 1135892110 1428
+sys/src/cmd/aquarela/smbcomclose.c - 664 sys sys 1135892110 578
+sys/src/cmd/aquarela/smbcomcreatedir.c - 664 sys sys 1135892110 692
+sys/src/cmd/aquarela/smbcomdelete.c - 664 sys sys 1135892110 1575
+sys/src/cmd/aquarela/smbcomdeletedir.c - 664 sys sys 1135892111 659
+sys/src/cmd/aquarela/smbcomdir.c - 664 sys sys 1135892111 1113
+sys/src/cmd/aquarela/smbcomecho.c - 664 sys sys 1135892111 819
+sys/src/cmd/aquarela/smbcomfindclose2.c - 664 sys sys 1135892111 319
+sys/src/cmd/aquarela/smbcomflush.c - 664 sys sys 1135892111 707
+sys/src/cmd/aquarela/smbcomlocking.c - 664 sys sys 1135892111 3701
+sys/src/cmd/aquarela/smbcommon.c - 664 sys sys 1135892111 8652
+sys/src/cmd/aquarela/smbcomopen.c - 664 sys sys 1135892111 18350
+sys/src/cmd/aquarela/smbcomquery.c - 664 sys sys 1135892111 2715
+sys/src/cmd/aquarela/smbcomread.c - 664 sys sys 1135892112 2601
+sys/src/cmd/aquarela/smbcomrename.c - 664 sys sys 1135892112 1259
+sys/src/cmd/aquarela/smbcomsessionsetupandx.c - 664 sys sys 1135892112 6175
+sys/src/cmd/aquarela/smbcomsetinfo.c - 664 sys sys 1135892112 2985
+sys/src/cmd/aquarela/smbcomtransaction.c - 664 sys sys 1135892112 4041
+sys/src/cmd/aquarela/smbcomtreeconnectandx.c - 664 sys sys 1135892112 3269
+sys/src/cmd/aquarela/smbcomtreedisconnect.c - 664 sys sys 1135892112 290
+sys/src/cmd/aquarela/smbcomwrite.c - 664 sys sys 1135892112 3312
+sys/src/cmd/aquarela/smbconnect.c - 664 sys sys 1135892112 9040
+sys/src/cmd/aquarela/smbconv.c - 664 sys sys 1135892112 531
+sys/src/cmd/aquarela/smbdat.h - 664 sys sys 1135892113 6649
+sys/src/cmd/aquarela/smbdircache.c - 664 sys sys 1135892113 631
+sys/src/cmd/aquarela/smbfile.c - 664 sys sys 1135892113 438
+sys/src/cmd/aquarela/smbfns.h - 664 sys sys 1135892113 12190
+sys/src/cmd/aquarela/smbglobals.c - 664 sys sys 1135892113 1096
+sys/src/cmd/aquarela/smbidmap.c - 664 sys sys 1135892113 2178
+sys/src/cmd/aquarela/smblisten.c - 664 sys sys 1135892113 2592
+sys/src/cmd/aquarela/smblog.c - 664 sys sys 1135892113 1841
+sys/src/cmd/aquarela/smbnegotiate.c - 664 sys sys 1135892113 2933
+sys/src/cmd/aquarela/smboptable.c - 664 sys sys 1135892113 5826
+sys/src/cmd/aquarela/smbpath.c - 664 sys sys 1135892114 393
+sys/src/cmd/aquarela/smbrap2.c - 664 sys sys 1135892114 11628
+sys/src/cmd/aquarela/smbrap2client.c - 664 sys sys 1135892114 3082
+sys/src/cmd/aquarela/smbrep.c - 664 sys sys 1135892114 1033
+sys/src/cmd/aquarela/smbresponse.c - 664 sys sys 1135892114 2820
+sys/src/cmd/aquarela/smbservice.c - 664 sys sys 1135892114 2335
+sys/src/cmd/aquarela/smbsharedfile.c - 664 sys sys 1135892114 6006
+sys/src/cmd/aquarela/smbstring.c - 664 sys sys 1135892114 4152
+sys/src/cmd/aquarela/smbtime.c - 664 sys sys 1135892114 1232
+sys/src/cmd/aquarela/smbtrans2client.c - 664 sys sys 1135892114 3726
+sys/src/cmd/aquarela/smbtrans2find.c - 664 sys sys 1135892115 9041
+sys/src/cmd/aquarela/smbtrans2query.c - 664 sys sys 1135892115 8215
+sys/src/cmd/aquarela/smbtrans2set.c - 664 sys sys 1135892115 2440
+sys/src/cmd/aquarela/smbtransaction.c - 664 sys sys 1135892115 16684
+sys/src/cmd/aquarela/smbtree.c - 664 sys sys 1135892115 1314
+sys/src/cmd/aquarela/testconnect.c - 664 sys sys 1135892115 1533
+sys/src/cmd/aquarela/testnbdgram.c - 664 sys sys 1135892115 2919
+sys/src/cmd/aquarela/testtime.c - 664 sys sys 1135892115 446
 sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
 sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
 sys/src/cmd/archfs.c - 664 sys sys 1014925694 3871
 sys/src/cmd/archfs.c - 664 sys sys 1014925694 3871
 sys/src/cmd/ascii.c - 664 sys sys 1134233061 3980
 sys/src/cmd/ascii.c - 664 sys sys 1134233061 3980
@@ -13010,6 +13091,7 @@ sys/src/cmd/tcs/font/qbits.c - 664 sys sys 944961251 2037
 sys/src/cmd/tcs/gb.c - 664 sys sys 944961288 62707
 sys/src/cmd/tcs/gb.c - 664 sys sys 944961288 62707
 sys/src/cmd/tcs/gb.h - 664 sys sys 944961287 183
 sys/src/cmd/tcs/gb.h - 664 sys sys 944961287 183
 sys/src/cmd/tcs/hdr.h - 664 sys sys 944961287 1213
 sys/src/cmd/tcs/hdr.h - 664 sys sys 944961287 1213
+sys/src/cmd/tcs/html.c - 664 sys sys 1135893400 5237
 sys/src/cmd/tcs/jis.h - 664 sys sys 944961287 2873
 sys/src/cmd/tcs/jis.h - 664 sys sys 944961287 2873
 sys/src/cmd/tcs/ksc.c - 664 sys sys 944961289 72413
 sys/src/cmd/tcs/ksc.c - 664 sys sys 944961289 72413
 sys/src/cmd/tcs/ksc.h - 664 sys sys 944961287 112
 sys/src/cmd/tcs/ksc.h - 664 sys sys 944961287 112
@@ -13085,185 +13167,415 @@ sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.8 - 664 sys sys 960684604 10864
 sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.c - 664 sys sys 960684605 25118
 sys/src/cmd/unix/9pfreebsd/mount_9fs/mount_9fs.c - 664 sys sys 960684605 25118
 sys/src/cmd/unix/README - 664 sys sys 1128520385 1735
 sys/src/cmd/unix/README - 664 sys sys 1128520385 1735
 sys/src/cmd/unix/drawterm - 20000000775 sys sys 964488190 0
 sys/src/cmd/unix/drawterm - 20000000775 sys sys 964488190 0
-sys/src/cmd/unix/drawterm/README - 664 sys sys 1128520449 373
-sys/src/cmd/unix/drawterm/README.MACOSX - 664 sys sys 1020578504 57
-sys/src/cmd/unix/drawterm/_asgetticket.c - 664 sys sys 954098597 285
-sys/src/cmd/unix/drawterm/_asrdfile.c - 664 sys sys 954098597 245
-sys/src/cmd/unix/drawterm/_asrdresp.c - 664 sys sys 954098598 545
-sys/src/cmd/unix/drawterm/_asreadn.c - 664 sys sys 954098599 200
-sys/src/cmd/unix/drawterm/argv0.c - 664 sys sys 954098599 32
-sys/src/cmd/unix/drawterm/asm-Solaris-386.s - 664 sys sys 954098600 885
-sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s - 664 sys sys 954098600 312
-sys/src/cmd/unix/drawterm/atexit.c - 664 sys sys 954098601 818
-sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 1077480264 2218
-sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 1077480264 2992
-sys/src/cmd/unix/drawterm/authaux.c - 664 sys sys 954098602 11934
-sys/src/cmd/unix/drawterm/authdial.c - 664 sys sys 954098603 145
-sys/src/cmd/unix/drawterm/authlocal.h - 664 sys sys 954098603 162
+sys/src/cmd/unix/drawterm/9ball.ico - 664 sys sys 1135900533 9326
+sys/src/cmd/unix/drawterm/9ball.rc - 664 sys sys 1135900533 39
+sys/src/cmd/unix/drawterm/LICENSE - 664 sys sys 1135900534 12184
+sys/src/cmd/unix/drawterm/Make.config - 664 sys sys 1135900534 29
+sys/src/cmd/unix/drawterm/Make.unix - 664 sys sys 1135900534 429
+sys/src/cmd/unix/drawterm/Make.win32 - 664 sys sys 1135900534 816
+sys/src/cmd/unix/drawterm/Makefile - 664 sys sys 1135900534 1112
+sys/src/cmd/unix/drawterm/README - 664 sys sys 1135900534 925
+sys/src/cmd/unix/drawterm/args.h - 664 sys sys 1135900534 709
 sys/src/cmd/unix/drawterm/bin - 20000000775 sys sys 959090509 0
 sys/src/cmd/unix/drawterm/bin - 20000000775 sys sys 959090509 0
-sys/src/cmd/unix/drawterm/bin/README - 664 sys sys 1113252460 106
-sys/src/cmd/unix/drawterm/canlock-power-gcc.c - 664 sys sys 1019839861 985
-sys/src/cmd/unix/drawterm/canlock-x86-gcc.c - 664 sys sys 1020313486 308
-sys/src/cmd/unix/drawterm/canlock.c - 664 sys sys 954098604 92
-sys/src/cmd/unix/drawterm/chan.c - 664 sys sys 954098604 10678
-sys/src/cmd/unix/drawterm/conv.c - 664 sys sys 954098605 8138
-sys/src/cmd/unix/drawterm/convD2M.c - 664 sys sys 954098606 703
-sys/src/cmd/unix/drawterm/convM2D.c - 664 sys sys 954098606 646
-sys/src/cmd/unix/drawterm/convM2S.c - 664 sys sys 954098607 2978
-sys/src/cmd/unix/drawterm/convM2T.c - 664 sys sys 954098607 557
-sys/src/cmd/unix/drawterm/convM2TR.c - 664 sys sys 954098608 269
-sys/src/cmd/unix/drawterm/convS2M.c - 664 sys sys 954098608 2984
-sys/src/cmd/unix/drawterm/convTR2M.c - 664 sys sys 954098609 529
-sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 1077480266 963
-sys/src/cmd/unix/drawterm/dev.c - 664 sys sys 954098610 5006
-sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 1077480267 7105
-sys/src/cmd/unix/drawterm/devdraw.c - 664 sys sys 958504757 39499
-sys/src/cmd/unix/drawterm/devip-unix.c - 664 sys sys 1046970237 15063
-sys/src/cmd/unix/drawterm/devip-win.c - 664 sys sys 1015701212 15055
-sys/src/cmd/unix/drawterm/devmnt.c - 664 sys sys 954098613 14492
-sys/src/cmd/unix/drawterm/devmouse.c - 664 sys sys 954098613 3982
-sys/src/cmd/unix/drawterm/devntfs.c - 664 sys sys 954098614 10545
-sys/src/cmd/unix/drawterm/devpipe.c - 664 sys sys 954098614 4958
-sys/src/cmd/unix/drawterm/devroot.c - 664 sys sys 954098615 1534
-sys/src/cmd/unix/drawterm/devssl.c - 664 sys sys 1077480268 25283
-sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 1077480268 2113
-sys/src/cmd/unix/drawterm/devunixfs.c - 664 sys sys 954098616 9548
-sys/src/cmd/unix/drawterm/dial.c - 664 sys sys 954098617 3640
-sys/src/cmd/unix/drawterm/dirfstat.c - 664 sys sys 954098617 179
-sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 1077480269 11757
-sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1077480270 12639
-sys/src/cmd/unix/drawterm/error.c - 664 sys sys 954098619 2515
-sys/src/cmd/unix/drawterm/error.h - 664 sys sys 954098619 3075
-sys/src/cmd/unix/drawterm/exportfs.c - 664 sys sys 964798439 13405
-sys/src/cmd/unix/drawterm/fcall.h - 664 sys sys 954098620 1675
-sys/src/cmd/unix/drawterm/fcallconv.c - 664 sys sys 954098621 4376
-sys/src/cmd/unix/drawterm/getcallerpc.c - 664 sys sys 954098622 89
-sys/src/cmd/unix/drawterm/getuser.c - 664 sys sys 954098622 274
-sys/src/cmd/unix/drawterm/glyph.c - 664 sys sys 954098624 4081
-sys/src/cmd/unix/drawterm/ip.h - 664 sys sys 954098625 560
-sys/src/cmd/unix/drawterm/irix.c - 664 sys sys 954098626 7552
-sys/src/cmd/unix/drawterm/kbd.c - 664 sys sys 954098627 8210
-sys/src/cmd/unix/drawterm/keyboard.h - 664 sys sys 1080159172 380
-sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1077480272 7808
-sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 1077480272 7930
+sys/src/cmd/unix/drawterm/cpu-bl.c - 644 sys sys 1135900534 14118
+sys/src/cmd/unix/drawterm/cpu.c - 664 sys sys 1135900534 13988
+sys/src/cmd/unix/drawterm/drawterm.h - 664 sys sys 1135900535 472
+sys/src/cmd/unix/drawterm/drawterm.ico - 664 sys sys 1135900535 1662
+sys/src/cmd/unix/drawterm/drawterm.rc - 664 sys sys 1135900535 1713
+sys/src/cmd/unix/drawterm/drawterm.res - 664 sys sys 1135900535 1756
+sys/src/cmd/unix/drawterm/exportfs - 20000000775 sys sys 1135900552 0
+sys/src/cmd/unix/drawterm/exportfs/Makefile - 664 sys sys 1135900552 200
+sys/src/cmd/unix/drawterm/exportfs/exportfs.c - 664 sys sys 1135900552 8412
+sys/src/cmd/unix/drawterm/exportfs/exportfs.h - 664 sys sys 1135900552 2738
+sys/src/cmd/unix/drawterm/exportfs/exportsrv.c - 664 sys sys 1135900552 10966
+sys/src/cmd/unix/drawterm/gui-win32 - 20000000775 sys sys 1135900547 0
+sys/src/cmd/unix/drawterm/gui-win32/Makefile - 664 sys sys 1135900546 220
+sys/src/cmd/unix/drawterm/gui-win32/alloc.c - 664 sys sys 1135900546 286
+sys/src/cmd/unix/drawterm/gui-win32/cload.c - 664 sys sys 1135900546 188
+sys/src/cmd/unix/drawterm/gui-win32/draw.c - 664 sys sys 1135900546 365
+sys/src/cmd/unix/drawterm/gui-win32/load.c - 664 sys sys 1135900546 186
+sys/src/cmd/unix/drawterm/gui-win32/screen.c - 664 sys sys 1135900547 11539
+sys/src/cmd/unix/drawterm/gui-win32/wstrtoutf.c - 664 sys sys 1135900547 408
+sys/src/cmd/unix/drawterm/gui-x11 - 20000000775 sys sys 1135900548 0
+sys/src/cmd/unix/drawterm/gui-x11/Makefile - 664 sys sys 1135900547 207
+sys/src/cmd/unix/drawterm/gui-x11/alloc.c - 664 sys sys 1135900547 3941
+sys/src/cmd/unix/drawterm/gui-x11/cload.c - 664 sys sys 1135900547 260
+sys/src/cmd/unix/drawterm/gui-x11/draw.c - 664 sys sys 1135900547 3896
+sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs-x11.c - 664 sys sys 1135900547 67008
+sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs.h - 664 sys sys 1135900548 244
+sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h - 664 sys sys 1135900548 13549
+sys/src/cmd/unix/drawterm/gui-x11/load.c - 664 sys sys 1135900548 258
+sys/src/cmd/unix/drawterm/gui-x11/screen.c - 664 sys sys 1135900548 24932
+sys/src/cmd/unix/drawterm/gui-x11/xmem.h - 664 sys sys 1135900548 1508
+sys/src/cmd/unix/drawterm/include - 20000000775 sys sys 1135900799 0
+sys/src/cmd/unix/drawterm/include/9windows.h - 664 sys sys 1135900761 420
+sys/src/cmd/unix/drawterm/include/a.out - 664 sys sys 1135900761 4522
+sys/src/cmd/unix/drawterm/include/auth.h - 664 sys sys 1135900761 3536
+sys/src/cmd/unix/drawterm/include/authsrv.h - 664 sys sys 1135900762 4562
+sys/src/cmd/unix/drawterm/include/cursor.h - 664 sys sys 1135900762 70
+sys/src/cmd/unix/drawterm/include/draw.h - 664 sys sys 1135900762 16052
+sys/src/cmd/unix/drawterm/include/dtos.h - 664 sys sys 1135900762 358
+sys/src/cmd/unix/drawterm/include/fcall.h - 664 sys sys 1135900762 2676
+sys/src/cmd/unix/drawterm/include/keyboard.h - 664 sys sys 1135900762 920
+sys/src/cmd/unix/drawterm/include/lib.h - 664 sys sys 1135900763 7449
+sys/src/cmd/unix/drawterm/include/libc.h - 664 sys sys 1135900763 36
+sys/src/cmd/unix/drawterm/include/libsec.h - 664 sys sys 1135900763 8861
+sys/src/cmd/unix/drawterm/include/memdraw.h - 664 sys sys 1135900763 6306
+sys/src/cmd/unix/drawterm/include/memlayer.h - 664 sys sys 1135900763 1871
+sys/src/cmd/unix/drawterm/include/mp.h - 664 sys sys 1135900763 4524
+sys/src/cmd/unix/drawterm/include/u.h - 664 sys sys 1135900763 336
+sys/src/cmd/unix/drawterm/include/unix.h - 664 sys sys 1135900763 263
+sys/src/cmd/unix/drawterm/include/user.h - 664 sys sys 1135900764 2532
+sys/src/cmd/unix/drawterm/kern - 20000000775 sys sys 1135900801 0
+sys/src/cmd/unix/drawterm/kern/Makefile - 664 sys sys 1135900764 571
+sys/src/cmd/unix/drawterm/kern/allocb.c - 664 sys sys 1135900764 3172
+sys/src/cmd/unix/drawterm/kern/cache.c - 664 sys sys 1135900764 466
+sys/src/cmd/unix/drawterm/kern/chan.c - 664 sys sys 1135900764 29593
+sys/src/cmd/unix/drawterm/kern/dat.h - 664 sys sys 1135900765 10716
+sys/src/cmd/unix/drawterm/kern/data.c - 664 sys sys 1135900765 423
+sys/src/cmd/unix/drawterm/kern/dev.c - 664 sys sys 1135900765 8523
+sys/src/cmd/unix/drawterm/kern/devcons.c - 664 sys sys 1135900765 19526
+sys/src/cmd/unix/drawterm/kern/devdraw.c - 664 sys sys 1135900765 42481
+sys/src/cmd/unix/drawterm/kern/devfs-posix.c - 664 sys sys 1135900765 9772
+sys/src/cmd/unix/drawterm/kern/devfs-win32.c - 664 sys sys 1135900766 10723
+sys/src/cmd/unix/drawterm/kern/devip-posix.c - 664 sys sys 1135900766 3488
+sys/src/cmd/unix/drawterm/kern/devip-win32.c - 664 sys sys 1135900766 3534
+sys/src/cmd/unix/drawterm/kern/devip.c - 664 sys sys 1135900766 16045
+sys/src/cmd/unix/drawterm/kern/devip.h - 664 sys sys 1135900766 469
+sys/src/cmd/unix/drawterm/kern/devlfd.c - 664 sys sys 1135900766 1534
+sys/src/cmd/unix/drawterm/kern/devmnt.c - 664 sys sys 1135900767 21739
+sys/src/cmd/unix/drawterm/kern/devmouse.c - 664 sys sys 1135900767 3799
+sys/src/cmd/unix/drawterm/kern/devpipe.c - 664 sys sys 1135900767 5927
+sys/src/cmd/unix/drawterm/kern/devroot.c - 664 sys sys 1135900767 4717
+sys/src/cmd/unix/drawterm/kern/devssl.c - 664 sys sys 1135900767 26455
+sys/src/cmd/unix/drawterm/kern/devtab.c - 664 sys sys 1135900767 470
+sys/src/cmd/unix/drawterm/kern/error.c - 664 sys sys 1135900767 2100
+sys/src/cmd/unix/drawterm/kern/error.h - 664 sys sys 1135900768 2583
+sys/src/cmd/unix/drawterm/kern/exportfs.c - 664 sys sys 1135900768 13444
+sys/src/cmd/unix/drawterm/kern/fns.h - 664 sys sys 1135900768 10731
+sys/src/cmd/unix/drawterm/kern/netif.h - 664 sys sys 1135900768 2950
+sys/src/cmd/unix/drawterm/kern/parse.c - 664 sys sys 1135900768 1993
+sys/src/cmd/unix/drawterm/kern/pgrp.c - 664 sys sys 1135900768 4017
+sys/src/cmd/unix/drawterm/kern/posix.c - 664 sys sys 1135900768 3149
+sys/src/cmd/unix/drawterm/kern/procinit.c - 664 sys sys 1135900769 1039
+sys/src/cmd/unix/drawterm/kern/qio.c - 664 sys sys 1135900769 23496
+sys/src/cmd/unix/drawterm/kern/qlock.c - 664 sys sys 1135900769 1119
+sys/src/cmd/unix/drawterm/kern/rendez.c - 664 sys sys 1135900769 1293
+sys/src/cmd/unix/drawterm/kern/rwlock.c - 664 sys sys 1135900769 634
+sys/src/cmd/unix/drawterm/kern/screen.h - 664 sys sys 1135900769 1151
+sys/src/cmd/unix/drawterm/kern/sleep.c - 664 sys sys 1135900769 1293
+sys/src/cmd/unix/drawterm/kern/smalloc.c - 664 sys sys 1135900769 187
+sys/src/cmd/unix/drawterm/kern/stub.c - 664 sys sys 1135900770 1273
+sys/src/cmd/unix/drawterm/kern/syscall.c - 664 sys sys 1135900770 12876
+sys/src/cmd/unix/drawterm/kern/sysfile.c - 664 sys sys 1135900770 18035
+sys/src/cmd/unix/drawterm/kern/sysproc.c - 664 sys sys 1135900770 498
+sys/src/cmd/unix/drawterm/kern/term.c - 664 sys sys 1135900770 3962
+sys/src/cmd/unix/drawterm/kern/todo.c - 664 sys sys 1135900770 0
+sys/src/cmd/unix/drawterm/kern/uart.c - 664 sys sys 1135900771 178
+sys/src/cmd/unix/drawterm/kern/waserror.c - 664 sys sys 1135900771 382
+sys/src/cmd/unix/drawterm/kern/win32.c - 664 sys sys 1135900771 7800
+sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1135900535 7806
+sys/src/cmd/unix/drawterm/libauth - 20000000775 sys sys 1135900560 0
+sys/src/cmd/unix/drawterm/libauth/Makefile - 664 sys sys 1135900556 306
+sys/src/cmd/unix/drawterm/libauth/attr.c - 664 sys sys 1135900556 2857
+sys/src/cmd/unix/drawterm/libauth/auth_attr.c - 664 sys sys 1135900556 217
+sys/src/cmd/unix/drawterm/libauth/auth_challenge.c - 664 sys sys 1135900556 1976
+sys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c - 664 sys sys 1135900556 1363
+sys/src/cmd/unix/drawterm/libauth/auth_proxy.c - 664 sys sys 1135900557 3606
+sys/src/cmd/unix/drawterm/libauth/auth_respond.c - 664 sys sys 1135900560 1420
+sys/src/cmd/unix/drawterm/libauth/auth_rpc.c - 664 sys sys 1135900560 2064
+sys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c - 664 sys sys 1135900560 1097
+sys/src/cmd/unix/drawterm/libauth/authlocal.h - 664 sys sys 1135900560 87
+sys/src/cmd/unix/drawterm/libauth/httpauth.c - 664 sys sys 1135900560 1059
+sys/src/cmd/unix/drawterm/libauthsrv - 20000000775 sys sys 1135900562 0
+sys/src/cmd/unix/drawterm/libauthsrv/Makefile - 664 sys sys 1135900560 355
+sys/src/cmd/unix/drawterm/libauthsrv/_asgetticket.c - 664 sys sys 1135900560 280
+sys/src/cmd/unix/drawterm/libauthsrv/_asrdresp.c - 664 sys sys 1135900560 874
+sys/src/cmd/unix/drawterm/libauthsrv/authdial.c - 664 sys sys 1135900561 711
+sys/src/cmd/unix/drawterm/libauthsrv/convA2M.c - 664 sys sys 1135900561 501
+sys/src/cmd/unix/drawterm/libauthsrv/convM2A.c - 664 sys sys 1135900561 470
+sys/src/cmd/unix/drawterm/libauthsrv/convM2PR.c - 664 sys sys 1135900561 610
+sys/src/cmd/unix/drawterm/libauthsrv/convM2T.c - 664 sys sys 1135900561 579
+sys/src/cmd/unix/drawterm/libauthsrv/convM2TR.c - 664 sys sys 1135900561 617
+sys/src/cmd/unix/drawterm/libauthsrv/convPR2M.c - 664 sys sys 1135900561 563
+sys/src/cmd/unix/drawterm/libauthsrv/convT2M.c - 664 sys sys 1135900561 558
+sys/src/cmd/unix/drawterm/libauthsrv/convTR2M.c - 664 sys sys 1135900561 562
+sys/src/cmd/unix/drawterm/libauthsrv/nvcsum.c - 664 sys sys 1135900562 192
+sys/src/cmd/unix/drawterm/libauthsrv/opasstokey.c - 664 sys sys 1135900562 448
+sys/src/cmd/unix/drawterm/libauthsrv/passtokey.c - 664 sys sys 1135900562 517
+sys/src/cmd/unix/drawterm/libauthsrv/readnvram.c - 664 sys sys 1135900562 8446
+sys/src/cmd/unix/drawterm/libc - 20000000775 sys sys 1135900573 0
+sys/src/cmd/unix/drawterm/libc/Makefile - 664 sys sys 1135900562 1097
+sys/src/cmd/unix/drawterm/libc/charstod.c - 664 sys sys 1135900562 1661
+sys/src/cmd/unix/drawterm/libc/cleanname.c - 664 sys sys 1135900562 1199
+sys/src/cmd/unix/drawterm/libc/convD2M.c - 664 sys sys 1135900562 1398
+sys/src/cmd/unix/drawterm/libc/convM2D.c - 664 sys sys 1135900563 1419
+sys/src/cmd/unix/drawterm/libc/convM2S.c - 664 sys sys 1135900563 4969
+sys/src/cmd/unix/drawterm/libc/convS2M.c - 664 sys sys 1135900563 5014
+sys/src/cmd/unix/drawterm/libc/crypt.c - 664 sys sys 1135900563 1045
+sys/src/cmd/unix/drawterm/libc/dial.c - 664 sys sys 1135900563 3703
+sys/src/cmd/unix/drawterm/libc/dirfstat.c - 664 sys sys 1135900563 676
+sys/src/cmd/unix/drawterm/libc/dirfwstat.c - 664 sys sys 1135900563 242
+sys/src/cmd/unix/drawterm/libc/dirmodefmt.c - 664 sys sys 1135900563 581
+sys/src/cmd/unix/drawterm/libc/dirstat.c - 664 sys sys 1135900563 688
+sys/src/cmd/unix/drawterm/libc/dirwstat.c - 664 sys sys 1135900564 246
+sys/src/cmd/unix/drawterm/libc/dofmt.c - 664 sys sys 1135900564 8626
+sys/src/cmd/unix/drawterm/libc/dorfmt.c - 664 sys sys 1135900564 777
+sys/src/cmd/unix/drawterm/libc/errfmt.c - 664 sys sys 1135900564 175
+sys/src/cmd/unix/drawterm/libc/fcallfmt.c - 664 sys sys 1135900564 5740
+sys/src/cmd/unix/drawterm/libc/fltfmt.c - 664 sys sys 1135900564 4345
+sys/src/cmd/unix/drawterm/libc/fmt.c - 664 sys sys 1135900564 2940
+sys/src/cmd/unix/drawterm/libc/fmt.h - 664 sys sys 1135900565 3075
+sys/src/cmd/unix/drawterm/libc/fmtdef.h - 664 sys sys 1135900565 1808
+sys/src/cmd/unix/drawterm/libc/fmtfd.c - 664 sys sys 1135900565 508
+sys/src/cmd/unix/drawterm/libc/fmtlock.c - 664 sys sys 1135900565 134
+sys/src/cmd/unix/drawterm/libc/fmtprint.c - 664 sys sys 1135900565 465
+sys/src/cmd/unix/drawterm/libc/fmtquote.c - 664 sys sys 1135900565 4732
+sys/src/cmd/unix/drawterm/libc/fmtrune.c - 664 sys sys 1135900565 314
+sys/src/cmd/unix/drawterm/libc/fmtstr.c - 664 sys sys 1135900565 140
+sys/src/cmd/unix/drawterm/libc/fmtvprint.c - 664 sys sys 1135900565 449
+sys/src/cmd/unix/drawterm/libc/fprint.c - 664 sys sys 1135900566 174
+sys/src/cmd/unix/drawterm/libc/frand.c - 664 sys sys 1135900566 210
+sys/src/cmd/unix/drawterm/libc/getfields.c - 664 sys sys 1135900566 516
+sys/src/cmd/unix/drawterm/libc/getpid.c - 664 sys sys 1135900566 198
+sys/src/cmd/unix/drawterm/libc/lnrand.c - 664 sys sys 1135900566 194
+sys/src/cmd/unix/drawterm/libc/lock.c - 664 sys sys 1135900566 774
+sys/src/cmd/unix/drawterm/libc/lrand.c - 664 sys sys 1135900566 1109
+sys/src/cmd/unix/drawterm/libc/mallocz.c - 664 sys sys 1135900566 141
+sys/src/cmd/unix/drawterm/libc/nan.h - 664 sys sys 1135900566 114
+sys/src/cmd/unix/drawterm/libc/nan64.c - 664 sys sys 1135900567 921
+sys/src/cmd/unix/drawterm/libc/netmkaddr.c - 664 sys sys 1135900567 863
+sys/src/cmd/unix/drawterm/libc/nrand.c - 664 sys sys 1135900567 191
+sys/src/cmd/unix/drawterm/libc/nsec.c - 664 sys sys 1135900567 1196
+sys/src/cmd/unix/drawterm/libc/pow10.c - 664 sys sys 1135900567 1946
+sys/src/cmd/unix/drawterm/libc/print.c - 664 sys sys 1135900567 164
+sys/src/cmd/unix/drawterm/libc/pushssl.c - 664 sys sys 1135900567 905
+sys/src/cmd/unix/drawterm/libc/rand.c - 664 sys sys 1135900567 79
+sys/src/cmd/unix/drawterm/libc/read9pmsg.c - 664 sys sys 1135900567 462
+sys/src/cmd/unix/drawterm/libc/readn.c - 664 sys sys 1135900568 234
+sys/src/cmd/unix/drawterm/libc/rune.c - 664 sys sys 1135900568 2306
+sys/src/cmd/unix/drawterm/libc/runefmtstr.c - 664 sys sys 1135900568 144
+sys/src/cmd/unix/drawterm/libc/runeseprint.c - 664 sys sys 1135900568 204
+sys/src/cmd/unix/drawterm/libc/runesmprint.c - 664 sys sys 1135900568 176
+sys/src/cmd/unix/drawterm/libc/runesnprint.c - 664 sys sys 1135900568 203
+sys/src/cmd/unix/drawterm/libc/runesprint.c - 664 sys sys 1135900568 192
+sys/src/cmd/unix/drawterm/libc/runestrcat.c - 664 sys sys 1135900568 124
+sys/src/cmd/unix/drawterm/libc/runestrchr.c - 664 sys sys 1135900568 207
+sys/src/cmd/unix/drawterm/libc/runestrcmp.c - 664 sys sys 1135900569 221
+sys/src/cmd/unix/drawterm/libc/runestrcpy.c - 664 sys sys 1135900569 138
+sys/src/cmd/unix/drawterm/libc/runestrdup.c - 664 sys sys 1135900569 180
+sys/src/cmd/unix/drawterm/libc/runestrecpy.c - 664 sys sys 1135900569 202
+sys/src/cmd/unix/drawterm/libc/runestrlen.c - 664 sys sys 1135900569 94
+sys/src/cmd/unix/drawterm/libc/runestrncat.c - 664 sys sys 1135900569 213
+sys/src/cmd/unix/drawterm/libc/runestrncmp.c - 664 sys sys 1135900569 250
+sys/src/cmd/unix/drawterm/libc/runestrncpy.c - 664 sys sys 1135900569 234
+sys/src/cmd/unix/drawterm/libc/runestrrchr.c - 664 sys sys 1135900569 182
+sys/src/cmd/unix/drawterm/libc/runestrstr.c - 664 sys sys 1135900570 397
+sys/src/cmd/unix/drawterm/libc/runetype.c - 664 sys sys 1135900570 29655
+sys/src/cmd/unix/drawterm/libc/runevseprint.c - 664 sys sys 1135900570 313
+sys/src/cmd/unix/drawterm/libc/runevsmprint.c - 664 sys sys 1135900570 1043
+sys/src/cmd/unix/drawterm/libc/runevsnprint.c - 664 sys sys 1135900570 330
+sys/src/cmd/unix/drawterm/libc/seprint.c - 664 sys sys 1135900570 196
+sys/src/cmd/unix/drawterm/libc/smprint.c - 664 sys sys 1135900570 168
+sys/src/cmd/unix/drawterm/libc/snprint.c - 664 sys sys 1135900570 195
+sys/src/cmd/unix/drawterm/libc/sprint.c - 664 sys sys 1135900570 236
+sys/src/cmd/unix/drawterm/libc/strecpy.c - 664 sys sys 1135900571 223
+sys/src/cmd/unix/drawterm/libc/strtod.c - 664 sys sys 1135900571 8558
+sys/src/cmd/unix/drawterm/libc/strtod.h - 664 sys sys 1135900571 120
+sys/src/cmd/unix/drawterm/libc/strtoll.c - 664 sys sys 1135900571 1302
+sys/src/cmd/unix/drawterm/libc/sysfatal.c - 664 sys sys 1135900571 479
+sys/src/cmd/unix/drawterm/libc/time.c - 664 sys sys 1135900571 878
+sys/src/cmd/unix/drawterm/libc/tokenize.c - 664 sys sys 1135900571 1691
+sys/src/cmd/unix/drawterm/libc/truerand.c - 664 sys sys 1135900571 306
+sys/src/cmd/unix/drawterm/libc/u16.c - 664 sys sys 1135900571 823
+sys/src/cmd/unix/drawterm/libc/u32.c - 664 sys sys 1135900572 2414
+sys/src/cmd/unix/drawterm/libc/u64.c - 664 sys sys 1135900572 3282
+sys/src/cmd/unix/drawterm/libc/utf.h - 664 sys sys 1135900572 1442
+sys/src/cmd/unix/drawterm/libc/utfdef.h - 664 sys sys 1135900572 335
+sys/src/cmd/unix/drawterm/libc/utfecpy.c - 664 sys sys 1135900572 284
+sys/src/cmd/unix/drawterm/libc/utflen.c - 664 sys sys 1135900572 242
+sys/src/cmd/unix/drawterm/libc/utfnlen.c - 664 sys sys 1135900572 317
+sys/src/cmd/unix/drawterm/libc/utfrrune.c - 664 sys sys 1135900572 414
+sys/src/cmd/unix/drawterm/libc/utfrune.c - 664 sys sys 1135900572 401
+sys/src/cmd/unix/drawterm/libc/utfutf.c - 664 sys sys 1135900573 391
+sys/src/cmd/unix/drawterm/libc/vfprint.c - 664 sys sys 1135900573 518
+sys/src/cmd/unix/drawterm/libc/vseprint.c - 664 sys sys 1135900573 309
+sys/src/cmd/unix/drawterm/libc/vsmprint.c - 664 sys sys 1135900573 997
+sys/src/cmd/unix/drawterm/libc/vsnprint.c - 664 sys sys 1135900573 326
 sys/src/cmd/unix/drawterm/libdraw - 20000000775 sys sys 954098713 0
 sys/src/cmd/unix/drawterm/libdraw - 20000000775 sys sys 954098713 0
-sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 954098710 111
-sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 954098710 2043
-sys/src/cmd/unix/drawterm/libdraw/bytesperline.c - 664 sys sys 954098711 538
-sys/src/cmd/unix/drawterm/libdraw/chan.c - 664 sys sys 954098711 1017
-sys/src/cmd/unix/drawterm/libdraw/defont.c - 664 sys sys 954098711 30537
-sys/src/cmd/unix/drawterm/libdraw/draw.h - 664 sys sys 954098712 13589
-sys/src/cmd/unix/drawterm/libdraw/icossin.c - 664 sys sys 954098712 2116
-sys/src/cmd/unix/drawterm/libdraw/icossin2.c - 664 sys sys 954098713 4586
-sys/src/cmd/unix/drawterm/libdraw/rectclip.c - 664 sys sys 954098713 571
-sys/src/cmd/unix/drawterm/libdraw/rgb.c - 664 sys sys 954098713 814
+sys/src/cmd/unix/drawterm/libdraw/Makefile - 664 sys sys 1135900573 293
+sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 1135900573 4095
+sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 1135900574 2839
+sys/src/cmd/unix/drawterm/libdraw/bytesperline.c - 664 sys sys 1135900574 617
+sys/src/cmd/unix/drawterm/libdraw/chan.c - 664 sys sys 1135900574 1151
+sys/src/cmd/unix/drawterm/libdraw/defont.c - 664 sys sys 1135900574 30537
+sys/src/cmd/unix/drawterm/libdraw/drawrepl.c - 664 sys sys 1135900574 314
+sys/src/cmd/unix/drawterm/libdraw/icossin.c - 664 sys sys 1135900574 2117
+sys/src/cmd/unix/drawterm/libdraw/icossin2.c - 664 sys sys 1135900574 4587
+sys/src/cmd/unix/drawterm/libdraw/rectclip.c - 664 sys sys 1135900575 571
+sys/src/cmd/unix/drawterm/libdraw/rgb.c - 664 sys sys 1135900575 1679
 sys/src/cmd/unix/drawterm/libmemdraw - 20000000775 sys sys 954098724 0
 sys/src/cmd/unix/drawterm/libmemdraw - 20000000775 sys sys 954098724 0
-sys/src/cmd/unix/drawterm/libmemdraw/alloc-win.c - 664 sys sys 954098714 300
-sys/src/cmd/unix/drawterm/libmemdraw/alloc-x11.c - 664 sys sys 954098714 4080
-sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 775 sys sys 964488227 3139
-sys/src/cmd/unix/drawterm/libmemdraw/arc.c - 664 sys sys 954098715 2612
-sys/src/cmd/unix/drawterm/libmemdraw/arctest.c - 664 sys sys 954098715 886
-sys/src/cmd/unix/drawterm/libmemdraw/cload-win.c - 664 sys sys 954098716 202
-sys/src/cmd/unix/drawterm/libmemdraw/cload-x11.c - 664 sys sys 954098716 274
-sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 775 sys sys 954098716 1352
-sys/src/cmd/unix/drawterm/libmemdraw/cmap.c - 664 sys sys 954098717 542
-sys/src/cmd/unix/drawterm/libmemdraw/cread.c - 664 sys sys 954098717 2281
-sys/src/cmd/unix/drawterm/libmemdraw/defont.c - 664 sys sys 954098718 1113
-sys/src/cmd/unix/drawterm/libmemdraw/draw-win.c - 664 sys sys 954098718 367
-sys/src/cmd/unix/drawterm/libmemdraw/draw-x11.c - 664 sys sys 954098718 4030
-sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 775 sys sys 964488227 43422
-sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c - 664 sys sys 964488226 4841
-sys/src/cmd/unix/drawterm/libmemdraw/fillpoly.c - 664 sys sys 954098720 9897
-sys/src/cmd/unix/drawterm/libmemdraw/hwdraw.c - 664 sys sys 954098720 169
-sys/src/cmd/unix/drawterm/libmemdraw/iprint.c - 664 sys sys 954098720 296
-sys/src/cmd/unix/drawterm/libmemdraw/line.c - 664 sys sys 954098721 10636
-sys/src/cmd/unix/drawterm/libmemdraw/load-win.c - 664 sys sys 954098721 200
-sys/src/cmd/unix/drawterm/libmemdraw/load-x11.c - 664 sys sys 954098721 272
-sys/src/cmd/unix/drawterm/libmemdraw/load.c - 775 sys sys 954098722 1510
-sys/src/cmd/unix/drawterm/libmemdraw/memdraw.h - 664 sys sys 954098722 5880
-sys/src/cmd/unix/drawterm/libmemdraw/poly.c - 664 sys sys 954098723 667
-sys/src/cmd/unix/drawterm/libmemdraw/read.c - 664 sys sys 954098723 2052
-sys/src/cmd/unix/drawterm/libmemdraw/string.c - 664 sys sys 954098723 1080
-sys/src/cmd/unix/drawterm/libmemdraw/subfont.c - 664 sys sys 954098724 575
-sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 775 sys sys 954098724 449
-sys/src/cmd/unix/drawterm/libmemdraw/xmem.h - 664 sys sys 954098725 1508
+sys/src/cmd/unix/drawterm/libmemdraw/Makefile - 664 sys sys 1135900575 391
+sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 664 sys sys 1135900575 3309
+sys/src/cmd/unix/drawterm/libmemdraw/alpha.hoc - 664 sys sys 1135900575 220
+sys/src/cmd/unix/drawterm/libmemdraw/arc.c - 664 sys sys 1135900575 2608
+sys/src/cmd/unix/drawterm/libmemdraw/arctest.c - 664 sys sys 1135900575 865
+sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 664 sys sys 1135900576 1338
+sys/src/cmd/unix/drawterm/libmemdraw/cmap.c - 664 sys sys 1135900576 25150
+sys/src/cmd/unix/drawterm/libmemdraw/cread.c - 664 sys sys 1135900576 1982
+sys/src/cmd/unix/drawterm/libmemdraw/defont.c - 664 sys sys 1135900576 1293
+sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 664 sys sys 1135900576 54684
+sys/src/cmd/unix/drawterm/libmemdraw/drawtest.c - 664 sys sys 1135900576 23441
+sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c - 664 sys sys 1135900576 4864
+sys/src/cmd/unix/drawterm/libmemdraw/fillpoly.c - 664 sys sys 1135900576 9973
+sys/src/cmd/unix/drawterm/libmemdraw/hwdraw.c - 664 sys sys 1135900577 159
+sys/src/cmd/unix/drawterm/libmemdraw/iprint.c - 664 sys sys 1135900577 128
+sys/src/cmd/unix/drawterm/libmemdraw/line.c - 664 sys sys 1135900577 11059
+sys/src/cmd/unix/drawterm/libmemdraw/load.c - 664 sys sys 1135900577 1496
+sys/src/cmd/unix/drawterm/libmemdraw/mkcmap.c - 664 sys sys 1135900577 1394
+sys/src/cmd/unix/drawterm/libmemdraw/openmemsubfont.c - 664 sys sys 1135900577 900
+sys/src/cmd/unix/drawterm/libmemdraw/poly.c - 664 sys sys 1135900577 484
+sys/src/cmd/unix/drawterm/libmemdraw/read.c - 664 sys sys 1135900577 2159
+sys/src/cmd/unix/drawterm/libmemdraw/string.c - 664 sys sys 1135900577 1081
+sys/src/cmd/unix/drawterm/libmemdraw/subfont.c - 664 sys sys 1135900578 561
+sys/src/cmd/unix/drawterm/libmemdraw/times - 664 sys sys 1135900578 586
+sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 664 sys sys 1135900578 435
+sys/src/cmd/unix/drawterm/libmemdraw/write.c - 664 sys sys 1135900578 4375
 sys/src/cmd/unix/drawterm/libmemlayer - 20000000775 sys sys 954098729 0
 sys/src/cmd/unix/drawterm/libmemlayer - 20000000775 sys sys 954098729 0
-sys/src/cmd/unix/drawterm/libmemlayer/draw.c - 664 sys sys 954098725 3913
-sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 775 sys sys 954098725 1799
-sys/src/cmd/unix/drawterm/libmemlayer/layerop.c - 664 sys sys 954098726 2587
-sys/src/cmd/unix/drawterm/libmemlayer/ldelete.c - 664 sys sys 954098726 1208
-sys/src/cmd/unix/drawterm/libmemlayer/lhide.c - 664 sys sys 954098726 1689
-sys/src/cmd/unix/drawterm/libmemlayer/line.c - 664 sys sys 954098727 2561
-sys/src/cmd/unix/drawterm/libmemlayer/load.c - 664 sys sys 954098727 1058
-sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c - 664 sys sys 954098727 2530
-sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 954098728 732
-sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 954098728 1179
-sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 954098729 1089
-sys/src/cmd/unix/drawterm/libmemlayer/memlayer.h - 664 sys sys 954098729 1691
+sys/src/cmd/unix/drawterm/libmemlayer/Makefile - 664 sys sys 1135900578 319
+sys/src/cmd/unix/drawterm/libmemlayer/draw.c - 664 sys sys 1135900578 4064
+sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 664 sys sys 1135900578 1794
+sys/src/cmd/unix/drawterm/libmemlayer/layerop.c - 664 sys sys 1135900578 2641
+sys/src/cmd/unix/drawterm/libmemlayer/ldelete.c - 664 sys sys 1135900579 1183
+sys/src/cmd/unix/drawterm/libmemlayer/lhide.c - 664 sys sys 1135900579 1675
+sys/src/cmd/unix/drawterm/libmemlayer/line.c - 664 sys sys 1135900579 2587
+sys/src/cmd/unix/drawterm/libmemlayer/load.c - 664 sys sys 1135900579 1032
+sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c - 664 sys sys 1135900579 2507
+sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 1135900579 703
+sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 1135900579 1289
+sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 1135900579 1062
+sys/src/cmd/unix/drawterm/libmemlayer/unload.c - 664 sys sys 1135900579 1007
+sys/src/cmd/unix/drawterm/libmp - 20000000775 sys sys 1135900584 0
+sys/src/cmd/unix/drawterm/libmp/Makefile - 664 sys sys 1135900580 602
+sys/src/cmd/unix/drawterm/libmp/betomp.c - 664 sys sys 1135900580 577
+sys/src/cmd/unix/drawterm/libmp/crt.c - 664 sys sys 1135900580 2050
+sys/src/cmd/unix/drawterm/libmp/crttest.c - 664 sys sys 1135900580 813
+sys/src/cmd/unix/drawterm/libmp/dat.h - 664 sys sys 1135900580 464
+sys/src/cmd/unix/drawterm/libmp/letomp.c - 664 sys sys 1135900581 455
+sys/src/cmd/unix/drawterm/libmp/mpadd.c - 664 sys sys 1135900581 783
+sys/src/cmd/unix/drawterm/libmp/mpaux.c - 664 sys sys 1135900581 2564
+sys/src/cmd/unix/drawterm/libmp/mpcmp.c - 664 sys sys 1135900581 462
+sys/src/cmd/unix/drawterm/libmp/mpdigdiv.c - 664 sys sys 1135900581 732
+sys/src/cmd/unix/drawterm/libmp/mpdiv.c - 664 sys sys 1135900581 2423
+sys/src/cmd/unix/drawterm/libmp/mpeuclid.c - 664 sys sys 1135900581 1226
+sys/src/cmd/unix/drawterm/libmp/mpexp.c - 664 sys sys 1135900581 1149
+sys/src/cmd/unix/drawterm/libmp/mpextendedgcd.c - 664 sys sys 1135900581 1613
+sys/src/cmd/unix/drawterm/libmp/mpfmt.c - 664 sys sys 1135900582 2729
+sys/src/cmd/unix/drawterm/libmp/mpinvert.c - 664 sys sys 1135900582 394
+sys/src/cmd/unix/drawterm/libmp/mpleft.c - 664 sys sys 1135900582 838
+sys/src/cmd/unix/drawterm/libmp/mpmod.c - 664 sys sys 1135900582 247
+sys/src/cmd/unix/drawterm/libmp/mpmul.c - 664 sys sys 1135900582 3110
+sys/src/cmd/unix/drawterm/libmp/mprand.c - 664 sys sys 1135900582 584
+sys/src/cmd/unix/drawterm/libmp/mpright.c - 664 sys sys 1135900582 695
+sys/src/cmd/unix/drawterm/libmp/mpsub.c - 664 sys sys 1135900582 792
+sys/src/cmd/unix/drawterm/libmp/mptobe.c - 664 sys sys 1135900582 879
+sys/src/cmd/unix/drawterm/libmp/mptoi.c - 664 sys sys 1135900582 553
+sys/src/cmd/unix/drawterm/libmp/mptole.c - 664 sys sys 1135900583 786
+sys/src/cmd/unix/drawterm/libmp/mptoui.c - 664 sys sys 1135900583 413
+sys/src/cmd/unix/drawterm/libmp/mptouv.c - 664 sys sys 1135900583 727
+sys/src/cmd/unix/drawterm/libmp/mptov.c - 664 sys sys 1135900583 995
+sys/src/cmd/unix/drawterm/libmp/mpvecadd.c - 664 sys sys 1135900583 519
+sys/src/cmd/unix/drawterm/libmp/mpveccmp.c - 664 sys sys 1135900583 402
+sys/src/cmd/unix/drawterm/libmp/mpvecdigmuladd.c - 664 sys sys 1135900583 1582
+sys/src/cmd/unix/drawterm/libmp/mpvecsub.c - 664 sys sys 1135900583 523
+sys/src/cmd/unix/drawterm/libmp/os.h - 664 sys sys 1135900583 34
+sys/src/cmd/unix/drawterm/libmp/reduce - 664 sys sys 1135900584 306
+sys/src/cmd/unix/drawterm/libmp/strtomp.c - 664 sys sys 1135900584 3026
 sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
 sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
-sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1077480282 17511
-sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1077480282 1078
-sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1077480282 860
-sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1077480283 662
-sys/src/cmd/unix/drawterm/libsec/libsec.h - 664 sys sys 1077480283 8912
-sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1077480283 4275
-sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1077480283 3313
-sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1077480283 5030
-sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1077480284 1430
-sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1077480284 2294
-sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1077480284 4678
-sys/src/cmd/unix/drawterm/libsec/u64.c - 664 sys sys 1077480285 3270
-sys/src/cmd/unix/drawterm/linux.c - 664 sys sys 963353235 9886
-sys/src/cmd/unix/drawterm/lock-irix.s - 664 sys sys 954098631 290
-sys/src/cmd/unix/drawterm/lock-osf1.s - 664 sys sys 954098631 887
-sys/src/cmd/unix/drawterm/lock.c - 664 sys sys 954098632 627
-sys/src/cmd/unix/drawterm/mallocz.c - 664 sys sys 954098632 104
-sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1077480273 2572
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 1077480274 555
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1077480274 549
-sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 1077480275 542
-sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1080159060 539
-sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 1077480276 553
-sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 1077480276 594
-sys/src/cmd/unix/drawterm/mkfile-Solaris-386 - 664 sys sys 954098636 25
-sys/src/cmd/unix/drawterm/mkfile-Solaris-sparc - 664 sys sys 954098637 27
-sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 1077480277 1353
-sys/src/cmd/unix/drawterm/nan.c - 664 sys sys 954098638 718
-sys/src/cmd/unix/drawterm/ndrawterm.mdp - 664 sys sys 954098639 33792
-sys/src/cmd/unix/drawterm/netmkaddr.c - 664 sys sys 954098639 784
-sys/src/cmd/unix/drawterm/new.bat - 664 sys sys 954098640 33
-sys/src/cmd/unix/drawterm/ns.c - 664 sys sys 954098641 2885
-sys/src/cmd/unix/drawterm/os.h - 664 sys sys 1019839871 303
-sys/src/cmd/unix/drawterm/passtokey.c - 664 sys sys 954098642 526
-sys/src/cmd/unix/drawterm/pipe.c - 664 sys sys 954098642 200
-sys/src/cmd/unix/drawterm/posix.c - 664 sys sys 964470494 8065
-sys/src/cmd/unix/drawterm/pow10.c - 664 sys sys 954098643 1121
-sys/src/cmd/unix/drawterm/print.c - 664 sys sys 954098644 1069
-sys/src/cmd/unix/drawterm/proc.c - 664 sys sys 954098645 3355
-sys/src/cmd/unix/drawterm/pushssl.c - 664 sys sys 1077480278 897
-sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 1077480279 14729
-sys/src/cmd/unix/drawterm/readn.c - 664 sys sys 954098646 219
-sys/src/cmd/unix/drawterm/ref.c - 664 sys sys 954098646 216
-sys/src/cmd/unix/drawterm/rune.c - 664 sys sys 954098647 2085
-sys/src/cmd/unix/drawterm/rwlock.c - 664 sys sys 954098647 580
-sys/src/cmd/unix/drawterm/screen-win.c - 664 sys sys 954098648 11441
-sys/src/cmd/unix/drawterm/screen-x11.c - 664 sys sys 964470495 21726
-sys/src/cmd/unix/drawterm/screen.h - 664 sys sys 954098649 1083
-sys/src/cmd/unix/drawterm/solaris.c - 664 sys sys 954098649 7927
-sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 1077480280 13888
-sys/src/cmd/unix/drawterm/syscall.c - 664 sys sys 954098651 12813
-sys/src/cmd/unix/drawterm/tabs.c - 664 sys sys 954098651 56506
-sys/src/cmd/unix/drawterm/tabs.h - 664 sys sys 954098652 681
-sys/src/cmd/unix/drawterm/term.c - 664 sys sys 954098652 3897
-sys/src/cmd/unix/drawterm/tokenize.c - 664 sys sys 954098653 598
-sys/src/cmd/unix/drawterm/unix.h - 664 sys sys 954098653 263
-sys/src/cmd/unix/drawterm/utflen.c - 664 sys sys 954098654 228
-sys/src/cmd/unix/drawterm/utfrune.c - 664 sys sys 954098654 386
-sys/src/cmd/unix/drawterm/werrstr.c - 664 sys sys 954098655 168
-sys/src/cmd/unix/drawterm/windows.c - 664 sys sys 954098655 8315
-sys/src/cmd/unix/drawterm/windows.h - 664 sys sys 954098656 401
-sys/src/cmd/unix/drawterm/winscreen.c - 664 sys sys 954098657 11393
-sys/src/cmd/unix/drawterm/wstrtoutf.c - 664 sys sys 954098657 393
+sys/src/cmd/unix/drawterm/libsec/Makefile - 664 sys sys 1135900584 771
+sys/src/cmd/unix/drawterm/libsec/aes.c - 664 sys sys 1135900584 64145
+sys/src/cmd/unix/drawterm/libsec/blowfish.c - 664 sys sys 1135900584 19676
+sys/src/cmd/unix/drawterm/libsec/decodepem.c - 664 sys sys 1135900584 1371
+sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1135900584 17496
+sys/src/cmd/unix/drawterm/libsec/des3CBC.c - 664 sys sys 1135900584 1135
+sys/src/cmd/unix/drawterm/libsec/des3ECB.c - 664 sys sys 1135900585 917
+sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1135900585 1079
+sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1135900585 861
+sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1135900585 647
+sys/src/cmd/unix/drawterm/libsec/dsaalloc.c - 664 sys sys 1135900585 864
+sys/src/cmd/unix/drawterm/libsec/dsagen.c - 664 sys sys 1135900585 1237
+sys/src/cmd/unix/drawterm/libsec/dsaprimes.c - 664 sys sys 1135900585 1881
+sys/src/cmd/unix/drawterm/libsec/dsaprivtopub.c - 664 sys sys 1135900585 279
+sys/src/cmd/unix/drawterm/libsec/dsasign.c - 664 sys sys 1135900586 934
+sys/src/cmd/unix/drawterm/libsec/dsaverify.c - 664 sys sys 1135900586 909
+sys/src/cmd/unix/drawterm/libsec/egalloc.c - 664 sys sys 1135900586 778
+sys/src/cmd/unix/drawterm/libsec/egdecrypt.c - 664 sys sys 1135900586 564
+sys/src/cmd/unix/drawterm/libsec/egencrypt.c - 664 sys sys 1135900586 806
+sys/src/cmd/unix/drawterm/libsec/eggen.c - 664 sys sys 1135900586 413
+sys/src/cmd/unix/drawterm/libsec/egprivtopub.c - 664 sys sys 1135900586 273
+sys/src/cmd/unix/drawterm/libsec/egsign.c - 664 sys sys 1135900586 807
+sys/src/cmd/unix/drawterm/libsec/egtest.c - 664 sys sys 1135900587 655
+sys/src/cmd/unix/drawterm/libsec/egverify.c - 664 sys sys 1135900587 519
+sys/src/cmd/unix/drawterm/libsec/fastrand.c - 664 sys sys 1135900587 258
+sys/src/cmd/unix/drawterm/libsec/genprime.c - 664 sys sys 1135900587 535
+sys/src/cmd/unix/drawterm/libsec/genrandom.c - 664 sys sys 1135900587 1171
+sys/src/cmd/unix/drawterm/libsec/gensafeprime.c - 664 sys sys 1135900587 741
+sys/src/cmd/unix/drawterm/libsec/genstrongprime.c - 664 sys sys 1135900587 1039
+sys/src/cmd/unix/drawterm/libsec/hmac.c - 664 sys sys 1135900587 1167
+sys/src/cmd/unix/drawterm/libsec/hmactest.c - 664 sys sys 1135900588 344
+sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1135900588 4260
+sys/src/cmd/unix/drawterm/libsec/md4test.c - 664 sys sys 1135900588 537
+sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1135900588 3254
+sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1135900588 5015
+sys/src/cmd/unix/drawterm/libsec/md5pickle.c - 664 sys sys 1135900588 657
+sys/src/cmd/unix/drawterm/libsec/nfastrand.c - 664 sys sys 1135900588 327
+sys/src/cmd/unix/drawterm/libsec/os.h - 664 sys sys 1135900588 33
+sys/src/cmd/unix/drawterm/libsec/primetest.c - 664 sys sys 1135900589 2486
+sys/src/cmd/unix/drawterm/libsec/prng.c - 664 sys sys 1135900589 187
+sys/src/cmd/unix/drawterm/libsec/probably_prime.c - 664 sys sys 1135900589 1567
+sys/src/cmd/unix/drawterm/libsec/ranlib.core - 664 sys sys 1135900590 430080
+sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1135900590 1415
+sys/src/cmd/unix/drawterm/libsec/readcert.c - 664 sys sys 1135900590 759
+sys/src/cmd/unix/drawterm/libsec/rsaalloc.c - 664 sys sys 1135900590 657
+sys/src/cmd/unix/drawterm/libsec/rsadecrypt.c - 664 sys sys 1135900590 749
+sys/src/cmd/unix/drawterm/libsec/rsaencrypt.c - 664 sys sys 1135900590 192
+sys/src/cmd/unix/drawterm/libsec/rsafill.c - 664 sys sys 1135900590 1104
+sys/src/cmd/unix/drawterm/libsec/rsagen.c - 664 sys sys 1135900591 1451
+sys/src/cmd/unix/drawterm/libsec/rsaprivtopub.c - 664 sys sys 1135900591 237
+sys/src/cmd/unix/drawterm/libsec/rsatest.c - 664 sys sys 1135900591 1095
+sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1135900591 2279
+sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1135900591 4673
+sys/src/cmd/unix/drawterm/libsec/sha1pickle.c - 664 sys sys 1135900591 717
+sys/src/cmd/unix/drawterm/libsec/smallprimes.c - 664 sys sys 1135900591 6851
+sys/src/cmd/unix/drawterm/libsec/smallprimetest.c - 664 sys sys 1135900591 70640
+sys/src/cmd/unix/drawterm/libsec/thumb.c - 664 sys sys 1135900592 1891
+sys/src/cmd/unix/drawterm/libsec/tlshand.c - 664 sys sys 1135900592 53926
+sys/src/cmd/unix/drawterm/libsec/x509.c - 664 sys sys 1135900592 50237
+sys/src/cmd/unix/drawterm/main.c - 664 sys sys 1135900536 2440
+sys/src/cmd/unix/drawterm/posix-386 - 20000000775 sys sys 1135900540 0
+sys/src/cmd/unix/drawterm/posix-386/Makefile - 664 sys sys 1135900540 378
+sys/src/cmd/unix/drawterm/posix-386/getcallerpc.c - 664 sys sys 1135900540 90
+sys/src/cmd/unix/drawterm/posix-386/md5block.spp - 664 sys sys 1135900540 6472
+sys/src/cmd/unix/drawterm/posix-386/sha1block.spp - 664 sys sys 1135900540 4749
+sys/src/cmd/unix/drawterm/posix-386/tas.c - 664 sys sys 1135900540 270
+sys/src/cmd/unix/drawterm/posix-factotum.c - 664 sys sys 1135900536 1880
+sys/src/cmd/unix/drawterm/posix-mips - 20000000775 sys sys 1135900037 0
+sys/src/cmd/unix/drawterm/posix-power - 20000000775 sys sys 1135900541 0
+sys/src/cmd/unix/drawterm/posix-power/Makefile - 664 sys sys 1135900541 291
+sys/src/cmd/unix/drawterm/posix-power/getcallerpc.c - 664 sys sys 1135900541 90
+sys/src/cmd/unix/drawterm/posix-power/md5block.c - 664 sys sys 1135900541 5032
+sys/src/cmd/unix/drawterm/posix-power/sha1block.c - 664 sys sys 1135900541 4710
+sys/src/cmd/unix/drawterm/posix-power/tas.c - 664 sys sys 1135900541 943
+sys/src/cmd/unix/drawterm/readcons.c - 664 sys sys 1135900536 1842
+sys/src/cmd/unix/drawterm/resource.h - 664 sys sys 1135900536 457
+sys/src/cmd/unix/drawterm/secstore.c - 664 sys sys 1135900536 15742
+sys/src/cmd/unix/drawterm/win32-386 - 20000000775 sys sys 1135900544 0
+sys/src/cmd/unix/drawterm/win32-386/Makefile - 664 sys sys 1135900544 291
+sys/src/cmd/unix/drawterm/win32-386/getcallerpc.c - 664 sys sys 1135900544 90
+sys/src/cmd/unix/drawterm/win32-386/md5block.spp - 664 sys sys 1135900544 6591
+sys/src/cmd/unix/drawterm/win32-386/sha1block.spp - 664 sys sys 1135900544 4912
+sys/src/cmd/unix/drawterm/win32-386/tas.c - 664 sys sys 1135900544 270
+sys/src/cmd/unix/drawterm/win32-factotum.c - 664 sys sys 1135900536 238
 sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs/LICENSE - 664 sys sys 1132498433 735
 sys/src/cmd/unix/u9fs/LICENSE - 664 sys sys 1132498433 735
@@ -13445,7 +13757,7 @@ sys/src/cmd/usb/audio/usbaudioctl.c - 664 sys sys 1101906325 17266
 sys/src/cmd/usb/audio/usbaudioctl.h - 664 sys sys 1100568597 600
 sys/src/cmd/usb/audio/usbaudioctl.h - 664 sys sys 1100568597 600
 sys/src/cmd/usb/lib - 20000000775 sys sys 1018369393 0
 sys/src/cmd/usb/lib - 20000000775 sys sys 1018369393 0
 sys/src/cmd/usb/lib/device.c - 664 sys sys 1099760882 2968
 sys/src/cmd/usb/lib/device.c - 664 sys sys 1099760882 2968
-sys/src/cmd/usb/lib/dump.c - 664 sys sys 1103381265 12921
+sys/src/cmd/usb/lib/dump.c - 664 sys sys 1135896862 12915
 sys/src/cmd/usb/lib/fmt.c - 664 sys sys 1091204978 291
 sys/src/cmd/usb/lib/fmt.c - 664 sys sys 1091204978 291
 sys/src/cmd/usb/lib/mkfile - 664 sys sys 1091204979 204
 sys/src/cmd/usb/lib/mkfile - 664 sys sys 1091204979 204
 sys/src/cmd/usb/lib/setup.c - 664 sys sys 1091204978 1953
 sys/src/cmd/usb/lib/setup.c - 664 sys sys 1091204978 1953
@@ -14601,14 +14913,14 @@ sys/src/libmach/vcodas.c - 664 sys sys 1131289385 10258
 sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
 sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
 sys/src/libmach/vobj.c - 664 sys sys 1091732625 2206
 sys/src/libmach/vobj.c - 664 sys sys 1091732625 2206
 sys/src/libmemdraw - 20000000775 sys sys 985020762 0
 sys/src/libmemdraw - 20000000775 sys sys 985020762 0
-sys/src/libmemdraw/alloc.c - 664 sys sys 1135394719 3332
+sys/src/libmemdraw/alloc.c - 664 sys sys 1135895512 3334
 sys/src/libmemdraw/alpha.hoc - 664 sys sys 944961741 220
 sys/src/libmemdraw/alpha.hoc - 664 sys sys 944961741 220
 sys/src/libmemdraw/arc.c - 664 sys sys 1039752932 2608
 sys/src/libmemdraw/arc.c - 664 sys sys 1039752932 2608
 sys/src/libmemdraw/arctest.c - 664 sys sys 1045502219 865
 sys/src/libmemdraw/arctest.c - 664 sys sys 1045502219 865
 sys/src/libmemdraw/cload.c - 664 sys sys 944961741 1337
 sys/src/libmemdraw/cload.c - 664 sys sys 944961741 1337
 sys/src/libmemdraw/cmap.c - 664 sys sys 1029430942 25150
 sys/src/libmemdraw/cmap.c - 664 sys sys 1029430942 25150
 sys/src/libmemdraw/cread.c - 664 sys sys 1014930216 1982
 sys/src/libmemdraw/cread.c - 664 sys sys 1014930216 1982
-sys/src/libmemdraw/defont.c - 664 sys sys 944961741 1288
+sys/src/libmemdraw/defont.c - 664 sys sys 1135895512 1290
 sys/src/libmemdraw/draw.c - 664 sys sys 1114867396 55720
 sys/src/libmemdraw/draw.c - 664 sys sys 1114867396 55720
 sys/src/libmemdraw/drawtest.c - 664 sys sys 1045502228 23441
 sys/src/libmemdraw/drawtest.c - 664 sys sys 1045502228 23441
 sys/src/libmemdraw/ellipse.c - 664 sys sys 1039752933 4866
 sys/src/libmemdraw/ellipse.c - 664 sys sys 1039752933 4866

+ 619 - 0
dist/replica/plan9.log

@@ -24060,3 +24060,622 @@
 1135632706 0 c 386/9loaddebug - 775 sys sys 1135631316 311840
 1135632706 0 c 386/9loaddebug - 775 sys sys 1135631316 311840
 1135632706 1 c 386/9loadlitedebug - 775 sys sys 1135631317 200089
 1135632706 1 c 386/9loadlitedebug - 775 sys sys 1135631317 200089
 1135785631 0 c sys/src/9/pc/etherec2t.c - 664 sys sys 1135784135 4092
 1135785631 0 c sys/src/9/pc/etherec2t.c - 664 sys sys 1135784135 4092
+1135893650 0 a sys/src/cmd/aquarela - 20000000775 sys sys 1135892145 0
+1135893650 1 a sys/src/cmd/aquarela/COPYRIGHT - 664 sys sys 1135892145 43
+1135893650 2 a sys/src/cmd/aquarela/addname.c - 664 sys sys 1135892108 1281
+1135893650 3 a sys/src/cmd/aquarela/alarm.c - 664 sys sys 1135892108 2194
+1135893650 4 a sys/src/cmd/aquarela/alloc.c - 664 sys sys 1135892108 245
+1135893650 5 a sys/src/cmd/aquarela/aquarela.c - 664 sys sys 1135892108 6986
+1135893650 6 a sys/src/cmd/aquarela/cifscmd.c - 664 sys sys 1135892108 4430
+1135893650 7 a sys/src/cmd/aquarela/client.c - 664 sys sys 1135892108 2724
+1135893650 8 a sys/src/cmd/aquarela/dump.c - 664 sys sys 1135892108 2864
+1135893650 9 a sys/src/cmd/aquarela/findname.c - 664 sys sys 1135892108 1351
+1135893650 10 a sys/src/cmd/aquarela/headers.h - 664 sys sys 1135892108 185
+1135893650 11 a sys/src/cmd/aquarela/message.c - 664 sys sys 1135892108 1260
+1135893650 12 a sys/src/cmd/aquarela/mkfile - 664 sys sys 1135892109 1487
+1135893650 13 a sys/src/cmd/aquarela/nb.c - 664 sys sys 1135892109 538
+1135893650 14 a sys/src/cmd/aquarela/nbdgram.c - 664 sys sys 1135892109 4364
+1135893650 15 a sys/src/cmd/aquarela/nbdgramconv.c - 664 sys sys 1135892109 2339
+1135893650 16 a sys/src/cmd/aquarela/nbdgramdump.c - 664 sys sys 1135892109 506
+1135893650 17 a sys/src/cmd/aquarela/nblistener.c - 664 sys sys 1135892109 738
+1135893650 18 a sys/src/cmd/aquarela/nbname.c - 664 sys sys 1135892109 5457
+1135893650 19 a sys/src/cmd/aquarela/nbns.c - 664 sys sys 1135892109 2747
+1135893650 20 a sys/src/cmd/aquarela/nbnsconv.c - 664 sys sys 1135892109 6257
+1135893650 21 a sys/src/cmd/aquarela/nbresolve.c - 664 sys sys 1135892109 672
+1135893650 22 a sys/src/cmd/aquarela/nbss.c - 664 sys sys 1135892110 8126
+1135893650 23 a sys/src/cmd/aquarela/netbios.h - 664 sys sys 1135892110 5967
+1135893650 24 a sys/src/cmd/aquarela/smb.h - 664 sys sys 1135892110 9492
+1135893650 25 a sys/src/cmd/aquarela/smballoc.c - 664 sys sys 1135892110 508
+1135893650 26 a sys/src/cmd/aquarela/smbbrowse.c - 664 sys sys 1135892110 1473
+1135893650 27 a sys/src/cmd/aquarela/smbbuffer.c - 664 sys sys 1135892110 9717
+1135893650 28 a sys/src/cmd/aquarela/smbclientopen.c - 664 sys sys 1135892110 1428
+1135893650 29 a sys/src/cmd/aquarela/smbcomclose.c - 664 sys sys 1135892110 578
+1135893650 30 a sys/src/cmd/aquarela/smbcomcreatedir.c - 664 sys sys 1135892110 692
+1135893650 31 a sys/src/cmd/aquarela/smbcomdelete.c - 664 sys sys 1135892110 1575
+1135893650 32 a sys/src/cmd/aquarela/smbcomdeletedir.c - 664 sys sys 1135892111 659
+1135893650 33 a sys/src/cmd/aquarela/smbcomdir.c - 664 sys sys 1135892111 1113
+1135893650 34 a sys/src/cmd/aquarela/smbcomecho.c - 664 sys sys 1135892111 819
+1135893650 35 a sys/src/cmd/aquarela/smbcomfindclose2.c - 664 sys sys 1135892111 319
+1135893650 36 a sys/src/cmd/aquarela/smbcomflush.c - 664 sys sys 1135892111 707
+1135893650 37 a sys/src/cmd/aquarela/smbcomlocking.c - 664 sys sys 1135892111 3701
+1135893650 38 a sys/src/cmd/aquarela/smbcommon.c - 664 sys sys 1135892111 8652
+1135893650 39 a sys/src/cmd/aquarela/smbcomopen.c - 664 sys sys 1135892111 18350
+1135893650 40 a sys/src/cmd/aquarela/smbcomquery.c - 664 sys sys 1135892111 2715
+1135893650 41 a sys/src/cmd/aquarela/smbcomread.c - 664 sys sys 1135892112 2601
+1135893650 42 a sys/src/cmd/aquarela/smbcomrename.c - 664 sys sys 1135892112 1259
+1135893650 43 a sys/src/cmd/aquarela/smbcomsessionsetupandx.c - 664 sys sys 1135892112 6175
+1135893650 44 a sys/src/cmd/aquarela/smbcomsetinfo.c - 664 sys sys 1135892112 2985
+1135893650 45 a sys/src/cmd/aquarela/smbcomtransaction.c - 664 sys sys 1135892112 4041
+1135893650 46 a sys/src/cmd/aquarela/smbcomtreeconnectandx.c - 664 sys sys 1135892112 3269
+1135893650 47 a sys/src/cmd/aquarela/smbcomtreedisconnect.c - 664 sys sys 1135892112 290
+1135893650 48 a sys/src/cmd/aquarela/smbcomwrite.c - 664 sys sys 1135892112 3312
+1135893650 49 a sys/src/cmd/aquarela/smbconnect.c - 664 sys sys 1135892112 9040
+1135893650 50 a sys/src/cmd/aquarela/smbconv.c - 664 sys sys 1135892112 531
+1135893650 51 a sys/src/cmd/aquarela/smbdat.h - 664 sys sys 1135892113 6649
+1135893650 52 a sys/src/cmd/aquarela/smbdircache.c - 664 sys sys 1135892113 631
+1135893650 53 a sys/src/cmd/aquarela/smbfile.c - 664 sys sys 1135892113 438
+1135893650 54 a sys/src/cmd/aquarela/smbfns.h - 664 sys sys 1135892113 12190
+1135893650 55 a sys/src/cmd/aquarela/smbglobals.c - 664 sys sys 1135892113 1096
+1135893650 56 a sys/src/cmd/aquarela/smbidmap.c - 664 sys sys 1135892113 2178
+1135893650 57 a sys/src/cmd/aquarela/smblisten.c - 664 sys sys 1135892113 2592
+1135893650 58 a sys/src/cmd/aquarela/smblog.c - 664 sys sys 1135892113 1841
+1135893650 59 a sys/src/cmd/aquarela/smbnegotiate.c - 664 sys sys 1135892113 2933
+1135893650 60 a sys/src/cmd/aquarela/smboptable.c - 664 sys sys 1135892113 5826
+1135893650 61 a sys/src/cmd/aquarela/smbpath.c - 664 sys sys 1135892114 393
+1135893650 62 a sys/src/cmd/aquarela/smbrap2.c - 664 sys sys 1135892114 11628
+1135893650 63 a sys/src/cmd/aquarela/smbrap2client.c - 664 sys sys 1135892114 3082
+1135893650 64 a sys/src/cmd/aquarela/smbrep.c - 664 sys sys 1135892114 1033
+1135893650 65 a sys/src/cmd/aquarela/smbresponse.c - 664 sys sys 1135892114 2820
+1135893650 66 a sys/src/cmd/aquarela/smbservice.c - 664 sys sys 1135892114 2335
+1135893650 67 a sys/src/cmd/aquarela/smbsharedfile.c - 664 sys sys 1135892114 6006
+1135893650 68 a sys/src/cmd/aquarela/smbstring.c - 664 sys sys 1135892114 4152
+1135893650 69 a sys/src/cmd/aquarela/smbtime.c - 664 sys sys 1135892114 1232
+1135893650 70 a sys/src/cmd/aquarela/smbtrans2client.c - 664 sys sys 1135892114 3726
+1135893650 71 a sys/src/cmd/aquarela/smbtrans2find.c - 664 sys sys 1135892115 9041
+1135893650 72 a sys/src/cmd/aquarela/smbtrans2query.c - 664 sys sys 1135892115 8215
+1135893650 73 a sys/src/cmd/aquarela/smbtrans2set.c - 664 sys sys 1135892115 2440
+1135893650 74 a sys/src/cmd/aquarela/smbtransaction.c - 664 sys sys 1135892115 16684
+1135893650 75 a sys/src/cmd/aquarela/smbtree.c - 664 sys sys 1135892115 1314
+1135893650 76 a sys/src/cmd/aquarela/testconnect.c - 664 sys sys 1135892115 1533
+1135893650 77 a sys/src/cmd/aquarela/testnbdgram.c - 664 sys sys 1135892115 2919
+1135893650 78 a sys/src/cmd/aquarela/testtime.c - 664 sys sys 1135892115 446
+1135893650 79 a sys/src/cmd/tcs/html.c - 664 sys sys 1135893400 5237
+1135895457 0 c sys/src/libmemdraw/alloc.c - 664 sys sys 1135895512 3334
+1135895457 1 c sys/src/libmemdraw/defont.c - 664 sys sys 1135895512 1290
+1135897258 0 c sys/src/cmd/usb/lib/dump.c - 664 sys sys 1135896862 12915
+1135900858 0 a sys/src/cmd/unix/drawterm/9ball.ico - 664 sys sys 1135900533 9326
+1135900858 1 a sys/src/cmd/unix/drawterm/9ball.rc - 664 sys sys 1135900533 39
+1135900858 2 a sys/src/cmd/unix/drawterm/LICENSE - 664 sys sys 1135900534 12184
+1135900858 3 a sys/src/cmd/unix/drawterm/Make.config - 664 sys sys 1135900534 29
+1135900858 4 a sys/src/cmd/unix/drawterm/Make.unix - 664 sys sys 1135900534 429
+1135900858 5 a sys/src/cmd/unix/drawterm/Make.win32 - 664 sys sys 1135900534 816
+1135900858 6 a sys/src/cmd/unix/drawterm/Makefile - 664 sys sys 1135900534 1112
+1135900858 7 c sys/src/cmd/unix/drawterm/README - 664 sys sys 1135900534 925
+1135900858 8 a sys/src/cmd/unix/drawterm/args.h - 664 sys sys 1135900534 709
+1135900858 9 a sys/src/cmd/unix/drawterm/cpu-bl.c - 644 sys sys 1135900534 14118
+1135900858 10 a sys/src/cmd/unix/drawterm/cpu.c - 664 sys sys 1135900534 13988
+1135900858 11 a sys/src/cmd/unix/drawterm/drawterm.h - 664 sys sys 1135900535 472
+1135900858 12 a sys/src/cmd/unix/drawterm/drawterm.ico - 664 sys sys 1135900535 1662
+1135900858 13 a sys/src/cmd/unix/drawterm/drawterm.rc - 664 sys sys 1135900535 1713
+1135900858 14 a sys/src/cmd/unix/drawterm/drawterm.res - 664 sys sys 1135900535 1756
+1135900858 15 a sys/src/cmd/unix/drawterm/exportfs - 20000000775 sys sys 1135900552 0
+1135900858 16 a sys/src/cmd/unix/drawterm/exportfs/Makefile - 664 sys sys 1135900552 200
+1135900858 17 a sys/src/cmd/unix/drawterm/exportfs/exportfs.c - 664 sys sys 1135900552 8412
+1135900858 18 a sys/src/cmd/unix/drawterm/exportfs/exportfs.h - 664 sys sys 1135900552 2738
+1135900858 19 a sys/src/cmd/unix/drawterm/exportfs/exportsrv.c - 664 sys sys 1135900552 10966
+1135900858 20 a sys/src/cmd/unix/drawterm/gui-win32 - 20000000775 sys sys 1135900547 0
+1135900858 21 a sys/src/cmd/unix/drawterm/gui-win32/Makefile - 664 sys sys 1135900546 220
+1135900858 22 a sys/src/cmd/unix/drawterm/gui-win32/alloc.c - 664 sys sys 1135900546 286
+1135900858 23 a sys/src/cmd/unix/drawterm/gui-win32/cload.c - 664 sys sys 1135900546 188
+1135900858 24 a sys/src/cmd/unix/drawterm/gui-win32/draw.c - 664 sys sys 1135900546 365
+1135900858 25 a sys/src/cmd/unix/drawterm/gui-win32/load.c - 664 sys sys 1135900546 186
+1135900858 26 a sys/src/cmd/unix/drawterm/gui-win32/screen.c - 664 sys sys 1135900547 11539
+1135900858 27 a sys/src/cmd/unix/drawterm/gui-win32/wstrtoutf.c - 664 sys sys 1135900547 408
+1135900858 28 a sys/src/cmd/unix/drawterm/gui-x11 - 20000000775 sys sys 1135900548 0
+1135900858 29 a sys/src/cmd/unix/drawterm/gui-x11/Makefile - 664 sys sys 1135900547 207
+1135900858 30 a sys/src/cmd/unix/drawterm/gui-x11/alloc.c - 664 sys sys 1135900547 3941
+1135900858 31 a sys/src/cmd/unix/drawterm/gui-x11/cload.c - 664 sys sys 1135900547 260
+1135900858 32 a sys/src/cmd/unix/drawterm/gui-x11/draw.c - 664 sys sys 1135900547 3896
+1135900858 33 a sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs-x11.c - 664 sys sys 1135900547 67008
+1135900858 34 a sys/src/cmd/unix/drawterm/gui-x11/keysym2ucs.h - 664 sys sys 1135900548 244
+1135900858 35 a sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h - 664 sys sys 1135900548 13549
+1135900858 36 a sys/src/cmd/unix/drawterm/gui-x11/load.c - 664 sys sys 1135900548 258
+1135900858 37 a sys/src/cmd/unix/drawterm/gui-x11/screen.c - 664 sys sys 1135900548 24932
+1135900858 38 a sys/src/cmd/unix/drawterm/gui-x11/xmem.h - 664 sys sys 1135900548 1508
+1135900858 39 a sys/src/cmd/unix/drawterm/include - 20000000775 sys sys 1135900799 0
+1135900858 40 a sys/src/cmd/unix/drawterm/include/9windows.h - 664 sys sys 1135900761 420
+1135900858 41 a sys/src/cmd/unix/drawterm/include/a.out - 664 sys sys 1135900761 4522
+1135900858 42 a sys/src/cmd/unix/drawterm/include/auth.h - 664 sys sys 1135900761 3536
+1135900858 43 a sys/src/cmd/unix/drawterm/include/authsrv.h - 664 sys sys 1135900762 4562
+1135900858 44 a sys/src/cmd/unix/drawterm/include/cursor.h - 664 sys sys 1135900762 70
+1135900858 45 a sys/src/cmd/unix/drawterm/include/draw.h - 664 sys sys 1135900762 16052
+1135900858 46 a sys/src/cmd/unix/drawterm/include/dtos.h - 664 sys sys 1135900762 358
+1135900858 47 a sys/src/cmd/unix/drawterm/include/fcall.h - 664 sys sys 1135900762 2676
+1135900858 48 a sys/src/cmd/unix/drawterm/include/keyboard.h - 664 sys sys 1135900762 920
+1135900858 49 a sys/src/cmd/unix/drawterm/include/lib.h - 664 sys sys 1135900763 7449
+1135900858 50 a sys/src/cmd/unix/drawterm/include/libc.h - 664 sys sys 1135900763 36
+1135900858 51 a sys/src/cmd/unix/drawterm/include/libsec.h - 664 sys sys 1135900763 8861
+1135900858 52 a sys/src/cmd/unix/drawterm/include/memdraw.h - 664 sys sys 1135900763 6306
+1135900858 53 a sys/src/cmd/unix/drawterm/include/memlayer.h - 664 sys sys 1135900763 1871
+1135900858 54 a sys/src/cmd/unix/drawterm/include/mp.h - 664 sys sys 1135900763 4524
+1135900858 55 a sys/src/cmd/unix/drawterm/include/u.h - 664 sys sys 1135900763 336
+1135900858 56 a sys/src/cmd/unix/drawterm/include/unix.h - 664 sys sys 1135900763 263
+1135900858 57 a sys/src/cmd/unix/drawterm/include/user.h - 664 sys sys 1135900764 2532
+1135900858 58 a sys/src/cmd/unix/drawterm/kern - 20000000775 sys sys 1135900801 0
+1135900858 59 a sys/src/cmd/unix/drawterm/kern/Makefile - 664 sys sys 1135900764 571
+1135900858 60 a sys/src/cmd/unix/drawterm/kern/allocb.c - 664 sys sys 1135900764 3172
+1135900858 61 a sys/src/cmd/unix/drawterm/kern/cache.c - 664 sys sys 1135900764 466
+1135900858 62 a sys/src/cmd/unix/drawterm/kern/chan.c - 664 sys sys 1135900764 29593
+1135900858 63 a sys/src/cmd/unix/drawterm/kern/dat.h - 664 sys sys 1135900765 10716
+1135900858 64 a sys/src/cmd/unix/drawterm/kern/data.c - 664 sys sys 1135900765 423
+1135900858 65 a sys/src/cmd/unix/drawterm/kern/dev.c - 664 sys sys 1135900765 8523
+1135900858 66 a sys/src/cmd/unix/drawterm/kern/devcons.c - 664 sys sys 1135900765 19526
+1135900858 67 a sys/src/cmd/unix/drawterm/kern/devdraw.c - 664 sys sys 1135900765 42481
+1135900858 68 a sys/src/cmd/unix/drawterm/kern/devfs-posix.c - 664 sys sys 1135900765 9772
+1135900858 69 a sys/src/cmd/unix/drawterm/kern/devfs-win32.c - 664 sys sys 1135900766 10723
+1135900858 70 a sys/src/cmd/unix/drawterm/kern/devip-posix.c - 664 sys sys 1135900766 3488
+1135900858 71 a sys/src/cmd/unix/drawterm/kern/devip-win32.c - 664 sys sys 1135900766 3534
+1135900858 72 a sys/src/cmd/unix/drawterm/kern/devip.c - 664 sys sys 1135900766 16045
+1135900858 73 a sys/src/cmd/unix/drawterm/kern/devip.h - 664 sys sys 1135900766 469
+1135900858 74 a sys/src/cmd/unix/drawterm/kern/devlfd.c - 664 sys sys 1135900766 1534
+1135900858 75 a sys/src/cmd/unix/drawterm/kern/devmnt.c - 664 sys sys 1135900767 21739
+1135900858 76 a sys/src/cmd/unix/drawterm/kern/devmouse.c - 664 sys sys 1135900767 3799
+1135900858 77 a sys/src/cmd/unix/drawterm/kern/devpipe.c - 664 sys sys 1135900767 5927
+1135900858 78 a sys/src/cmd/unix/drawterm/kern/devroot.c - 664 sys sys 1135900767 4717
+1135900858 79 a sys/src/cmd/unix/drawterm/kern/devssl.c - 664 sys sys 1135900767 26455
+1135900858 80 a sys/src/cmd/unix/drawterm/kern/devtab.c - 664 sys sys 1135900767 470
+1135900858 81 a sys/src/cmd/unix/drawterm/kern/error.c - 664 sys sys 1135900767 2100
+1135900858 82 a sys/src/cmd/unix/drawterm/kern/error.h - 664 sys sys 1135900768 2583
+1135900858 83 a sys/src/cmd/unix/drawterm/kern/exportfs.c - 664 sys sys 1135900768 13444
+1135900858 84 a sys/src/cmd/unix/drawterm/kern/fns.h - 664 sys sys 1135900768 10731
+1135900858 85 a sys/src/cmd/unix/drawterm/kern/netif.h - 664 sys sys 1135900768 2950
+1135900858 86 a sys/src/cmd/unix/drawterm/kern/parse.c - 664 sys sys 1135900768 1993
+1135900858 87 a sys/src/cmd/unix/drawterm/kern/pgrp.c - 664 sys sys 1135900768 4017
+1135900858 88 a sys/src/cmd/unix/drawterm/kern/posix.c - 664 sys sys 1135900768 3149
+1135900858 89 a sys/src/cmd/unix/drawterm/kern/procinit.c - 664 sys sys 1135900769 1039
+1135900858 90 a sys/src/cmd/unix/drawterm/kern/qio.c - 664 sys sys 1135900769 23496
+1135900858 91 a sys/src/cmd/unix/drawterm/kern/qlock.c - 664 sys sys 1135900769 1119
+1135900858 92 a sys/src/cmd/unix/drawterm/kern/rendez.c - 664 sys sys 1135900769 1293
+1135900858 93 a sys/src/cmd/unix/drawterm/kern/rwlock.c - 664 sys sys 1135900769 634
+1135900858 94 a sys/src/cmd/unix/drawterm/kern/screen.h - 664 sys sys 1135900769 1151
+1135900858 95 a sys/src/cmd/unix/drawterm/kern/sleep.c - 664 sys sys 1135900769 1293
+1135900858 96 a sys/src/cmd/unix/drawterm/kern/smalloc.c - 664 sys sys 1135900769 187
+1135900858 97 a sys/src/cmd/unix/drawterm/kern/stub.c - 664 sys sys 1135900770 1273
+1135900858 98 a sys/src/cmd/unix/drawterm/kern/syscall.c - 664 sys sys 1135900770 12876
+1135900858 99 a sys/src/cmd/unix/drawterm/kern/sysfile.c - 664 sys sys 1135900770 18035
+1135900858 100 a sys/src/cmd/unix/drawterm/kern/sysproc.c - 664 sys sys 1135900770 498
+1135900858 101 a sys/src/cmd/unix/drawterm/kern/term.c - 664 sys sys 1135900770 3962
+1135900858 102 a sys/src/cmd/unix/drawterm/kern/todo.c - 664 sys sys 1135900770 0
+1135900858 103 a sys/src/cmd/unix/drawterm/kern/uart.c - 664 sys sys 1135900771 178
+1135900858 104 a sys/src/cmd/unix/drawterm/kern/waserror.c - 664 sys sys 1135900771 382
+1135900858 105 a sys/src/cmd/unix/drawterm/kern/win32.c - 664 sys sys 1135900771 7800
+1135900858 106 c sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1135900535 7806
+1135900858 107 a sys/src/cmd/unix/drawterm/libauth - 20000000775 sys sys 1135900560 0
+1135900858 108 a sys/src/cmd/unix/drawterm/libauth/Makefile - 664 sys sys 1135900556 306
+1135900858 109 a sys/src/cmd/unix/drawterm/libauth/attr.c - 664 sys sys 1135900556 2857
+1135900858 110 a sys/src/cmd/unix/drawterm/libauth/auth_attr.c - 664 sys sys 1135900556 217
+1135900858 111 a sys/src/cmd/unix/drawterm/libauth/auth_challenge.c - 664 sys sys 1135900556 1976
+1135900858 112 a sys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c - 664 sys sys 1135900556 1363
+1135900858 113 a sys/src/cmd/unix/drawterm/libauth/auth_proxy.c - 664 sys sys 1135900557 3606
+1135900858 114 a sys/src/cmd/unix/drawterm/libauth/auth_respond.c - 664 sys sys 1135900560 1420
+1135900858 115 a sys/src/cmd/unix/drawterm/libauth/auth_rpc.c - 664 sys sys 1135900560 2064
+1135900858 116 a sys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c - 664 sys sys 1135900560 1097
+1135900858 117 a sys/src/cmd/unix/drawterm/libauth/authlocal.h - 664 sys sys 1135900560 87
+1135900858 118 a sys/src/cmd/unix/drawterm/libauth/httpauth.c - 664 sys sys 1135900560 1059
+1135900858 119 a sys/src/cmd/unix/drawterm/libauthsrv - 20000000775 sys sys 1135900562 0
+1135900858 120 a sys/src/cmd/unix/drawterm/libauthsrv/Makefile - 664 sys sys 1135900560 355
+1135900858 121 a sys/src/cmd/unix/drawterm/libauthsrv/_asgetticket.c - 664 sys sys 1135900560 280
+1135900858 122 a sys/src/cmd/unix/drawterm/libauthsrv/_asrdresp.c - 664 sys sys 1135900560 874
+1135900858 123 a sys/src/cmd/unix/drawterm/libauthsrv/authdial.c - 664 sys sys 1135900561 711
+1135900858 124 a sys/src/cmd/unix/drawterm/libauthsrv/convA2M.c - 664 sys sys 1135900561 501
+1135900858 125 a sys/src/cmd/unix/drawterm/libauthsrv/convM2A.c - 664 sys sys 1135900561 470
+1135900858 126 a sys/src/cmd/unix/drawterm/libauthsrv/convM2PR.c - 664 sys sys 1135900561 610
+1135900858 127 a sys/src/cmd/unix/drawterm/libauthsrv/convM2T.c - 664 sys sys 1135900561 579
+1135900858 128 a sys/src/cmd/unix/drawterm/libauthsrv/convM2TR.c - 664 sys sys 1135900561 617
+1135900858 129 a sys/src/cmd/unix/drawterm/libauthsrv/convPR2M.c - 664 sys sys 1135900561 563
+1135900858 130 a sys/src/cmd/unix/drawterm/libauthsrv/convT2M.c - 664 sys sys 1135900561 558
+1135900858 131 a sys/src/cmd/unix/drawterm/libauthsrv/convTR2M.c - 664 sys sys 1135900561 562
+1135900858 132 a sys/src/cmd/unix/drawterm/libauthsrv/nvcsum.c - 664 sys sys 1135900562 192
+1135900858 133 a sys/src/cmd/unix/drawterm/libauthsrv/opasstokey.c - 664 sys sys 1135900562 448
+1135900858 134 a sys/src/cmd/unix/drawterm/libauthsrv/passtokey.c - 664 sys sys 1135900562 517
+1135900858 135 a sys/src/cmd/unix/drawterm/libauthsrv/readnvram.c - 664 sys sys 1135900562 8446
+1135900858 136 a sys/src/cmd/unix/drawterm/libc - 20000000775 sys sys 1135900573 0
+1135900858 137 a sys/src/cmd/unix/drawterm/libc/Makefile - 664 sys sys 1135900562 1097
+1135900858 138 a sys/src/cmd/unix/drawterm/libc/charstod.c - 664 sys sys 1135900562 1661
+1135900858 139 a sys/src/cmd/unix/drawterm/libc/cleanname.c - 664 sys sys 1135900562 1199
+1135900858 140 a sys/src/cmd/unix/drawterm/libc/convD2M.c - 664 sys sys 1135900562 1398
+1135900858 141 a sys/src/cmd/unix/drawterm/libc/convM2D.c - 664 sys sys 1135900563 1419
+1135900858 142 a sys/src/cmd/unix/drawterm/libc/convM2S.c - 664 sys sys 1135900563 4969
+1135900858 143 a sys/src/cmd/unix/drawterm/libc/convS2M.c - 664 sys sys 1135900563 5014
+1135900858 144 a sys/src/cmd/unix/drawterm/libc/crypt.c - 664 sys sys 1135900563 1045
+1135900858 145 a sys/src/cmd/unix/drawterm/libc/dial.c - 664 sys sys 1135900563 3703
+1135900858 146 a sys/src/cmd/unix/drawterm/libc/dirfstat.c - 664 sys sys 1135900563 676
+1135900858 147 a sys/src/cmd/unix/drawterm/libc/dirfwstat.c - 664 sys sys 1135900563 242
+1135900858 148 a sys/src/cmd/unix/drawterm/libc/dirmodefmt.c - 664 sys sys 1135900563 581
+1135900858 149 a sys/src/cmd/unix/drawterm/libc/dirstat.c - 664 sys sys 1135900563 688
+1135900858 150 a sys/src/cmd/unix/drawterm/libc/dirwstat.c - 664 sys sys 1135900564 246
+1135900858 151 a sys/src/cmd/unix/drawterm/libc/dofmt.c - 664 sys sys 1135900564 8626
+1135900858 152 a sys/src/cmd/unix/drawterm/libc/dorfmt.c - 664 sys sys 1135900564 777
+1135900858 153 a sys/src/cmd/unix/drawterm/libc/errfmt.c - 664 sys sys 1135900564 175
+1135900858 154 a sys/src/cmd/unix/drawterm/libc/fcallfmt.c - 664 sys sys 1135900564 5740
+1135900858 155 a sys/src/cmd/unix/drawterm/libc/fltfmt.c - 664 sys sys 1135900564 4345
+1135900858 156 a sys/src/cmd/unix/drawterm/libc/fmt.c - 664 sys sys 1135900564 2940
+1135900858 157 a sys/src/cmd/unix/drawterm/libc/fmt.h - 664 sys sys 1135900565 3075
+1135900858 158 a sys/src/cmd/unix/drawterm/libc/fmtdef.h - 664 sys sys 1135900565 1808
+1135900858 159 a sys/src/cmd/unix/drawterm/libc/fmtfd.c - 664 sys sys 1135900565 508
+1135900858 160 a sys/src/cmd/unix/drawterm/libc/fmtlock.c - 664 sys sys 1135900565 134
+1135900858 161 a sys/src/cmd/unix/drawterm/libc/fmtprint.c - 664 sys sys 1135900565 465
+1135900858 162 a sys/src/cmd/unix/drawterm/libc/fmtquote.c - 664 sys sys 1135900565 4732
+1135900858 163 a sys/src/cmd/unix/drawterm/libc/fmtrune.c - 664 sys sys 1135900565 314
+1135900858 164 a sys/src/cmd/unix/drawterm/libc/fmtstr.c - 664 sys sys 1135900565 140
+1135900858 165 a sys/src/cmd/unix/drawterm/libc/fmtvprint.c - 664 sys sys 1135900565 449
+1135900858 166 a sys/src/cmd/unix/drawterm/libc/fprint.c - 664 sys sys 1135900566 174
+1135900858 167 a sys/src/cmd/unix/drawterm/libc/frand.c - 664 sys sys 1135900566 210
+1135900858 168 a sys/src/cmd/unix/drawterm/libc/getfields.c - 664 sys sys 1135900566 516
+1135900858 169 a sys/src/cmd/unix/drawterm/libc/getpid.c - 664 sys sys 1135900566 198
+1135900858 170 a sys/src/cmd/unix/drawterm/libc/lnrand.c - 664 sys sys 1135900566 194
+1135900858 171 a sys/src/cmd/unix/drawterm/libc/lock.c - 664 sys sys 1135900566 774
+1135900858 172 a sys/src/cmd/unix/drawterm/libc/lrand.c - 664 sys sys 1135900566 1109
+1135900858 173 a sys/src/cmd/unix/drawterm/libc/mallocz.c - 664 sys sys 1135900566 141
+1135900858 174 a sys/src/cmd/unix/drawterm/libc/nan.h - 664 sys sys 1135900566 114
+1135900858 175 a sys/src/cmd/unix/drawterm/libc/nan64.c - 664 sys sys 1135900567 921
+1135900858 176 a sys/src/cmd/unix/drawterm/libc/netmkaddr.c - 664 sys sys 1135900567 863
+1135900858 177 a sys/src/cmd/unix/drawterm/libc/nrand.c - 664 sys sys 1135900567 191
+1135900858 178 a sys/src/cmd/unix/drawterm/libc/nsec.c - 664 sys sys 1135900567 1196
+1135900858 179 a sys/src/cmd/unix/drawterm/libc/pow10.c - 664 sys sys 1135900567 1946
+1135900858 180 a sys/src/cmd/unix/drawterm/libc/print.c - 664 sys sys 1135900567 164
+1135900858 181 a sys/src/cmd/unix/drawterm/libc/pushssl.c - 664 sys sys 1135900567 905
+1135900858 182 a sys/src/cmd/unix/drawterm/libc/rand.c - 664 sys sys 1135900567 79
+1135900858 183 a sys/src/cmd/unix/drawterm/libc/read9pmsg.c - 664 sys sys 1135900567 462
+1135900858 184 a sys/src/cmd/unix/drawterm/libc/readn.c - 664 sys sys 1135900568 234
+1135900858 185 a sys/src/cmd/unix/drawterm/libc/rune.c - 664 sys sys 1135900568 2306
+1135900858 186 a sys/src/cmd/unix/drawterm/libc/runefmtstr.c - 664 sys sys 1135900568 144
+1135900858 187 a sys/src/cmd/unix/drawterm/libc/runeseprint.c - 664 sys sys 1135900568 204
+1135900858 188 a sys/src/cmd/unix/drawterm/libc/runesmprint.c - 664 sys sys 1135900568 176
+1135900858 189 a sys/src/cmd/unix/drawterm/libc/runesnprint.c - 664 sys sys 1135900568 203
+1135900858 190 a sys/src/cmd/unix/drawterm/libc/runesprint.c - 664 sys sys 1135900568 192
+1135900858 191 a sys/src/cmd/unix/drawterm/libc/runestrcat.c - 664 sys sys 1135900568 124
+1135900858 192 a sys/src/cmd/unix/drawterm/libc/runestrchr.c - 664 sys sys 1135900568 207
+1135900858 193 a sys/src/cmd/unix/drawterm/libc/runestrcmp.c - 664 sys sys 1135900569 221
+1135900858 194 a sys/src/cmd/unix/drawterm/libc/runestrcpy.c - 664 sys sys 1135900569 138
+1135900858 195 a sys/src/cmd/unix/drawterm/libc/runestrdup.c - 664 sys sys 1135900569 180
+1135900858 196 a sys/src/cmd/unix/drawterm/libc/runestrecpy.c - 664 sys sys 1135900569 202
+1135900858 197 a sys/src/cmd/unix/drawterm/libc/runestrlen.c - 664 sys sys 1135900569 94
+1135900858 198 a sys/src/cmd/unix/drawterm/libc/runestrncat.c - 664 sys sys 1135900569 213
+1135900858 199 a sys/src/cmd/unix/drawterm/libc/runestrncmp.c - 664 sys sys 1135900569 250
+1135900858 200 a sys/src/cmd/unix/drawterm/libc/runestrncpy.c - 664 sys sys 1135900569 234
+1135900858 201 a sys/src/cmd/unix/drawterm/libc/runestrrchr.c - 664 sys sys 1135900569 182
+1135900858 202 a sys/src/cmd/unix/drawterm/libc/runestrstr.c - 664 sys sys 1135900570 397
+1135900858 203 a sys/src/cmd/unix/drawterm/libc/runetype.c - 664 sys sys 1135900570 29655
+1135900858 204 a sys/src/cmd/unix/drawterm/libc/runevseprint.c - 664 sys sys 1135900570 313
+1135900858 205 a sys/src/cmd/unix/drawterm/libc/runevsmprint.c - 664 sys sys 1135900570 1043
+1135900858 206 a sys/src/cmd/unix/drawterm/libc/runevsnprint.c - 664 sys sys 1135900570 330
+1135900858 207 a sys/src/cmd/unix/drawterm/libc/seprint.c - 664 sys sys 1135900570 196
+1135900858 208 a sys/src/cmd/unix/drawterm/libc/smprint.c - 664 sys sys 1135900570 168
+1135900858 209 a sys/src/cmd/unix/drawterm/libc/snprint.c - 664 sys sys 1135900570 195
+1135900858 210 a sys/src/cmd/unix/drawterm/libc/sprint.c - 664 sys sys 1135900570 236
+1135900858 211 a sys/src/cmd/unix/drawterm/libc/strecpy.c - 664 sys sys 1135900571 223
+1135900858 212 a sys/src/cmd/unix/drawterm/libc/strtod.c - 664 sys sys 1135900571 8558
+1135900858 213 a sys/src/cmd/unix/drawterm/libc/strtod.h - 664 sys sys 1135900571 120
+1135900858 214 a sys/src/cmd/unix/drawterm/libc/strtoll.c - 664 sys sys 1135900571 1302
+1135900858 215 a sys/src/cmd/unix/drawterm/libc/sysfatal.c - 664 sys sys 1135900571 479
+1135900858 216 a sys/src/cmd/unix/drawterm/libc/time.c - 664 sys sys 1135900571 878
+1135900858 217 a sys/src/cmd/unix/drawterm/libc/tokenize.c - 664 sys sys 1135900571 1691
+1135900858 218 a sys/src/cmd/unix/drawterm/libc/truerand.c - 664 sys sys 1135900571 306
+1135900858 219 a sys/src/cmd/unix/drawterm/libc/u16.c - 664 sys sys 1135900571 823
+1135900858 220 a sys/src/cmd/unix/drawterm/libc/u32.c - 664 sys sys 1135900572 2414
+1135900858 221 a sys/src/cmd/unix/drawterm/libc/u64.c - 664 sys sys 1135900572 3282
+1135900858 222 a sys/src/cmd/unix/drawterm/libc/utf.h - 664 sys sys 1135900572 1442
+1135900858 223 a sys/src/cmd/unix/drawterm/libc/utfdef.h - 664 sys sys 1135900572 335
+1135900858 224 a sys/src/cmd/unix/drawterm/libc/utfecpy.c - 664 sys sys 1135900572 284
+1135900858 225 a sys/src/cmd/unix/drawterm/libc/utflen.c - 664 sys sys 1135900572 242
+1135900858 226 a sys/src/cmd/unix/drawterm/libc/utfnlen.c - 664 sys sys 1135900572 317
+1135900858 227 a sys/src/cmd/unix/drawterm/libc/utfrrune.c - 664 sys sys 1135900572 414
+1135900858 228 a sys/src/cmd/unix/drawterm/libc/utfrune.c - 664 sys sys 1135900572 401
+1135900858 229 a sys/src/cmd/unix/drawterm/libc/utfutf.c - 664 sys sys 1135900573 391
+1135900858 230 a sys/src/cmd/unix/drawterm/libc/vfprint.c - 664 sys sys 1135900573 518
+1135900858 231 a sys/src/cmd/unix/drawterm/libc/vseprint.c - 664 sys sys 1135900573 309
+1135900858 232 a sys/src/cmd/unix/drawterm/libc/vsmprint.c - 664 sys sys 1135900573 997
+1135900858 233 a sys/src/cmd/unix/drawterm/libc/vsnprint.c - 664 sys sys 1135900573 326
+1135900858 234 a sys/src/cmd/unix/drawterm/libdraw/Makefile - 664 sys sys 1135900573 293
+1135900858 235 c sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 1135900573 4095
+1135900858 236 c sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 1135900574 2839
+1135900858 237 c sys/src/cmd/unix/drawterm/libdraw/bytesperline.c - 664 sys sys 1135900574 617
+1135900858 238 c sys/src/cmd/unix/drawterm/libdraw/chan.c - 664 sys sys 1135900574 1151
+1135900858 239 c sys/src/cmd/unix/drawterm/libdraw/defont.c - 664 sys sys 1135900574 30537
+1135900858 240 a sys/src/cmd/unix/drawterm/libdraw/drawrepl.c - 664 sys sys 1135900574 314
+1135900858 241 c sys/src/cmd/unix/drawterm/libdraw/icossin.c - 664 sys sys 1135900574 2117
+1135900858 242 c sys/src/cmd/unix/drawterm/libdraw/icossin2.c - 664 sys sys 1135900574 4587
+1135900858 243 c sys/src/cmd/unix/drawterm/libdraw/rectclip.c - 664 sys sys 1135900575 571
+1135900858 244 c sys/src/cmd/unix/drawterm/libdraw/rgb.c - 664 sys sys 1135900575 1679
+1135900858 245 a sys/src/cmd/unix/drawterm/libmemdraw/Makefile - 664 sys sys 1135900575 391
+1135900858 246 c sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 664 sys sys 1135900575 3309
+1135900858 247 m sys/src/cmd/unix/drawterm/libmemdraw/alloc.c - 664 sys sys 1135900575 3309
+1135900858 248 a sys/src/cmd/unix/drawterm/libmemdraw/alpha.hoc - 664 sys sys 1135900575 220
+1135900858 249 c sys/src/cmd/unix/drawterm/libmemdraw/arc.c - 664 sys sys 1135900575 2608
+1135900858 250 c sys/src/cmd/unix/drawterm/libmemdraw/arctest.c - 664 sys sys 1135900575 865
+1135900858 251 c sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 664 sys sys 1135900576 1338
+1135900858 252 m sys/src/cmd/unix/drawterm/libmemdraw/cload.c - 664 sys sys 1135900576 1338
+1135900858 253 c sys/src/cmd/unix/drawterm/libmemdraw/cmap.c - 664 sys sys 1135900576 25150
+1135900858 254 c sys/src/cmd/unix/drawterm/libmemdraw/cread.c - 664 sys sys 1135900576 1982
+1135900858 255 c sys/src/cmd/unix/drawterm/libmemdraw/defont.c - 664 sys sys 1135900576 1293
+1135900858 256 c sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 664 sys sys 1135900576 54684
+1135900858 257 m sys/src/cmd/unix/drawterm/libmemdraw/draw.c - 664 sys sys 1135900576 54684
+1135900858 258 a sys/src/cmd/unix/drawterm/libmemdraw/drawtest.c - 664 sys sys 1135900576 23441
+1135900858 259 c sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c - 664 sys sys 1135900576 4864
+1135900858 260 c sys/src/cmd/unix/drawterm/libmemdraw/fillpoly.c - 664 sys sys 1135900576 9973
+1135900858 261 c sys/src/cmd/unix/drawterm/libmemdraw/hwdraw.c - 664 sys sys 1135900577 159
+1135900858 262 c sys/src/cmd/unix/drawterm/libmemdraw/iprint.c - 664 sys sys 1135900577 128
+1135900858 263 c sys/src/cmd/unix/drawterm/libmemdraw/line.c - 664 sys sys 1135900577 11059
+1135900858 264 c sys/src/cmd/unix/drawterm/libmemdraw/load.c - 664 sys sys 1135900577 1496
+1135900858 265 m sys/src/cmd/unix/drawterm/libmemdraw/load.c - 664 sys sys 1135900577 1496
+1135900858 266 a sys/src/cmd/unix/drawterm/libmemdraw/mkcmap.c - 664 sys sys 1135900577 1394
+1135900858 267 a sys/src/cmd/unix/drawterm/libmemdraw/openmemsubfont.c - 664 sys sys 1135900577 900
+1135900858 268 c sys/src/cmd/unix/drawterm/libmemdraw/poly.c - 664 sys sys 1135900577 484
+1135900858 269 c sys/src/cmd/unix/drawterm/libmemdraw/read.c - 664 sys sys 1135900577 2159
+1135900858 270 c sys/src/cmd/unix/drawterm/libmemdraw/string.c - 664 sys sys 1135900577 1081
+1135900858 271 c sys/src/cmd/unix/drawterm/libmemdraw/subfont.c - 664 sys sys 1135900578 561
+1135900858 272 a sys/src/cmd/unix/drawterm/libmemdraw/times - 664 sys sys 1135900578 586
+1135900858 273 c sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 664 sys sys 1135900578 435
+1135900858 274 m sys/src/cmd/unix/drawterm/libmemdraw/unload.c - 664 sys sys 1135900578 435
+1135900858 275 a sys/src/cmd/unix/drawterm/libmemdraw/write.c - 664 sys sys 1135900578 4375
+1135900858 276 a sys/src/cmd/unix/drawterm/libmemlayer/Makefile - 664 sys sys 1135900578 319
+1135900858 277 c sys/src/cmd/unix/drawterm/libmemlayer/draw.c - 664 sys sys 1135900578 4064
+1135900858 278 c sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 664 sys sys 1135900578 1794
+1135900858 279 m sys/src/cmd/unix/drawterm/libmemlayer/lalloc.c - 664 sys sys 1135900578 1794
+1135900858 280 c sys/src/cmd/unix/drawterm/libmemlayer/layerop.c - 664 sys sys 1135900578 2641
+1135900858 281 c sys/src/cmd/unix/drawterm/libmemlayer/ldelete.c - 664 sys sys 1135900579 1183
+1135900858 282 c sys/src/cmd/unix/drawterm/libmemlayer/lhide.c - 664 sys sys 1135900579 1675
+1135900858 283 c sys/src/cmd/unix/drawterm/libmemlayer/line.c - 664 sys sys 1135900579 2587
+1135900858 284 c sys/src/cmd/unix/drawterm/libmemlayer/load.c - 664 sys sys 1135900579 1032
+1135900858 285 c sys/src/cmd/unix/drawterm/libmemlayer/lorigin.c - 664 sys sys 1135900579 2507
+1135900858 286 c sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 1135900579 703
+1135900858 287 c sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 1135900579 1289
+1135900858 288 c sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 1135900579 1062
+1135900858 289 a sys/src/cmd/unix/drawterm/libmemlayer/unload.c - 664 sys sys 1135900579 1007
+1135900858 290 a sys/src/cmd/unix/drawterm/libmp - 20000000775 sys sys 1135900584 0
+1135900858 291 a sys/src/cmd/unix/drawterm/libmp/Makefile - 664 sys sys 1135900580 602
+1135900858 292 a sys/src/cmd/unix/drawterm/libmp/betomp.c - 664 sys sys 1135900580 577
+1135900858 293 a sys/src/cmd/unix/drawterm/libmp/crt.c - 664 sys sys 1135900580 2050
+1135900858 294 a sys/src/cmd/unix/drawterm/libmp/crttest.c - 664 sys sys 1135900580 813
+1135900858 295 a sys/src/cmd/unix/drawterm/libmp/dat.h - 664 sys sys 1135900580 464
+1135900858 296 a sys/src/cmd/unix/drawterm/libmp/letomp.c - 664 sys sys 1135900581 455
+1135900858 297 a sys/src/cmd/unix/drawterm/libmp/mpadd.c - 664 sys sys 1135900581 783
+1135900858 298 a sys/src/cmd/unix/drawterm/libmp/mpaux.c - 664 sys sys 1135900581 2564
+1135900858 299 a sys/src/cmd/unix/drawterm/libmp/mpcmp.c - 664 sys sys 1135900581 462
+1135900858 300 a sys/src/cmd/unix/drawterm/libmp/mpdigdiv.c - 664 sys sys 1135900581 732
+1135900858 301 a sys/src/cmd/unix/drawterm/libmp/mpdiv.c - 664 sys sys 1135900581 2423
+1135900858 302 a sys/src/cmd/unix/drawterm/libmp/mpeuclid.c - 664 sys sys 1135900581 1226
+1135900858 303 a sys/src/cmd/unix/drawterm/libmp/mpexp.c - 664 sys sys 1135900581 1149
+1135900858 304 a sys/src/cmd/unix/drawterm/libmp/mpextendedgcd.c - 664 sys sys 1135900581 1613
+1135900858 305 a sys/src/cmd/unix/drawterm/libmp/mpfmt.c - 664 sys sys 1135900582 2729
+1135900858 306 a sys/src/cmd/unix/drawterm/libmp/mpinvert.c - 664 sys sys 1135900582 394
+1135900858 307 a sys/src/cmd/unix/drawterm/libmp/mpleft.c - 664 sys sys 1135900582 838
+1135900858 308 a sys/src/cmd/unix/drawterm/libmp/mpmod.c - 664 sys sys 1135900582 247
+1135900858 309 a sys/src/cmd/unix/drawterm/libmp/mpmul.c - 664 sys sys 1135900582 3110
+1135900858 310 a sys/src/cmd/unix/drawterm/libmp/mprand.c - 664 sys sys 1135900582 584
+1135900858 311 a sys/src/cmd/unix/drawterm/libmp/mpright.c - 664 sys sys 1135900582 695
+1135900858 312 a sys/src/cmd/unix/drawterm/libmp/mpsub.c - 664 sys sys 1135900582 792
+1135900858 313 a sys/src/cmd/unix/drawterm/libmp/mptobe.c - 664 sys sys 1135900582 879
+1135900858 314 a sys/src/cmd/unix/drawterm/libmp/mptoi.c - 664 sys sys 1135900582 553
+1135900858 315 a sys/src/cmd/unix/drawterm/libmp/mptole.c - 664 sys sys 1135900583 786
+1135900858 316 a sys/src/cmd/unix/drawterm/libmp/mptoui.c - 664 sys sys 1135900583 413
+1135900858 317 a sys/src/cmd/unix/drawterm/libmp/mptouv.c - 664 sys sys 1135900583 727
+1135900858 318 a sys/src/cmd/unix/drawterm/libmp/mptov.c - 664 sys sys 1135900583 995
+1135900858 319 a sys/src/cmd/unix/drawterm/libmp/mpvecadd.c - 664 sys sys 1135900583 519
+1135900858 320 a sys/src/cmd/unix/drawterm/libmp/mpveccmp.c - 664 sys sys 1135900583 402
+1135900858 321 a sys/src/cmd/unix/drawterm/libmp/mpvecdigmuladd.c - 664 sys sys 1135900583 1582
+1135900858 322 a sys/src/cmd/unix/drawterm/libmp/mpvecsub.c - 664 sys sys 1135900583 523
+1135900858 323 a sys/src/cmd/unix/drawterm/libmp/os.h - 664 sys sys 1135900583 34
+1135900858 324 a sys/src/cmd/unix/drawterm/libmp/reduce - 664 sys sys 1135900584 306
+1135900858 325 a sys/src/cmd/unix/drawterm/libmp/strtomp.c - 664 sys sys 1135900584 3026
+1135900858 326 a sys/src/cmd/unix/drawterm/libsec/Makefile - 664 sys sys 1135900584 771
+1135900858 327 a sys/src/cmd/unix/drawterm/libsec/aes.c - 664 sys sys 1135900584 64145
+1135900858 328 a sys/src/cmd/unix/drawterm/libsec/blowfish.c - 664 sys sys 1135900584 19676
+1135900858 329 a sys/src/cmd/unix/drawterm/libsec/decodepem.c - 664 sys sys 1135900584 1371
+1135900858 330 c sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1135900584 17496
+1135900858 331 a sys/src/cmd/unix/drawterm/libsec/des3CBC.c - 664 sys sys 1135900584 1135
+1135900858 332 a sys/src/cmd/unix/drawterm/libsec/des3ECB.c - 664 sys sys 1135900585 917
+1135900858 333 c sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1135900585 1079
+1135900858 334 c sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1135900585 861
+1135900858 335 c sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1135900585 647
+1135900858 336 a sys/src/cmd/unix/drawterm/libsec/dsaalloc.c - 664 sys sys 1135900585 864
+1135900858 337 a sys/src/cmd/unix/drawterm/libsec/dsagen.c - 664 sys sys 1135900585 1237
+1135900858 338 a sys/src/cmd/unix/drawterm/libsec/dsaprimes.c - 664 sys sys 1135900585 1881
+1135900858 339 a sys/src/cmd/unix/drawterm/libsec/dsaprivtopub.c - 664 sys sys 1135900585 279
+1135900858 340 a sys/src/cmd/unix/drawterm/libsec/dsasign.c - 664 sys sys 1135900586 934
+1135900858 341 a sys/src/cmd/unix/drawterm/libsec/dsaverify.c - 664 sys sys 1135900586 909
+1135900858 342 a sys/src/cmd/unix/drawterm/libsec/egalloc.c - 664 sys sys 1135900586 778
+1135900858 343 a sys/src/cmd/unix/drawterm/libsec/egdecrypt.c - 664 sys sys 1135900586 564
+1135900858 344 a sys/src/cmd/unix/drawterm/libsec/egencrypt.c - 664 sys sys 1135900586 806
+1135900858 345 a sys/src/cmd/unix/drawterm/libsec/eggen.c - 664 sys sys 1135900586 413
+1135900858 346 a sys/src/cmd/unix/drawterm/libsec/egprivtopub.c - 664 sys sys 1135900586 273
+1135900858 347 a sys/src/cmd/unix/drawterm/libsec/egsign.c - 664 sys sys 1135900586 807
+1135900858 348 a sys/src/cmd/unix/drawterm/libsec/egtest.c - 664 sys sys 1135900587 655
+1135900858 349 a sys/src/cmd/unix/drawterm/libsec/egverify.c - 664 sys sys 1135900587 519
+1135900858 350 a sys/src/cmd/unix/drawterm/libsec/fastrand.c - 664 sys sys 1135900587 258
+1135900858 351 a sys/src/cmd/unix/drawterm/libsec/genprime.c - 664 sys sys 1135900587 535
+1135900858 352 a sys/src/cmd/unix/drawterm/libsec/genrandom.c - 664 sys sys 1135900587 1171
+1135900858 353 a sys/src/cmd/unix/drawterm/libsec/gensafeprime.c - 664 sys sys 1135900587 741
+1135900858 354 a sys/src/cmd/unix/drawterm/libsec/genstrongprime.c - 664 sys sys 1135900587 1039
+1135900858 355 a sys/src/cmd/unix/drawterm/libsec/hmac.c - 664 sys sys 1135900587 1167
+1135900858 356 a sys/src/cmd/unix/drawterm/libsec/hmactest.c - 664 sys sys 1135900588 344
+1135900858 357 c sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1135900588 4260
+1135900858 358 a sys/src/cmd/unix/drawterm/libsec/md4test.c - 664 sys sys 1135900588 537
+1135900858 359 c sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1135900588 3254
+1135900858 360 c sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1135900588 5015
+1135900858 361 a sys/src/cmd/unix/drawterm/libsec/md5pickle.c - 664 sys sys 1135900588 657
+1135900858 362 a sys/src/cmd/unix/drawterm/libsec/nfastrand.c - 664 sys sys 1135900588 327
+1135900858 363 a sys/src/cmd/unix/drawterm/libsec/os.h - 664 sys sys 1135900588 33
+1135900858 364 a sys/src/cmd/unix/drawterm/libsec/primetest.c - 664 sys sys 1135900589 2486
+1135900858 365 a sys/src/cmd/unix/drawterm/libsec/prng.c - 664 sys sys 1135900589 187
+1135900858 366 a sys/src/cmd/unix/drawterm/libsec/probably_prime.c - 664 sys sys 1135900589 1567
+1135900858 367 a sys/src/cmd/unix/drawterm/libsec/ranlib.core - 664 sys sys 1135900590 430080
+1135900858 368 c sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1135900590 1415
+1135900858 369 a sys/src/cmd/unix/drawterm/libsec/readcert.c - 664 sys sys 1135900590 759
+1135900858 370 a sys/src/cmd/unix/drawterm/libsec/rsaalloc.c - 664 sys sys 1135900590 657
+1135900858 371 a sys/src/cmd/unix/drawterm/libsec/rsadecrypt.c - 664 sys sys 1135900590 749
+1135900858 372 a sys/src/cmd/unix/drawterm/libsec/rsaencrypt.c - 664 sys sys 1135900590 192
+1135900858 373 a sys/src/cmd/unix/drawterm/libsec/rsafill.c - 664 sys sys 1135900590 1104
+1135900858 374 a sys/src/cmd/unix/drawterm/libsec/rsagen.c - 664 sys sys 1135900591 1451
+1135900858 375 a sys/src/cmd/unix/drawterm/libsec/rsaprivtopub.c - 664 sys sys 1135900591 237
+1135900858 376 a sys/src/cmd/unix/drawterm/libsec/rsatest.c - 664 sys sys 1135900591 1095
+1135900858 377 c sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1135900591 2279
+1135900858 378 c sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1135900591 4673
+1135900858 379 a sys/src/cmd/unix/drawterm/libsec/sha1pickle.c - 664 sys sys 1135900591 717
+1135900858 380 a sys/src/cmd/unix/drawterm/libsec/smallprimes.c - 664 sys sys 1135900591 6851
+1135900858 381 a sys/src/cmd/unix/drawterm/libsec/smallprimetest.c - 664 sys sys 1135900591 70640
+1135900858 382 a sys/src/cmd/unix/drawterm/libsec/thumb.c - 664 sys sys 1135900592 1891
+1135900858 383 a sys/src/cmd/unix/drawterm/libsec/tlshand.c - 664 sys sys 1135900592 53926
+1135900858 384 a sys/src/cmd/unix/drawterm/libsec/x509.c - 664 sys sys 1135900592 50237
+1135900858 385 a sys/src/cmd/unix/drawterm/main.c - 664 sys sys 1135900536 2440
+1135900858 386 a sys/src/cmd/unix/drawterm/posix-386 - 20000000775 sys sys 1135900540 0
+1135900858 387 a sys/src/cmd/unix/drawterm/posix-386/Makefile - 664 sys sys 1135900540 378
+1135900858 388 a sys/src/cmd/unix/drawterm/posix-386/getcallerpc.c - 664 sys sys 1135900540 90
+1135900858 389 a sys/src/cmd/unix/drawterm/posix-386/md5block.spp - 664 sys sys 1135900540 6472
+1135900858 390 a sys/src/cmd/unix/drawterm/posix-386/sha1block.spp - 664 sys sys 1135900540 4749
+1135900858 391 a sys/src/cmd/unix/drawterm/posix-386/tas.c - 664 sys sys 1135900540 270
+1135900858 392 a sys/src/cmd/unix/drawterm/posix-factotum.c - 664 sys sys 1135900536 1880
+1135900858 393 a sys/src/cmd/unix/drawterm/posix-mips - 20000000775 sys sys 1135900037 0
+1135900858 394 a sys/src/cmd/unix/drawterm/posix-power - 20000000775 sys sys 1135900541 0
+1135900858 395 a sys/src/cmd/unix/drawterm/posix-power/Makefile - 664 sys sys 1135900541 291
+1135900858 396 a sys/src/cmd/unix/drawterm/posix-power/getcallerpc.c - 664 sys sys 1135900541 90
+1135900858 397 a sys/src/cmd/unix/drawterm/posix-power/md5block.c - 664 sys sys 1135900541 5032
+1135900858 398 a sys/src/cmd/unix/drawterm/posix-power/sha1block.c - 664 sys sys 1135900541 4710
+1135900858 399 a sys/src/cmd/unix/drawterm/posix-power/tas.c - 664 sys sys 1135900541 943
+1135900858 400 a sys/src/cmd/unix/drawterm/readcons.c - 664 sys sys 1135900536 1842
+1135900858 401 a sys/src/cmd/unix/drawterm/resource.h - 664 sys sys 1135900536 457
+1135900858 402 a sys/src/cmd/unix/drawterm/secstore.c - 664 sys sys 1135900536 15742
+1135900858 403 a sys/src/cmd/unix/drawterm/win32-386 - 20000000775 sys sys 1135900544 0
+1135900858 404 a sys/src/cmd/unix/drawterm/win32-386/Makefile - 664 sys sys 1135900544 291
+1135900858 405 a sys/src/cmd/unix/drawterm/win32-386/getcallerpc.c - 664 sys sys 1135900544 90
+1135900858 406 a sys/src/cmd/unix/drawterm/win32-386/md5block.spp - 664 sys sys 1135900544 6591
+1135900858 407 a sys/src/cmd/unix/drawterm/win32-386/sha1block.spp - 664 sys sys 1135900544 4912
+1135900858 408 a sys/src/cmd/unix/drawterm/win32-386/tas.c - 664 sys sys 1135900544 270
+1135900858 409 a sys/src/cmd/unix/drawterm/win32-factotum.c - 664 sys sys 1135900536 238
+1135900858 410 d sys/src/cmd/unix/drawterm/wstrtoutf.c - 664 sys sys 954098657 0
+1135900858 411 d sys/src/cmd/unix/drawterm/winscreen.c - 664 sys sys 954098657 0
+1135900858 412 d sys/src/cmd/unix/drawterm/windows.h - 664 sys sys 954098656 0
+1135900858 413 d sys/src/cmd/unix/drawterm/windows.c - 664 sys sys 954098655 0
+1135900858 414 d sys/src/cmd/unix/drawterm/werrstr.c - 664 sys sys 954098655 0
+1135900858 415 d sys/src/cmd/unix/drawterm/utfrune.c - 664 sys sys 954098654 0
+1135900858 416 d sys/src/cmd/unix/drawterm/utflen.c - 664 sys sys 954098654 0
+1135900858 417 d sys/src/cmd/unix/drawterm/unix.h - 664 sys sys 954098653 0
+1135900858 418 d sys/src/cmd/unix/drawterm/tokenize.c - 664 sys sys 954098653 0
+1135900858 419 d sys/src/cmd/unix/drawterm/term.c - 664 sys sys 954098652 0
+1135900858 420 d sys/src/cmd/unix/drawterm/tabs.h - 664 sys sys 954098652 0
+1135900858 421 d sys/src/cmd/unix/drawterm/tabs.c - 664 sys sys 954098651 0
+1135900858 422 d sys/src/cmd/unix/drawterm/syscall.c - 664 sys sys 954098651 0
+1135900858 423 d sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 1077480280 0
+1135900858 424 d sys/src/cmd/unix/drawterm/solaris.c - 664 sys sys 954098649 0
+1135900858 425 d sys/src/cmd/unix/drawterm/screen.h - 664 sys sys 954098649 0
+1135900858 426 d sys/src/cmd/unix/drawterm/screen-x11.c - 664 sys sys 964470495 0
+1135900858 427 d sys/src/cmd/unix/drawterm/screen-win.c - 664 sys sys 954098648 0
+1135900858 428 d sys/src/cmd/unix/drawterm/rwlock.c - 664 sys sys 954098647 0
+1135900858 429 d sys/src/cmd/unix/drawterm/rune.c - 664 sys sys 954098647 0
+1135900858 430 d sys/src/cmd/unix/drawterm/ref.c - 664 sys sys 954098646 0
+1135900858 431 d sys/src/cmd/unix/drawterm/readn.c - 664 sys sys 954098646 0
+1135900858 432 d sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 1077480279 0
+1135900858 433 d sys/src/cmd/unix/drawterm/pushssl.c - 664 sys sys 1077480278 0
+1135900858 434 d sys/src/cmd/unix/drawterm/proc.c - 664 sys sys 954098645 0
+1135900858 435 d sys/src/cmd/unix/drawterm/print.c - 664 sys sys 954098644 0
+1135900858 436 d sys/src/cmd/unix/drawterm/pow10.c - 664 sys sys 954098643 0
+1135900858 437 d sys/src/cmd/unix/drawterm/posix.c - 664 sys sys 964470494 0
+1135900858 438 d sys/src/cmd/unix/drawterm/pipe.c - 664 sys sys 954098642 0
+1135900858 439 d sys/src/cmd/unix/drawterm/passtokey.c - 664 sys sys 954098642 0
+1135900858 440 d sys/src/cmd/unix/drawterm/os.h - 664 sys sys 1019839871 0
+1135900858 441 d sys/src/cmd/unix/drawterm/ns.c - 664 sys sys 954098641 0
+1135900858 442 d sys/src/cmd/unix/drawterm/new.bat - 664 sys sys 954098640 0
+1135900858 443 d sys/src/cmd/unix/drawterm/netmkaddr.c - 664 sys sys 954098639 0
+1135900858 444 d sys/src/cmd/unix/drawterm/ndrawterm.mdp - 664 sys sys 954098639 0
+1135900858 445 d sys/src/cmd/unix/drawterm/nan.c - 664 sys sys 954098638 0
+1135900858 446 d sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 1077480277 0
+1135900858 447 d sys/src/cmd/unix/drawterm/mkfile-Solaris-sparc - 664 sys sys 954098637 0
+1135900858 448 d sys/src/cmd/unix/drawterm/mkfile-Solaris-386 - 664 sys sys 954098636 0
+1135900858 449 d sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 1077480276 0
+1135900858 450 d sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 1077480276 0
+1135900858 451 d sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1080159060 0
+1135900858 452 d sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 1077480275 0
+1135900858 453 d sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1077480274 0
+1135900858 454 d sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 1077480274 0
+1135900858 455 d sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1077480273 0
+1135900858 456 d sys/src/cmd/unix/drawterm/mallocz.c - 664 sys sys 954098632 0
+1135900858 457 d sys/src/cmd/unix/drawterm/lock.c - 664 sys sys 954098632 0
+1135900858 458 d sys/src/cmd/unix/drawterm/lock-osf1.s - 664 sys sys 954098631 0
+1135900858 459 d sys/src/cmd/unix/drawterm/lock-irix.s - 664 sys sys 954098631 0
+1135900858 460 d sys/src/cmd/unix/drawterm/linux.c - 664 sys sys 963353235 0
+1135900858 461 d sys/src/cmd/unix/drawterm/libsec/u64.c - 664 sys sys 1077480285 0
+1135900858 462 d sys/src/cmd/unix/drawterm/libsec/libsec.h - 664 sys sys 1077480283 0
+1135900858 463 d sys/src/cmd/unix/drawterm/libmemlayer/memlayer.h - 664 sys sys 954098729 0
+1135900858 464 d sys/src/cmd/unix/drawterm/libmemdraw/xmem.h - 664 sys sys 954098725 0
+1135900858 465 d sys/src/cmd/unix/drawterm/libmemdraw/memdraw.h - 664 sys sys 954098722 0
+1135900858 466 d sys/src/cmd/unix/drawterm/libmemdraw/load-x11.c - 664 sys sys 954098721 0
+1135900858 467 d sys/src/cmd/unix/drawterm/libmemdraw/load-win.c - 664 sys sys 954098721 0
+1135900858 468 d sys/src/cmd/unix/drawterm/libmemdraw/draw-x11.c - 664 sys sys 954098718 0
+1135900858 469 d sys/src/cmd/unix/drawterm/libmemdraw/draw-win.c - 664 sys sys 954098718 0
+1135900858 470 d sys/src/cmd/unix/drawterm/libmemdraw/cload-x11.c - 664 sys sys 954098716 0
+1135900858 471 d sys/src/cmd/unix/drawterm/libmemdraw/cload-win.c - 664 sys sys 954098716 0
+1135900858 472 d sys/src/cmd/unix/drawterm/libmemdraw/alloc-x11.c - 664 sys sys 954098714 0
+1135900858 473 d sys/src/cmd/unix/drawterm/libmemdraw/alloc-win.c - 664 sys sys 954098714 0
+1135900858 474 d sys/src/cmd/unix/drawterm/libdraw/draw.h - 664 sys sys 954098712 0
+1135900858 475 d sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 1077480272 0
+1135900858 476 d sys/src/cmd/unix/drawterm/keyboard.h - 664 sys sys 1080159172 0
+1135900858 477 d sys/src/cmd/unix/drawterm/kbd.c - 664 sys sys 954098627 0
+1135900858 478 d sys/src/cmd/unix/drawterm/irix.c - 664 sys sys 954098626 0
+1135900858 479 d sys/src/cmd/unix/drawterm/ip.h - 664 sys sys 954098625 0
+1135900858 480 d sys/src/cmd/unix/drawterm/glyph.c - 664 sys sys 954098624 0
+1135900858 481 d sys/src/cmd/unix/drawterm/getuser.c - 664 sys sys 954098622 0
+1135900858 482 d sys/src/cmd/unix/drawterm/getcallerpc.c - 664 sys sys 954098622 0
+1135900858 483 d sys/src/cmd/unix/drawterm/fcallconv.c - 664 sys sys 954098621 0
+1135900858 484 d sys/src/cmd/unix/drawterm/fcall.h - 664 sys sys 954098620 0
+1135900858 485 d sys/src/cmd/unix/drawterm/exportfs.c - 664 sys sys 964798439 0
+1135900858 486 d sys/src/cmd/unix/drawterm/error.h - 664 sys sys 954098619 0
+1135900858 487 d sys/src/cmd/unix/drawterm/error.c - 664 sys sys 954098619 0
+1135900858 488 d sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1077480270 0
+1135900858 489 d sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 1077480269 0
+1135900858 490 d sys/src/cmd/unix/drawterm/dirfstat.c - 664 sys sys 954098617 0
+1135900858 491 d sys/src/cmd/unix/drawterm/dial.c - 664 sys sys 954098617 0
+1135900858 492 d sys/src/cmd/unix/drawterm/devunixfs.c - 664 sys sys 954098616 0
+1135900858 493 d sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 1077480268 0
+1135900858 494 d sys/src/cmd/unix/drawterm/devssl.c - 664 sys sys 1077480268 0
+1135900858 495 d sys/src/cmd/unix/drawterm/devroot.c - 664 sys sys 954098615 0
+1135900858 496 d sys/src/cmd/unix/drawterm/devpipe.c - 664 sys sys 954098614 0
+1135900858 497 d sys/src/cmd/unix/drawterm/devntfs.c - 664 sys sys 954098614 0
+1135900858 498 d sys/src/cmd/unix/drawterm/devmouse.c - 664 sys sys 954098613 0
+1135900858 499 d sys/src/cmd/unix/drawterm/devmnt.c - 664 sys sys 954098613 0
+1135900858 500 d sys/src/cmd/unix/drawterm/devip-win.c - 664 sys sys 1015701212 0
+1135900858 501 d sys/src/cmd/unix/drawterm/devip-unix.c - 664 sys sys 1046970237 0
+1135900858 502 d sys/src/cmd/unix/drawterm/devdraw.c - 664 sys sys 958504757 0
+1135900858 503 d sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 1077480267 0
+1135900858 504 d sys/src/cmd/unix/drawterm/dev.c - 664 sys sys 954098610 0
+1135900858 505 d sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 1077480266 0
+1135900858 506 d sys/src/cmd/unix/drawterm/convTR2M.c - 664 sys sys 954098609 0
+1135900858 507 d sys/src/cmd/unix/drawterm/convS2M.c - 664 sys sys 954098608 0
+1135900858 508 d sys/src/cmd/unix/drawterm/convM2TR.c - 664 sys sys 954098608 0
+1135900858 509 d sys/src/cmd/unix/drawterm/convM2T.c - 664 sys sys 954098607 0
+1135900858 510 d sys/src/cmd/unix/drawterm/convM2S.c - 664 sys sys 954098607 0
+1135900858 511 d sys/src/cmd/unix/drawterm/convM2D.c - 664 sys sys 954098606 0
+1135900858 512 d sys/src/cmd/unix/drawterm/convD2M.c - 664 sys sys 954098606 0
+1135900858 513 d sys/src/cmd/unix/drawterm/conv.c - 664 sys sys 954098605 0
+1135900858 514 d sys/src/cmd/unix/drawterm/chan.c - 664 sys sys 954098604 0
+1135900858 515 d sys/src/cmd/unix/drawterm/canlock.c - 664 sys sys 954098604 0
+1135900858 516 d sys/src/cmd/unix/drawterm/canlock-x86-gcc.c - 664 sys sys 1020313486 0
+1135900858 517 d sys/src/cmd/unix/drawterm/canlock-power-gcc.c - 664 sys sys 1019839861 0
+1135900858 518 d sys/src/cmd/unix/drawterm/bin/README - 664 sys sys 1113252460 0
+1135900858 519 d sys/src/cmd/unix/drawterm/authlocal.h - 664 sys sys 954098603 0
+1135900858 520 d sys/src/cmd/unix/drawterm/authdial.c - 664 sys sys 954098603 0
+1135900858 521 d sys/src/cmd/unix/drawterm/authaux.c - 664 sys sys 954098602 0
+1135900858 522 d sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 1077480264 0
+1135900858 523 d sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 1077480264 0
+1135900858 524 d sys/src/cmd/unix/drawterm/atexit.c - 664 sys sys 954098601 0
+1135900858 525 d sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s - 664 sys sys 954098600 0
+1135900858 526 d sys/src/cmd/unix/drawterm/asm-Solaris-386.s - 664 sys sys 954098600 0
+1135900858 527 d sys/src/cmd/unix/drawterm/argv0.c - 664 sys sys 954098599 0
+1135900858 528 d sys/src/cmd/unix/drawterm/_asreadn.c - 664 sys sys 954098599 0
+1135900858 529 d sys/src/cmd/unix/drawterm/_asrdresp.c - 664 sys sys 954098598 0
+1135900858 530 d sys/src/cmd/unix/drawterm/_asrdfile.c - 664 sys sys 954098597 0
+1135900858 531 d sys/src/cmd/unix/drawterm/_asgetticket.c - 664 sys sys 954098597 0
+1135900858 532 d sys/src/cmd/unix/drawterm/README.MACOSX - 664 sys sys 1020578504 0
+1135902654 0 c sys/man/8/drawterm - 664 sys sys 1135901219 1741
+1135915258 0 a 386/bin/aquarela - 775 sys sys 1135914849 331831
+1135915258 1 a 386/bin/cifscmd - 775 sys sys 1135914850 342709

+ 29 - 50
sys/man/8/drawterm

@@ -4,6 +4,9 @@ drawterm \- connect to Plan 9 CPU servers from other operating systems
 .SH SYNOPSIS
 .SH SYNOPSIS
 .B drawterm
 .B drawterm
 [
 [
+.B -d
+]
+[
 .B -a
 .B -a
 .I authaddr
 .I authaddr
 ]
 ]
@@ -12,15 +15,24 @@ drawterm \- connect to Plan 9 CPU servers from other operating systems
 .I cpuaddr
 .I cpuaddr
 ]
 ]
 [
 [
-.B -d
-depth
+.B -e
+.I encryption-hash-algs
+]
+[
+.B -k
+.I keypattern
+]
+[
+.B -s
+.I secstoreaddr
 ]
 ]
 [
 [
-.B -r
-root
+.B -u
+.I user
 ]
 ]
 [
 [
-.B -nm
+.B -C
+.I cmd args ...
 ]
 ]
 .SH DESCRIPTION
 .SH DESCRIPTION
 .I Drawterm
 .I Drawterm
@@ -46,66 +58,33 @@ to start
 By default, 
 By default, 
 drawterm
 drawterm
 uses the CPU server
 uses the CPU server
-.B CPUSERV
+.B $cpu
+or
+.BR cpu .
 and the authentication server
 and the authentication server
-.BR AUTHSERV .
+.B $auth
+or
+.BR auth .
 The 
 The 
 .B -a
 .B -a
 and
 and
 .B -c
 .B -c
 options specify alternate servers.
 options specify alternate servers.
-(Edit the source to set appropriate local values  for the variables
-.B AUTHSERV
-and
-.BR CPUSERV ).
-.PP
-On Windows systems, the file system served by the
-terminal (and mounted on
-.BR /mnt/term )
-is the tree rooted at
-.BR c:/ .
-The
-.B -r
-option specifies a different file system root.
-In Windows, the depth of the virtual screen
-provided by
-drawterm
-matches the depth of the actual screen.
-To present a screen with a different depth, use the
-.B -d
-option.
-Both options do nothing on non-Windows systems.
-.PP
-The 
-.B -n
-option causes 
-drawterm to prompt for authentication via
-.IR netkey -style
-challenge/response rather than using
-the password-based protocol typically used
-by terminals.
-.PP
-By default, drawterm queues mouse events to
-guard against lost events due to network latency.
-The
-.B -m
-option turns this behavior off.
+(Edit the source to set appropriate local defaults.)
 .PP
 .PP
 Drawterm has been ported to
 Drawterm has been ported to
-Digital Unix,
+FreeBSD,
 Irix,
 Irix,
 Linux,
 Linux,
-Solaris,
+NetBSD,
 and
 and
 Windows.
 Windows.
-Binaries are kept in
-.BR /sys/src/cmd/unix/drawterm/bin .
+Binaries can be downloaded from
+.BR http://swtch.com/drawterm/ .
 .SH SOURCE
 .SH SOURCE
 .B /sys/src/cmd/unix/drawterm
 .B /sys/src/cmd/unix/drawterm
 .SH DIAGNOSTICS
 .SH DIAGNOSTICS
-The Unix versions of drawterm print diagnostics
-to standard error.
-The Windows version displays message boxes.
+Drawterm prints most diagnostics in its own window.
 .SH "SEE ALSO
 .SH "SEE ALSO
 .IR cpu (1),
 .IR cpu (1),
 .IR rio (1)
 .IR rio (1)

+ 1 - 0
sys/src/cmd/aquarela/COPYRIGHT

@@ -0,0 +1 @@
+Contributed by Nigel Roles <nigel@9fs.org>

+ 69 - 0
sys/src/cmd/aquarela/addname.c

@@ -0,0 +1,69 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+int
+nbnsaddname(uchar *serveripaddr, NbName name, ulong ttl, uchar *ipaddr)
+{
+	NbnsMessage *nq;
+	Alt aa[3];
+	int tries = NbnsRetryBroadcast;
+	NbnsAlarm *a;
+	int rv;
+	NbnsMessage *response;
+
+	nq = nbnsmessagenameregistrationrequestnew(0, serveripaddr == nil, name, ttl, ipaddr);
+	if (nq == nil)
+		return -1;
+	a = nbnsalarmnew();
+	if (a == nil) {
+		free(nq);
+		return -1;
+	}
+	aa[0].c = a->c;
+	aa[0].v = nil;
+	aa[0].op = CHANRCV;
+	aa[1].op = CHANRCV;
+	aa[2].op = CHANEND;
+	while (tries > 0) {
+		NbnsTransaction *t;
+		nq->id = nbnsnextid();
+		t = nbnstransactionnew(nq, serveripaddr);
+		aa[1].c = t->c;
+		aa[1].v = &response;
+		nbnsalarmset(a, NbnsTimeoutBroadcast);
+		for (;;) {
+			int i;
+			i = alt(aa);
+			if (i == 0) {
+				tries--;
+				break;
+			}
+			else if (i == 1) {
+				if (response->opcode == NbnsOpRegistration) {
+					nbnstransactionfree(&t);
+					goto done;
+				}
+				nbnsmessagefree(&response);
+			}
+		}
+		nbnstransactionfree(&t);
+	}
+done:
+	if (tries == 0)
+		rv = -1;
+	else {
+		if (response->rcode != 0)
+			rv = response->rcode;
+		else if (response->an == nil)
+			rv = -1;
+		else
+			rv = 0;
+		nbnsmessagefree(&response);
+	}
+	nbnsalarmfree(&a);
+	nbnsmessagefree(&nq);
+	return rv;
+}

+ 126 - 0
sys/src/cmd/aquarela/alarm.c

@@ -0,0 +1,126 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static struct {
+	int thread;
+	int die;
+	QLock;
+	NbnsAlarm *head;
+} alarmlist = { -1 };
+
+#define MaxLong ((1 << (sizeof(long) * 8 - 1)) - 1)
+
+void
+alarmist(void *)
+{
+	for (;;) {
+		vlong now;
+		long snooze;
+//print("running\n");
+		qlock(&alarmlist);
+		if (alarmlist.die) {
+			qunlock(&alarmlist);
+			break;
+		}
+		now = nsec() / 1000000;
+		while (alarmlist.head && alarmlist.head->expirems <= now) {
+//print("expiring because %lld > %lld\n", alarmlist.head->expirems, now);
+			sendul(alarmlist.head->c, 1);
+			alarmlist.head = alarmlist.head->next;
+		}
+		if (alarmlist.head) {
+			vlong vsnooze = alarmlist.head->expirems - now;
+			if (vsnooze > MaxLong)
+				snooze = MaxLong;
+			else
+				snooze = vsnooze;
+			qunlock(&alarmlist);
+		}
+		else
+			snooze = 60 * 1000;
+//print("snoozing for %ld\n", snooze);
+		qunlock(&alarmlist);
+		sleep(snooze);
+	}
+}
+
+NbnsAlarm *
+nbnsalarmnew(void)
+{
+	NbnsAlarm *a;
+	a = mallocz(sizeof(*a), 1);
+	if (a == nil)
+		return nil;
+	a->c = chancreate(sizeof(ulong), 1);
+	if (a->c == nil) {
+		free(a);
+		return nil;
+	}
+	return a;
+}
+
+void
+nbnsalarmcancel(NbnsAlarm *a)
+{
+	NbnsAlarm **ap;
+	int rv;
+	qlock(&alarmlist);
+	for (ap = &alarmlist.head; *ap && *ap != a; ap = &(*ap)->next)
+		;
+	if (*ap) {
+		*ap = a->next;
+		if (ap == &alarmlist.head)
+			threadint(alarmlist.thread);
+	}
+	qunlock(&alarmlist);
+	do {
+		ulong v;
+		rv = nbrecv(a->c, &v);
+	} while (rv != 0);
+}
+
+void
+nbnsalarmend(void)
+{
+	qlock(&alarmlist);
+	if (alarmlist.thread >= 0) {
+		alarmlist.die = 1;
+		threadint(alarmlist.thread);
+	}
+	qunlock(&alarmlist);
+}
+
+void
+nbnsalarmset(NbnsAlarm *a, ulong millisec)
+{
+	NbnsAlarm **ap;
+	nbnsalarmcancel(a);
+	a->expirems = nsec() / 1000000 + millisec;
+	qlock(&alarmlist);
+	for (ap = &alarmlist.head; *ap; ap = &(*ap)->next)
+		if (a->expirems < (*ap)->expirems)
+			break;
+	a->next = (*ap);
+	*ap = a;
+	if (alarmlist.thread < 0)
+		alarmlist.thread = proccreate(alarmist, nil, 16384);
+	else
+		threadint(alarmlist.thread);
+	qunlock(&alarmlist);
+}
+
+void
+nbnsalarmfree(NbnsAlarm **ap)
+{
+	NbnsAlarm *a;
+	a = *ap;
+	if (a) {
+		nbnsalarmcancel(a);
+		chanfree(a->c);
+		free(a);
+		*ap = nil;
+	}
+}

+ 17 - 0
sys/src/cmd/aquarela/alloc.c

@@ -0,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+void *
+nbemalloc(ulong nbytes)
+{
+	void *p;
+	p = malloc(nbytes);
+	if (p == nil) {
+		print("nbemalloc: failed\n");
+		threadexitsall("mem");
+	}
+	return p;
+}

+ 308 - 0
sys/src/cmd/aquarela/aquarela.c

@@ -0,0 +1,308 @@
+#include "headers.h"
+#include <pool.h>
+
+static void
+disconnecttree(void *magic, void *arg)
+{
+	smbtreedisconnect((SmbSession *)magic, (SmbTree *)arg);
+}
+
+static void
+closesearch(void *magic, void *arg)
+{
+	smbsearchclose((SmbSession *)magic, (SmbSearch *)arg);
+}
+
+static void
+smbsessionfree(SmbSession *s)
+{
+	if (s) {
+		smbidmapfree(&s->tidmap, disconnecttree, s);
+		smbidmapfree(&s->sidmap, closesearch, s);
+		smbbufferfree(&s->response);
+		free(s->client.accountname);
+		free(s->client.primarydomain);
+		free(s->client.nativeos);
+		free(s->client.nativelanman);
+		free(s->transaction.in.parameters);
+		free(s->transaction.in.data);
+		free(s->transaction.in.setup);
+		free(s->transaction.in.name);
+		smbbufferfree(&s->transaction.out.parameters);
+		smbbufferfree(&s->transaction.out.data);
+		auth_freechal(s->cs);
+		free(s);
+	}
+}
+
+int
+smbsessionwrite(SmbSession *smbs, void *p, long n)
+{
+	SmbHeader h;
+	SmbOpTableEntry *ote;
+	uchar *pdata;
+	int rv;
+	SmbBuffer *b = nil;
+	ushort bytecount;
+	SmbProcessResult pr;
+
+	if (smbs->response == nil)
+		smbs->response = smbbuffernew(576);
+	else
+		smbresponsereset(smbs);
+	smbs->errclass = SUCCESS;
+	smbs->error = SUCCESS;
+//	print("received %ld bytes\n", n);
+	if (n <= 0)
+		goto closedown;
+	b = smbbufferinit(p, p, n);
+	if (!smbbuffergetheader(b, &h, &pdata, &bytecount)) {
+		smblogprint(-1, "smb: invalid header\n");
+		goto closedown;
+	}
+smbloglock();
+smblogprint(h.command, "received:\n");
+smblogdata(h.command, smblogprint, p, n, 0x1000);
+smblogunlock();
+	ote = smboptable + h.command;
+	if (ote->name == nil) {
+		smblogprint(-1, "smb: illegal opcode 0x%.2ux\n", h.command);
+		goto unimp;
+	}
+	if (ote->process == nil) {
+		smblogprint(-1, "smb: opcode %s unimplemented\n", ote->name);
+		goto unimp;
+	}
+	if (smbs->nextcommand != SMB_COM_NO_ANDX_COMMAND
+		&& smbs->nextcommand != h.command) {
+		smblogprint(-1, "smb: wrong command - expected %.2ux\n", smbs->nextcommand);
+		goto misc;
+	}
+	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
+	switch (h.command) {
+	case SMB_COM_NEGOTIATE:
+	case SMB_COM_SESSION_SETUP_ANDX:
+	case SMB_COM_TREE_CONNECT_ANDX:
+	case SMB_COM_ECHO:
+		break;
+	default:
+		if (smbs->state != SmbSessionEstablished) {
+			smblogprint(-1, "aquarela: command %.2ux unexpected\n", h.command);
+			goto unimp;
+		}
+	}
+	pr = (*ote->process)(smbs, &h, pdata, b);
+	switch (pr) {
+	case SmbProcessResultUnimp:
+	unimp:
+		smbseterror(smbs, ERRDOS, ERRunsup);
+		pr = SmbProcessResultError;
+		break;
+	case SmbProcessResultFormat:
+		smbseterror(smbs, ERRSRV, ERRsmbcmd);
+		pr = SmbProcessResultError;
+		break;
+	case SmbProcessResultMisc:
+	misc:
+		smbseterror(smbs, ERRSRV, ERRerror);
+		pr = SmbProcessResultError;
+		break;
+	}
+	if (pr == SmbProcessResultError) {
+		smblogprint(h.command, "reply: error %d/%d\n", smbs->errclass, smbs->error);
+		if (!smbresponseputerror(smbs, &h, smbs->errclass, smbs->error))
+			pr = SmbProcessResultDie;
+		else
+			pr = SmbProcessResultReply;
+	}
+	else
+		smblogprint(h.command, "reply: ok\n");
+	if (pr == SmbProcessResultReply)
+		rv = smbresponsesend(smbs) == SmbProcessResultOk ? 0 : -1;
+	else if (pr == SmbProcessResultDie)
+		rv = -1;
+	else
+		rv = 0;
+	goto done;
+closedown:
+	rv = -1;
+done:
+	if (rv < 0) {
+		smblogprintif(smbglobals.log.sessions, "shutting down\n");
+		smbsessionfree(smbs);
+	}
+	smbbufferfree(&b);
+	if (smbglobals.log.poolparanoia)
+		poolcheck(mainmem);
+	return rv;
+}
+
+static int
+nbwrite(NbSession *nbss, void *p, long n)
+{
+	return smbsessionwrite((SmbSession *)nbss->magic, p, n);
+}
+
+static int
+cifswrite(SmbCifsSession *cifs, void *p, long n)
+{
+	return smbsessionwrite((SmbSession *)cifs->magic, p, n);
+}
+
+int
+nbssaccept(void *, NbSession *s, NBSSWRITEFN **writep)
+{
+	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
+	smbs->nbss = s;
+	s->magic = smbs;
+	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
+	*writep = nbwrite;
+	smblogprintif(smbglobals.log.sessions, "netbios session started\n");
+	return 1;
+}
+
+int
+cifsaccept(SmbCifsSession *s, SMBCIFSWRITEFN **writep)
+{
+	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
+	smbs->cifss = s;
+	s->magic = smbs;
+	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
+	*writep = cifswrite;
+	smblogprintif(smbglobals.log.sessions, "cifs session started\n");
+	return 1;
+}
+
+void
+usage(void)
+{
+	print("usage: aquarela [-u unicodevalue]\n");
+	threadexitsall("");
+}
+
+static void
+logset(char *cmd)
+{
+	int x;
+	if (strcmp(cmd, "allcmds") == 0) {
+		for (x = 0; x < 256; x++)
+			smboptable[x].debug = 1;
+		for (x = 0; x < smbtrans2optablesize; x++)
+			smbtrans2optable[x].debug = 1;
+		return;
+	}
+	if (strcmp(cmd, "tids") == 0) {
+		smbglobals.log.tids = 1;
+		return;
+	}
+	if (strcmp(cmd, "sids") == 0) {
+		smbglobals.log.sids = 1;
+		return;
+	}
+	if (strcmp(cmd, "fids") == 0) {
+		smbglobals.log.fids = 1;
+		return;
+	}
+	if (strcmp(cmd, "rap2") == 0) {
+		smbglobals.log.rap2 = 1;
+		return;
+	}
+	else if (strcmp(cmd, "find") == 0) {
+		smbglobals.log.find = 1;
+		return;
+	}
+	if (strcmp(cmd, "query") == 0) {
+		smbglobals.log.query = 1;
+		return;
+	}
+	if (strcmp(cmd, "sharedfiles") == 0) {
+		smbglobals.log.sharedfiles = 1;
+		return;
+	}
+	if (strcmp(cmd, "poolparanoia") == 0) {
+		mainmem->flags |= POOL_PARANOIA;
+		smbglobals.log.poolparanoia = 1;
+		return;
+	}
+	if (strcmp(cmd, "sessions") == 0) {
+		smbglobals.log.sessions = 1;
+		return;
+	}
+	if (strcmp(cmd, "rep") == 0) {
+		smbglobals.log.rep = 1;
+		return;
+	}
+	if (strcmp(cmd, "locks") == 0) {
+		smbglobals.log.locks = 1;
+		return;
+	}
+
+	for (x = 0; x < 256; x++)
+		if (smboptable[x].name && strcmp(smboptable[x].name, cmd) == 0) {
+			smboptable[x].debug = 1;
+			return;
+		}
+	for (x = 0; x < smbtrans2optablesize; x++)
+		if (smbtrans2optable[x].name && strcmp(smbtrans2optable[x].name, cmd) == 0) {
+			smbtrans2optable[x].debug = 1;
+			return;
+		}
+	if (strlen(cmd) == 4 && cmd[0] == '0' && cmd[1] == 'x') {
+		int c;
+		c = strtoul(cmd + 2, 0, 16);
+		if (c >= 0 && c <= 255) {
+			smboptable[c].debug = 1;
+			return;
+		}
+	}
+	print("debugging command %s not recognised\n", cmd);
+}
+
+
+void
+threadmain(int argc, char **argv)
+{
+	NbName from, to;
+	char *e = nil;
+	int netbios = 0;
+	ARGBEGIN {
+	case 'u':
+		smbglobals.unicode = strtol(ARGF(), 0, 0) != 0;
+		break;
+	case 'p':
+		smbglobals.log.print = 1;
+		break;
+	case 'd':
+		logset(ARGF());
+		break;
+	case 'w':
+		smbglobals.primarydomain = ARGF();
+		break;
+	case 'n':
+		netbios = 1;
+		break;
+	default:
+		usage();
+	} ARGEND;
+	smbglobalsguess(0);
+	smblistencifs(cifsaccept);
+	if (netbios) {
+		nbinit();
+		nbmknamefromstring(from, "*");
+		nbmknamefromstring(to, "*smbserver\\x20");
+		nbsslisten(to, from, nbssaccept, nil);
+		nbmknamefromstringandtype(to, smbglobals.serverinfo.name, 0x20);
+		nbsslisten(to, from, nbssaccept, nil);
+	}
+	smblogprint(-1, "Aquarela %d.%d running\n", smbglobals.serverinfo.vmaj, smbglobals.serverinfo.vmin);
+	for (;;) {
+		if (netbios&& !smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 60 * 1000,
+			SV_TYPE_SERVER,
+			smbglobals.serverinfo.remark, &e)) {
+			smblogprint(-1, "hostannounce failed: %s\n", e);
+		}
+		if (sleep(60 * 1000) < 0)
+			break;
+	}
+}
+

+ 239 - 0
sys/src/cmd/aquarela/cifscmd.c

@@ -0,0 +1,239 @@
+#include "headers.h"
+#include <bio.h>
+
+SmbClient *c;
+Biobuf bin, bout;
+static int verbose = 1;
+
+#define	SEP(c)	(((c)==' ')||((c)=='\t')||((c)=='\n'))
+
+typedef struct Slut {
+	char *name;
+	int val;
+} Slut;
+
+static char *
+tokenise(char *s, char **start, char **end)
+{
+	char *to;
+	Rune r;
+	int n;
+
+	while(*s && SEP(*s))				/* skip leading white space */
+		s++;
+	to = *start = s;
+	while(*s){
+		n = chartorune(&r, s);
+		if(SEP(r)){
+			if(to != *start)		/* we have data */
+				break;
+			s += n;				/* null string - keep looking */
+			while(*s && SEP(*s))	
+				s++;
+			to = *start = s;
+		} 
+		else if(r == '\''){
+			s += n;				/* skip leading quote */
+			while(*s){
+				n = chartorune(&r, s);
+				if(r == '\''){
+					if(s[1] != '\'')
+						break;
+					s++;		/* embedded quote */
+				}
+				while (n--)
+					*to++ = *s++;
+			}
+			if(!*s)				/* no trailing quote */
+				break;
+			s++;				/* skip trailing quote */ 
+		}
+		else  {
+			while(n--)
+				*to++ = *s++;
+		}
+	}
+	*end = to;
+	return s;
+}
+
+static int
+parse(char *s, char *fields[], int nfields)
+{
+	int c, argc;
+	char *start, *end;
+
+	argc = 0;
+	c = *s;
+	while(c){
+		s = tokenise(s, &start, &end);
+		c = *s++;
+		if(*start == 0)
+			break;
+		if(argc >= nfields-1)
+			return -1;
+		*end = 0;
+		fields[argc++] = start;
+	}
+	fields[argc] = 0;
+Bprint(&bout, "parse returns %d\n", argc);
+	return argc;
+}
+
+typedef struct {
+	char *name;
+	long (*f)(SmbClient *, int, char *[]);
+	int connected;
+	char *help;
+} Cmd;
+static Cmd cmd[];
+
+static long
+cmdhelp(SmbClient *, int argc, char *argv[])
+{
+	Cmd *cp;
+	char *p;
+
+	if(argc)
+		p = argv[0];
+	else
+		p = 0;
+	for (cp = cmd; cp->name; cp++) {
+		if (p == 0 || strcmp(p, cp->name) == 0)
+			Bprint(&bout, "%s\n", cp->help);
+	}
+	return 0;
+}
+
+static Slut sharemodeslut[] = {
+	{ "compatibility", SMB_OPEN_MODE_SHARE_COMPATIBILITY },
+	{ "exclusive", SMB_OPEN_MODE_SHARE_EXCLUSIVE },
+	{ "denywrite", SMB_OPEN_MODE_SHARE_DENY_WRITE },
+	{ "denyread", SMB_OPEN_MODE_SHARE_DENY_READOREXEC },
+	{ "denynone", SMB_OPEN_MODE_SHARE_DENY_NONE },
+	{ 0 }
+};
+
+static Slut openmodeslut[] = {
+	{ "oread", OREAD },
+	{ "owrite", OWRITE },
+	{ "ordwr", ORDWR },
+	{ "oexec", OEXEC },
+	{ 0 }
+};
+
+static int
+slut(Slut *s, char *pat)
+{
+	while (s->name) {
+		if (cistrcmp(s->name, pat) == 0)
+			return s->val;
+		s++;
+	}
+	Bprint(&bout, "%s unrecognised\n", pat);
+	return -1;	
+}
+
+static long
+cmdopen(SmbClient *c, int argc, char *argv[])
+{
+	char *errmsg;
+	int sm, om;
+	int rv;
+	uchar errclass;
+	ushort error;
+	ushort fid, attr;
+	ulong mtime, size;
+	ushort accessallowed;
+
+	if (argc != 3) {
+		Bprint(&bout, "wrong number of arguments\n");
+		return -1;
+	}
+	sm = slut(sharemodeslut, argv[1]);
+	if (sm < 0) 
+		return -1;
+	om = slut(openmodeslut, argv[2]);
+	if (om < 0)
+		return -1;
+	errmsg = nil;
+	rv = smbclientopen(c, (sm << 3) | om, argv[0], &errclass, &error, &fid, &attr, &mtime, &size, &accessallowed, &errmsg);
+	if (rv == 0) {
+		if (errmsg) {
+			print("local error %s\n", errmsg);
+			free(errmsg);
+			return -1;
+		}
+		return (errclass << 16) | error;
+	}
+	print("fid 0x%.4ux attr 0x%.4ux time %ld size %lud accessallowed %ud\n",
+		fid, attr, mtime, size, accessallowed);
+	return 0;
+}
+
+static Cmd cmd[] = {
+	{ "help",	cmdhelp,	0, "help" },
+	{ "open", cmdopen, 1, "open name sharemode openmode" },
+	{ 0, 0 },
+};
+
+void
+threadmain(int argc, char *argv[])
+{
+	char *errmsg;
+	int ac;
+	char *ap, *av[256];
+	Cmd *cp;
+	long status;
+
+	if (argc > 3) {
+		print("usage: cifscmd [to [share]]\n");
+		exits("args");
+	}
+	smbglobalsguess(1);
+	errmsg = nil;
+
+	if (Binit(&bin, 0, OREAD) == Beof || Binit(&bout, 1, OWRITE) == Beof) {
+		fprint(2, "%s: can't init bio: %r\n", argv0);
+		threadexits("Binit");
+	}
+
+	if (argc > 1) {
+		c = smbconnect(argv[1], argc == 3 ? argv[2] : nil, &errmsg);
+		if (c == nil)
+			fprint(2, "failed to connect: %s\n", errmsg);
+	}
+	while (ap = Brdline(&bin, '\n')) {
+		ap[Blinelen(&bin) - 1] = 0;
+		switch (ac = parse(ap, av, nelem(av))) {
+		default:
+			for (cp = cmd; cp->name; cp++) {
+				if (strcmp(cp->name, av[0]) == 0)
+					break;
+			}
+			if (cp->name == 0) {
+				Bprint(&bout, "eh?\n");
+				break;
+			}
+			if (c == 0 && cp->connected) {
+				Bprint(&bout, "not currently connected\n");
+				break;
+			}
+			if ((status = (*cp->f)(c, ac - 1, &av[1])) != -1) {
+				if(verbose)
+					Bprint(&bout, "ok %ld/%ld\n", status >> 16, status & 0xffff);
+				break;
+			}
+			break;
+
+		case -1:
+			Bprint(&bout, "eh?\n");
+			break;
+
+		case 0:
+			break;
+		}
+		Bflush(&bout);
+	}
+	threadexits(0);
+}

+ 147 - 0
sys/src/cmd/aquarela/client.c

@@ -0,0 +1,147 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static char *hmsg = "headers";
+int chatty = 1;
+
+void
+warning(char *fmt, ...)
+{
+	char err[128];
+	va_list arg;
+
+	va_start(arg, fmt);
+	vseprint(err, err+sizeof(err), fmt, arg);
+	va_end(arg);
+	syslog(1, "netbios-ns", err);
+	if (chatty)
+		print("%s\n", err);
+}
+
+static int
+udpannounce(void)
+{
+	int data, ctl;
+	char dir[64];
+	char datafile[64+6];
+
+	/* get a udp port */
+	ctl = announce("udp!*!netbios-ns", dir);
+	if(ctl < 0){
+		warning("can't announce on netbios-ns udp port");
+		return -1;
+	}
+	snprint(datafile, sizeof(datafile), "%s/data", dir);
+
+	/* turn on header style interface */
+	if(write(ctl, hmsg, strlen(hmsg)) , 0)
+		abort(); /* hmsg */;
+	data = open(datafile, ORDWR);
+	if(data < 0){
+		close(ctl);
+		warning("can't announce on dns udp port");
+		return -1;
+	}
+
+	close(ctl);
+	return data;
+}
+
+#define BROADCAST 1
+
+
+void
+listen137(void *)
+{	
+	for (;;) {
+		uchar msg[Udphdrsize + 576];
+		int len = read(fd137, msg, sizeof(msg));
+		if (len < 0)
+			break;
+		if (len >= Udphdrsize) {
+			NbnsMessage *s;
+			Udphdr *uh;
+			uchar *p;
+
+			uh = (Udphdr*)msg;
+			p = msg + Udphdrsize;
+			len -= Udphdrsize;
+			s = nbnsconvM2S(p, len);
+			if (s) {
+				print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
+				nbnsdumpmessage(s);
+				if (s->response) {
+					NbnsTransaction *t;
+					qlock(&transactionlist);
+					for (t = transactionlist.head; t; t = t->next)
+						if (t->id == s->id)
+							break;
+					if (t) {
+						sendp(t->c, s);
+					}
+					else
+						nbnsmessagefree(&s);
+					qunlock(&transactionlist);
+				}
+				else
+					nbnsmessagefree(&s);
+			}
+		}
+	}
+}
+
+void
+usage(void)
+{
+	print("usage: client [-u ipaddr] name\n");
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	int i;
+	NbName nbname;
+	int listen137thread;
+	uchar ipaddr[IPaddrlen];
+	int rv;
+	int broadcast = 1;
+	uchar serveripaddr[IPaddrlen];
+
+	ARGBEGIN {
+	case 'u':
+		broadcast = 0;
+		parseip(serveripaddr, ARGF());
+		break;
+	default:
+		usage();
+	} ARGEND;
+
+	if (argc == 0)
+		exits("");
+
+	nbmknamefromstring(nbname, argv[0]);
+
+	ipifc = readipifc("/net", nil, 0);
+	if (ipifc == nil || ipifc->lifc == nil) {
+		print("no network interface");
+		exits("");
+	}
+	fmtinstall('I', eipfmt);
+	ipmove(bcastaddr, ipifc->lifc->ip);
+	for (i = 0; i < IPaddrlen; i++)
+		bcastaddr[i] |= ~ipifc->lifc->mask[i];
+	print("broadcasting to %I\n", bcastaddr);
+//	setnetmtpt("/net");
+	fd137 = udpannounce();
+	listen137thread = proccreate(listen137, nil, 16384);
+	rv = nbnsaddname(broadcast ? nil : serveripaddr, nbname, 3000, ipifc->lifc->ip);
+	if (rv != 0)
+		print("error code %d\n", rv);
+	else
+		print("%I\n", ipaddr);
+	nbnsalarmend();
+	threadint(listen137thread);
+}

+ 137 - 0
sys/src/cmd/aquarela/dump.c

@@ -0,0 +1,137 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static char *
+opname(int opcode)
+{
+	switch (opcode) {
+	case NbnsOpQuery: return "query";
+	case NbnsOpRegistration: return "registration";
+	case NbnsOpRelease: return "release";
+	case NbnsOpWack: return "wack";
+	case NbnsOpRefresh: return "refresh";
+	default:
+		return "???";
+	}
+}
+
+void
+nbnsdumpname(NbName name)
+{
+	int x;
+	for (x = 0; x < NbNameLen - 1; x++) {
+		if (name[x] == ' ')
+			break;
+		print("%c", tolower(name[x]));
+	}
+	print("\\x%.2ux", name[NbNameLen - 1]);
+}
+
+void
+nbnsdumpmessagequestion(NbnsMessageQuestion *q)
+{
+	print("question: ");
+	nbnsdumpname(q->name);
+	switch (q->type) {
+	case NbnsQuestionTypeNb: print(" NB");	break;
+	case NbnsQuestionTypeNbStat: print(" NBSTAT"); break;
+	default: print(" ???");
+	}
+	switch (q->class) {
+	case NbnsQuestionClassIn: print(" IN"); break;
+	default: print(" ???");
+	}
+	print("\n");
+}
+
+void
+nbnsdumpmessageresource(NbnsMessageResource *r, char *name)
+{
+	print("%s: ", name);
+	nbnsdumpname(r->name);
+	switch (r->type) {
+	case NbnsResourceTypeA: print(" A");	break;
+	case NbnsResourceTypeNs: print(" NS");	break;
+	case NbnsResourceTypeNull: print(" NULL");	break;
+	case NbnsResourceTypeNb: print(" NB");	break;
+	case NbnsResourceTypeNbStat: print(" NBSTAT"); break;
+	default: print(" ???");
+	}
+	switch (r->class) {
+	case NbnsResourceClassIn: print(" IN"); break;
+	default: print(" ???");
+	}
+	print(" ttl: %lud", r->ttl);
+	if (r->rdlength) {
+		int i;
+		print(" rdata: ");
+		for (i = 0; i < r->rdlength; i++)
+			print("%.2ux", r->rdata[i]);
+	}
+	print("\n");
+}
+
+void
+nbnsdumpmessage(NbnsMessage *s)
+{
+	NbnsMessageQuestion *q;
+	NbnsMessageResource *r;
+	print("0x%.4ux %s %s (%d)",
+		s->id, opname(s->opcode), s->response ? "response" : "request", s->opcode);
+	if (s->broadcast)
+		print(" B");
+	if (s->recursionavailable)
+		print(" RA");
+	if (s->recursiondesired)
+		print(" RD");
+	if (s->truncation)
+		print(" TC");
+	if (s->authoritativeanswer)
+		print(" AA");
+	if (s->response)
+		print(" rcode %d", s->rcode);
+	print("\n");
+	for (q = s->q; q; q = q->next)
+		nbnsdumpmessagequestion(q);
+	for (r = s->an; r; r = r->next)
+		nbnsdumpmessageresource(r, "answer");
+	for (r = s->ns; r; r = r->next)
+		nbnsdumpmessageresource(r, "ns");
+	for (r = s->ar; r; r = r->next)
+		nbnsdumpmessageresource(r, "additional");
+}
+
+void
+nbdumpdata(void *ap, long n)
+{
+	uchar *p = ap;
+	long i;
+	i = 0;
+	while (i < n) {
+		int l = n - i < 16 ? n - i : 16;
+		int b;
+		print("0x%.4lux  ", i);
+		for (b = 0; b < l; b += 2) {
+			print(" %.2ux", p[i + b]);
+			if (b < l - 1)
+				print("%.2ux", p[i + b + 1]);
+			else
+				print("  ");
+		}
+		while (b < 16) {
+			print("     ");
+			b++;
+		}
+		print("        ");
+		for (b = 0; b < l; b++)
+			if (p[i + b] >= ' ' && p[i + b] <= '~')
+				print("%c", p[i + b]);
+			else
+				print(".");
+		print("\n");
+		i += l;
+	}
+}

+ 73 - 0
sys/src/cmd/aquarela/findname.c

@@ -0,0 +1,73 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+int
+nbnsfindname(uchar *serveripaddr, NbName name, uchar *ipaddr, ulong *ttlp)
+{
+	NbnsMessage *nq;
+	Alt aa[3];
+	int tries = NbnsRetryBroadcast;
+	NbnsAlarm *a;
+	int rv;
+	NbnsMessage *response;
+
+	nq = nbnsmessagenamequeryrequestnew(0, serveripaddr == nil, name);
+	if (nq == nil)
+		return -1;
+	a = nbnsalarmnew();
+	if (a == nil) {
+		free(nq);
+		return -1;
+	}
+	aa[0].c = a->c;
+	aa[0].v = nil;
+	aa[0].op = CHANRCV;
+	aa[1].op = CHANRCV;
+	aa[2].op = CHANEND;
+	while (tries > 0) {
+		NbnsTransaction *t;
+		nq->id = nbnsnextid();
+		t = nbnstransactionnew(nq, serveripaddr);
+		aa[1].c = t->c;
+		aa[1].v = &response;
+		nbnsalarmset(a, NbnsTimeoutBroadcast);
+		for (;;) {
+			int i;
+			i = alt(aa);
+			if (i == 0) {
+				tries--;
+				break;
+			}
+			else if (i == 1) {
+				if (response->opcode == NbnsOpQuery) {
+					nbnstransactionfree(&t);
+					goto done;
+				}
+				nbnsmessagefree(&response);
+			}
+		}
+		nbnstransactionfree(&t);
+	}
+done:
+	if (tries == 0)
+		rv = -1;
+	else {
+		if (response->rcode != 0)
+			rv = response->rcode;
+		else if (response->an == nil)
+			rv = -1;
+		else {
+			rv = 0;
+			v4tov6(ipaddr, response->an->rdata + 2);
+			if (ttlp)
+				*ttlp = response->an->ttl;
+		}
+		nbnsmessagefree(&response);
+	}
+	nbnsalarmfree(&a);
+	nbnsmessagefree(&nq);
+	return rv;
+}

+ 10 - 0
sys/src/cmd/aquarela/headers.h

@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include <auth.h>
+#include <regexp.h>
+#include "netbios.h"
+#include "smb.h"
+#include "smbdat.h"
+#include "smbfns.h"

+ 55 - 0
sys/src/cmd/aquarela/message.c

@@ -0,0 +1,55 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+NbnsMessage *
+nbnsmessagenamequeryrequestnew(ushort id, int broadcast, NbName name)
+{
+	NbnsMessage *s;
+	NbnsMessageQuestion *q;
+	s = nbnsmessagenew();
+	if (s == nil)
+		return nil;
+	s->id = id;
+	s->opcode = NbnsOpQuery;
+	s->broadcast = broadcast;
+	s->recursiondesired = 1;
+	q =  nbnsmessagequestionnew(name, NbnsQuestionTypeNb, NbnsQuestionClassIn);
+	if (q == nil) {
+		nbnsmessagefree(&s);
+		return nil;
+	}
+	nbnsmessageaddquestion(s, q);
+	return s;
+}
+
+NbnsMessage *
+nbnsmessagenameregistrationrequestnew(ushort id, int broadcast, NbName name, ulong ttl, uchar *ipaddr)
+{
+	NbnsMessage *s;
+	NbnsMessageQuestion *q;
+	uchar rdata[6];
+	NbnsMessageResource *r;
+
+	s = nbnsmessagenew();
+	if (s == nil)
+		return nil;
+	s->id = id;
+	s->opcode = NbnsOpRegistration;
+	s->broadcast = broadcast;
+	s->recursiondesired = 1;
+	q =  nbnsmessagequestionnew(name, NbnsQuestionTypeNb, NbnsQuestionClassIn);
+	if (q == nil) {
+		nbnsmessagefree(&s);
+		return nil;
+	}
+	nbnsmessageaddquestion(s, q);
+	rdata[0] = 0;
+	rdata[1] = 0;
+	v6tov4(rdata + 2, ipaddr);
+	r = nbnsmessageresourcenew(name, NbnsResourceTypeNb, NbnsResourceClassIn, ttl, 6, rdata);
+	nbnsmessageaddresource(&s->ar, r);
+	return s;
+}

+ 114 - 0
sys/src/cmd/aquarela/mkfile

@@ -0,0 +1,114 @@
+</$objtype/mkfile
+
+CFLAGS=$CFLAGS
+
+UPDATEFLAGS=
+
+FILES=\
+	nbnsconv\
+	dump\
+	message\
+	findname\
+	addname\
+	alarm\
+	nbss\
+	nbns\
+	nbname\
+	alloc\
+	nbresolve\
+	smbconv\
+	smbnegotiate\
+	smballoc\
+	smbcommon\
+	smbcomsessionsetupandx\
+	smbstring\
+	smbresponse\
+	smbcomtreeconnectandx\
+	smbtree\
+	smbservice\
+	smbcomtransaction\
+	smbrap2\
+	smbcomdir\
+	smbglobals\
+	smboptable\
+	smbconnect\
+	smbbuffer\
+	nbdgram\
+	nbdgramconv\
+	nbdgramdump\
+	nb\
+	nblistener\
+	smbtransaction\
+	smbbrowse\
+	smbtrans2find\
+	smbidmap\
+	smbcomecho\
+	smbcomopen\
+	smbtime\
+	smbpath\
+	smbfile\
+	smbtrans2query\
+	smbcomclose\
+	smbcomread\
+	smblog\
+	smbcomquery\
+	smbcomfindclose2\
+	smbcomtreedisconnect\
+	smbsharedfile\
+	smblisten\
+	smbrap2client\
+	smbtrans2client\
+	smbcomdelete\
+	smbdircache\
+	smbrep\
+	smbcomflush\
+	smbcomwrite\
+	smbclientopen\
+	smbcomsetinfo\
+	smbcomcreatedir\
+	smbcomdeletedir\
+	smbcomrename\
+	smbcomlocking\
+	smbtrans2set\
+
+LIBCFILES=${FILES:%=%.c}
+LIBOFILES=${FILES:%=%.$O}
+
+SLIB=libsmb.a.$O
+
+LIB=$SLIB\
+
+HFILES=\
+	headers.h\
+	netbios.h\
+	smb.h\
+	smbfns.h\
+	smbdat.h
+
+TARG=\
+	aquarela\
+	cifscmd\
+#	testconnect\
+#	testnbdgram\
+#	testtime\
+
+
+CFILES=${TARG:%=%.c} $LIBCFILES
+
+BIN=/$objtype/bin
+
+it:V: all
+
+</sys/src/cmd/mkmany
+
+INC=
+CFLAGS=$INC $CFLAGS $XCFLAGS
+
+$SLIB(%.$O):N: %.$O
+$SLIB:	${LIBOFILES:%=$SLIB(%)}
+	names = `{echo $newprereq |sed 's/ /\n/g' |sed -n 's/'$SLIB'\(([^)]+)\)/\1/gp'}
+	ar vu $SLIB $names
+#	rm $names
+
+clean:V:
+	rm -f *.[$OS] y.tab.? y.debug y.output [$OS].* $TARG *.log

+ 25 - 0
sys/src/cmd/aquarela/nb.c

@@ -0,0 +1,25 @@
+#include "headers.h"
+
+NbGlobals nbglobals;
+
+NbName nbnameany = { '*' };
+
+int
+nbinit(void)
+{
+	Ipifc *ipifc;
+	int i;
+	fmtinstall('I', eipfmt);
+	fmtinstall('B', nbnamefmt);
+	ipifc = readipifc("/net", nil, 0);
+	if (ipifc == nil || ipifc->lifc == nil) {
+		print("no network interface");
+		return -1;
+	}
+	ipmove(nbglobals.myipaddr, ipifc->lifc->ip);
+	ipmove(nbglobals.bcastaddr, ipifc->lifc->ip);
+	nbmknamefromstring(nbglobals.myname, sysname());
+	for (i = 0; i < IPaddrlen; i++)
+		nbglobals.bcastaddr[i] |= ~ipifc->lifc->mask[i];
+	return 0;
+}

+ 216 - 0
sys/src/cmd/aquarela/nbdgram.c

@@ -0,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static struct {
+	int thread;
+	QLock;
+	int fd;
+} udp = { -1 };
+
+typedef struct Listen Listen;
+
+struct Listen {
+	NbName to;
+	int (*deliver)(void *magic, NbDgram *s);
+	void *magic;
+	Listen *next;
+};
+
+static struct {
+	QLock;
+	Listen *head;
+} listens;
+
+static void
+udplistener(void *)
+{
+//print("udplistener - starting\n");
+	for (;;) {
+		uchar msg[Udphdrsize + 576];
+		int len = read(udp.fd, msg, sizeof(msg));
+		if (len < 0)
+			break;
+		if (len >= nbudphdrsize) {
+			NbDgram s;
+//			Udphdr *uh;
+			uchar *p;
+			int n;
+
+//			uh = (Udphdr*)msg;
+			p = msg + nbudphdrsize;
+			len -= nbudphdrsize;
+			n = nbdgramconvM2S(&s, p, p + len);
+			if (n) {
+				switch (s.type) {
+				case NbDgramError:
+					print("nbdgramlisten: error: ip %I port %d code 0x%.2ux\n", s.srcip, s.srcport, s.error.code);
+					break;
+				case NbDgramDirectUnique:
+				case NbDgramDirectGroup:
+				case NbDgramBroadcast: {
+					int delivered = 0;
+					Listen **lp, *l;
+					if ((s.flags & NbDgramMore) || s.datagram.offset != 0)
+						break;
+					if (!nbnameisany(s.datagram.dstname)
+						&& !nbnametablefind(s.datagram.dstname, 0)) {
+/* - only do this if a broadcast node, and can tell when packets are broadcast...
+						s.flags &= 3;
+						ipmove(s.srcip, nbglobals.myipaddr);
+						s.srcport = NbDgramPort;
+						s.type = NbDgramError;	
+						s.error.code = NbDgramErrorDestinationNameNotPresent;
+						nbdgramsendto(uh->raddr, nhgets(uh->rport), &s);
+*/
+						break;
+					}
+					qlock(&listens);
+					for (lp = &listens.head; (l = *lp) != nil;) {
+						if (nbnameisany(l->to) || nbnameequal(l->to, s.datagram.dstname)) {
+							switch ((*l->deliver)(l->magic, &s)) {
+							case 0:
+								delivered = 1;
+								/* fall through */
+							case -1:
+								*lp = l->next;
+								free(l);
+								continue;
+							default:
+								delivered = 1;
+								break;
+							}
+						}
+						lp = &l->next;
+					}
+					qunlock(&listens);
+					USED(delivered);
+				}
+				default:
+					;
+				}
+			}
+		}
+	}
+print("udplistener - exiting\n");
+	qlock(&udp);
+	udp.thread = -1;
+	qunlock(&udp);
+}
+
+static char *
+startlistener(void)
+{
+	qlock(&udp);
+	if (udp.thread < 0) {
+		char *e;
+		e = nbudpannounce(NbDgramPort, &udp.fd);
+		if (e) {
+			qunlock(&udp);
+			return e;
+		}
+		udp.thread = proccreate(udplistener, nil, 16384);
+	}
+	qunlock(&udp);
+	return nil;
+}
+
+char *
+nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic)
+{
+	Listen *l;
+	char *e;
+	nbnametablefind(to, 1);
+	e = startlistener();
+	if (e)
+		return e;
+	l = nbemalloc(sizeof(Listen));
+	nbnamecpy(l->to, to);
+	l->deliver = deliver;
+	l->magic = magic;
+	qlock(&listens);
+	l->next = listens.head;
+	listens.head = l;
+	qunlock(&listens);
+	return 0;
+}
+
+int
+nbdgramsendto(uchar *ipaddr, ushort port, NbDgram *s)
+{
+	Udphdr *u;
+	uchar msg[NbDgramMaxPacket + Udphdrsize];
+	int l;
+	int rv;
+	char *e;
+
+	e = startlistener();
+	if (e != nil)
+		return 0;
+
+	l = nbdgramconvS2M(msg + nbudphdrsize, msg + sizeof(msg), s);
+	if (l == 0) {
+		print("conv failed\n");
+		return 0;
+	}
+	u = (Udphdr *)msg;
+	ipmove(u->laddr, nbglobals.myipaddr);
+	hnputs(u->lport, NbDgramPort);
+	ipmove(u->raddr, ipaddr);
+	hnputs(u->rport, port);
+//nbdumpdata(msg, l + nbudphdrsize);
+//print("transmitting\n");
+	rv = write(udp.fd, msg, l + nbudphdrsize);
+//print("rv %d l %d hdrsize %d error %r\n", rv, l, nbudphdrsize);
+	return rv == l + nbudphdrsize;
+}
+
+static struct {
+	Lock;
+	ushort id;
+} id;
+
+static ushort
+nextdgramid(void)
+{
+	ushort v;
+	lock(&id);
+	v = id.id++;
+	unlock(&id);
+	return v;
+}
+
+int
+nbdgramsend(NbDgramSendParameters *p, uchar *data, long datalen)
+{
+	NbDgram s;
+	uchar dstip[IPaddrlen];
+	s.type = p->type;
+	switch (p->type) {
+	case NbDgramBroadcast:
+	case NbDgramDirectGroup:
+		ipmove(dstip, nbglobals.bcastaddr);
+		break;
+	case NbDgramDirectUnique:
+		if (!nbnameresolve(p->to, dstip)) {
+			werrstr("nbdgramsend: name resolution failed");
+			return 0;
+		}
+		break;
+	default:
+		werrstr("nbdgramsend: illegal datagram type");
+		return 0;
+	}
+	s.flags = NbDgramFirst;
+	s.id = nextdgramid();
+	ipmove(s.srcip, nbglobals.myipaddr);
+	s.srcport = NbDgramPort;
+	s.datagram.offset = 0;
+	s.datagram.data = data;
+	s.datagram.length = datalen;
+	nbnamecpy(s.datagram.dstname, p->to);
+	nbnamecpy(s.datagram.srcname, nbglobals.myname);
+	return nbdgramsendto(dstip, NbDgramPort, &s);
+}

+ 116 - 0
sys/src/cmd/aquarela/nbdgramconv.c

@@ -0,0 +1,116 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+int
+nbdgramconvM2S(NbDgram *s, uchar *ap, uchar *ep)
+{
+	uchar *p = ap;
+	int n;
+	ushort length;
+
+	if (ap + 6 + IPv4addrlen > ep)
+		return 0;
+	s->type = *p++;
+	s->flags = *p++;
+	s->id = nhgets(p); p+= 2;
+	v4tov6(s->srcip, p); p+= IPv4addrlen;
+	s->srcport = nhgets(p); p += 2;
+	switch (s->type) {
+	case NbDgramDirectUnique:
+	case NbDgramDirectGroup:
+	case NbDgramBroadcast:
+		if (p + 4 > ep)
+			return 0;
+		length = nhgets(p); p += 2;
+		s->datagram.offset = nhgets(p); p += 2;
+		if (p + length > ep)
+			return 0;
+		ep = p + length;
+		n = nbnamedecode(p, p, ep, s->datagram.srcname);
+		if (n == 0)
+			return 0;
+		p += n;
+		n = nbnamedecode(p, p, ep, s->datagram.dstname);
+		if (n == 0)
+			return 0;
+		p += n;
+		s->datagram.data = p;
+		s->datagram.length = ep - p;
+		p = ep;
+		break;
+	case NbDgramError:
+		if (p + 1 > ep)
+			return 0;
+		s->error.code = *p++;
+		break;
+	case NbDgramQueryRequest:
+	case NbDgramPositiveQueryResponse:
+	case NbDgramNegativeQueryResponse:
+		n = nbnamedecode(p, p, ep, s->query.dstname);
+		if (n == 0)
+			return 0;
+		p += n;
+		break;
+	default:
+		return 0;
+	}
+	return p - ap;
+}
+
+int
+nbdgramconvS2M(uchar *ap, uchar *ep, NbDgram *s)
+{
+	uchar *p = ap;
+	uchar *fixup;
+	int n;
+
+	if (p + 6 + IPv4addrlen > ep)
+		return 0;
+	*p++ = s->type;
+	*p++ = s->flags;
+	hnputs(p, s->id); p+= 2;
+	v6tov4(p, s->srcip); p += IPv4addrlen;
+	hnputs(p, s->srcport); p+= 2;
+	switch (s->type) {
+	case NbDgramDirectUnique:
+	case NbDgramDirectGroup:
+	case NbDgramBroadcast:
+		if (p + 4 > ep)
+			return 0;
+		fixup = p;
+		hnputs(p, s->datagram.length); p += 2;
+		hnputs(p, s->datagram.offset); p += 2;
+		n = nbnameencode(p, ep, s->datagram.srcname);
+		if (n == 0)
+			return 0;
+		p += n;
+		n = nbnameencode(p, ep, s->datagram.dstname);
+		if (n == 0)
+			return 0;
+		p += n;
+		if (p + s->datagram.length > ep)
+			return 0;
+		memcpy(p, s->datagram.data, s->datagram.length); p += s->datagram.length;
+		hnputs(fixup, p - fixup - 4);
+		break;
+	case NbDgramError:
+		if (p + 1 > ep)
+			return 0;
+		*p++ = s->error.code;
+		break;
+	case NbDgramQueryRequest:
+	case NbDgramPositiveQueryResponse:
+	case NbDgramNegativeQueryResponse:
+		n = nbnameencode(p, ep, s->datagram.dstname);
+		if (n == 0)
+			return 0;
+		p += n;
+		break;
+	default:
+		return 0;
+	}
+	return p - ap;
+}

+ 19 - 0
sys/src/cmd/aquarela/nbdgramdump.c

@@ -0,0 +1,19 @@
+#include "headers.h"
+
+void
+nbdgramdump(NbDgram *s)
+{
+	print("type 0x%.2ux flags 0x%.2ux id 0x%.4ux srcip %I port %d\n",
+		s->type, s->flags, s->id, s->srcip, s->srcport);
+	switch (s->type) {
+	case NbDgramError:
+		print("\terror.code 0x%.2ux\n", s->error.code);
+		break;
+	case NbDgramDirectUnique:
+	case NbDgramDirectGroup:
+	case NbDgramBroadcast:
+		print("\tlength %ud offset %ud srcname %B dstname %B\n",
+			s->datagram.length, s->datagram.offset, s->datagram.srcname, s->datagram.dstname);
+		break;
+	}
+}

+ 35 - 0
sys/src/cmd/aquarela/nblistener.c

@@ -0,0 +1,35 @@
+#include "headers.h"
+
+static char *hmsg = "headers";
+static char *ohmsg = "oldheaders";
+
+int nbudphdrsize;
+
+char *
+nbudpannounce(ushort port, int *fdp)
+{
+	int data, ctl;
+	char dir[64];
+	char datafile[64+6];
+	char addr[NETPATHLEN];
+	snprint(addr, sizeof(addr), "udp!*!%d", port);
+	/* get a udp port */
+	ctl = announce(addr, dir);
+	if(ctl < 0)
+		return "can't announce on port";
+	snprint(datafile, sizeof(datafile), "%s/data", dir);
+
+	/* turn on header style interface */
+	nbudphdrsize = Udphdrsize;
+	if (write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)) {
+		return "failed to turn on headers";
+	}
+	data = open(datafile, ORDWR);
+	if (data < 0) {
+		close(ctl);
+		return "failed to open data file";
+	}
+	close(ctl);
+	*fdp = data;
+	return nil;
+}

+ 299 - 0
sys/src/cmd/aquarela/nbname.c

@@ -0,0 +1,299 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static int
+decodehex(char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	else if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	else if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return 0;
+}
+
+static char
+encodehex(int n)
+{
+	if (n >= 0 && n <= 9)
+		return '0' + n;
+	if (n >= 10 && n <= 15)
+		return 'a' + (n - 10);
+	return '?';
+}
+
+static int
+_nameextract(uchar *base, uchar *p, uchar *ep, int k, uchar *outbuf, int outbufmaxlen, int *outbuflenp)
+{
+	uchar *op, *oep, *savep;
+	savep = p;
+	op = outbuf;
+	oep = outbuf + outbufmaxlen;
+	for (;;) {
+		uchar b;
+		int n;
+		if (p >= ep)
+			return 0;
+		b = *p++;
+		if (b == 0)
+			break;
+		if (k) {
+			if (op >= oep)
+				return 0;
+			*op++ = '.';
+		}
+		if ((b & 0xc0) == 0xc0) {
+			ushort off;
+			if (ep - p < 2)
+				return 0;
+			off = nhgets(p - 1) & 0x3fff; p++;
+			if (_nameextract(base, base + off, p, k, op, oep - ep, &n) == 0)
+				return 0;
+			op += n;
+		}
+		else if ((b & 0xc0) != 0x00)
+			return 0;
+		else if (b != 0x20)
+			return 0;
+		else {
+			int x;
+			if (p + b > ep)
+				return 0;
+			if (op + b / 2 > oep)
+				return 0;
+			for (x = 0; x < b; x += 2) {
+				uchar hn, ln;
+				if (*p < 'A' || *p >= 'A' + 16)
+					return 0;
+				hn = *p++ - 'A';
+				if (*p < 'A' || *p >= 'A' + 16)
+					return 0;
+				ln = *p++ - 'A';
+				*op++ = (hn << 4) | ln;
+			}
+		}
+		k++;
+	}
+	*outbuflenp = op - outbuf;
+	return p - savep;
+}
+
+int
+nbnamedecode(uchar *base, uchar *p, uchar *ep, NbName nbname)
+{
+	int n;
+	int rv = _nameextract(base, p, ep, 0, nbname, NbNameLen, &n);
+	if (rv == 0)
+		return rv;
+	if (n != NbNameLen)
+		return 0;
+	return rv;
+}
+
+int
+nbnameencode(uchar *ap, uchar *ep, NbName name)
+{
+	uchar *p = ap;
+	int i;
+	if (p + 1 + 2 * NbNameLen + 1 > ep)
+		return 0;
+	*p++ = NbNameLen * 2;
+	for (i = 0; i < NbNameLen; i++) {
+		*p++ = 'A' + ((name[i] >> 4) & 0xf);
+		*p++ = 'A' + (name[i] & 0xf);
+	}
+	*p++ = 0;
+	return p - ap;
+}
+
+void
+nbnamecpy(NbName n1, NbName n2)
+{
+	memcpy(n1, n2, NbNameLen);
+}
+
+void
+nbmknamefromstring(NbName nbname, char *s)
+{
+	int i;
+	memset(nbname, ' ', NbNameLen - 1);
+	nbname[NbNameLen - 1] = 0;
+	i = 0;
+	while (*s) {
+		if (*s == '\\' && *(s + 1) == 'x') {
+			s += 2;
+			if (*s == 0 || *(s + 1) == 0)
+				return;
+			nbname[NbNameLen - 1] = (decodehex(s[0]) << 4) | decodehex(s[1]);
+			return;
+		} else {
+			if (i < NbNameLen - 1)
+				nbname[i++] = toupper(*s);
+			s++;
+		}
+	}
+}
+
+void
+nbmknamefromstringandtype(NbName nbname, char *s, uchar type)
+{
+	nbmknamefromstring(nbname, s);
+	nbname[NbNameLen - 1] = type;
+}
+
+void
+nbmkstringfromname(char *buf, int buflen, NbName name)
+{
+	int x;
+	for (x = 0; x < NbNameLen - 1; x++) {
+		if (name[x] == ' ')
+			break;
+		if (buflen > 1) {
+			*buf++ = tolower(name[x]);
+			buflen--;
+		}
+	}
+	if (name[NbNameLen - 1] != 0) {
+		if (buflen > 1) {
+			*buf++ = '\\';
+			buflen--;
+		}
+		if (buflen > 1) {
+			*buf++ = 'x';
+			buflen--;
+		}
+		if (buflen > 1) {
+			*buf++ = encodehex(name[NbNameLen - 1] >> 4);
+			buflen--;
+		}
+		if (buflen > 1)
+			*buf++ = encodehex(name[NbNameLen - 1] & 0x0f);
+	}
+	*buf = 0;
+}
+
+int
+nbnameisany(NbName name)
+{
+	return name[0] == '*';
+}
+
+int
+nbnameequal(NbName name1, NbName name2)
+{
+	if (name1[NbNameLen - 1] != name2[NbNameLen - 1])
+		return 0;
+	if (nbnameisany(name1))
+		return 1;
+	if (nbnameisany(name2))
+		return 1;
+	return memcmp(name1, name2, NbNameLen - 1) == 0;
+}
+
+int
+nbnamefmt(Fmt *f)
+{
+	uchar *n;
+	char buf[100];
+	n = va_arg(f->args, uchar *);
+	nbmkstringfromname(buf, sizeof(buf), n);
+	return fmtstrcpy(f, buf);
+}
+
+typedef struct NbNameTableEntry NbNameTableEntry;
+struct NbNameTableEntry {
+	NbName name;
+	NbNameTableEntry *next;
+};
+
+static struct {
+	QLock;
+	NbNameTableEntry *head;
+} nbnametable;
+
+int
+nbnametablefind(NbName name, int add)
+{
+	int rv;
+	NbNameTableEntry *p;
+	qlock(&nbnametable);
+	for (p = nbnametable.head; p; p = p->next) {
+		if (nbnameequal(p->name, name)) {
+			qunlock(&nbnametable);
+			return 1;
+		}
+	}
+	if (add) {
+		p = nbemalloc(sizeof(*p));
+		nbnamecpy(p->name, name);
+		p->next = nbnametable.head;
+		nbnametable.head = p;
+		rv = 1;
+	}
+	else
+		rv = 0;
+	qunlock(&nbnametable);
+	return rv;
+}
+
+typedef struct NbRemoteNameTableEntry NbRemoteNameTableEntry;
+struct NbRemoteNameTableEntry {
+	NbName name;
+	char ipaddr[IPaddrlen];
+	long expire;
+	NbRemoteNameTableEntry *next;
+};
+
+static struct {
+	QLock;
+	NbRemoteNameTableEntry *head;
+} nbremotenametable;
+
+int
+nbremotenametablefind(NbName name, uchar *ipaddr)
+{
+	NbRemoteNameTableEntry *p, **pp;
+	long now = time(nil);
+	qlock(&nbremotenametable);
+	for (pp = &nbremotenametable.head; (p = *pp) != nil;) {
+		if (p->expire <= now) {
+//print("nbremotenametablefind: expired %B\n", p->name);
+			*pp = p->next;
+			free(p);
+			continue;
+		}
+		if (nbnameequal(p->name, name)) {
+			ipmove(ipaddr, p->ipaddr);
+			qunlock(&nbremotenametable);
+			return 1;
+		}
+		pp = &p->next;
+	}
+	qunlock(&nbremotenametable);
+	return 0;
+}
+
+int
+nbremotenametableadd(NbName name, uchar *ipaddr, ulong ttl)
+{
+	NbRemoteNameTableEntry *p;
+	qlock(&nbremotenametable);
+	for (p = nbremotenametable.head; p; p = p->next)
+		if (nbnameequal(p->name, name))
+			break;
+	if (p == nil) {
+		p = nbemalloc(sizeof(*p));
+		p->next = nbremotenametable.head;
+		nbremotenametable.head = p;
+		nbnamecpy(p->name, name);
+	}
+	ipmove(p->ipaddr, ipaddr);
+	p->expire = time(nil) + ttl;
+//print("nbremotenametableadd: %B ttl %lud expire %ld\n", p->name, ttl, p->expire);
+	qunlock(&nbremotenametable);
+	return 1;
+}

+ 156 - 0
sys/src/cmd/aquarela/nbns.c

@@ -0,0 +1,156 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static struct {
+	int thread;
+	QLock;
+	int fd;
+} udp = { -1 };
+
+typedef struct Listen Listen;
+
+struct Listen {
+	NbName to;
+	int (*deliver)(void *magic, NbDgram *s);
+	void *magic;
+	Listen *next;
+};
+
+static struct {
+	Lock;
+	ushort id;
+} id;
+
+struct {
+	QLock;
+	NbnsTransaction *head;
+} transactionlist;
+
+static void
+udplistener(void *)
+{	
+	for (;;) {
+		uchar msg[Udphdrsize + 576];
+		int len = read(udp.fd, msg, sizeof(msg));
+		if (len < 0)
+			break;
+		if (len >= nbudphdrsize) {
+			NbnsMessage *s;
+//			Udphdr *uh;
+			uchar *p;
+
+//			uh = (Udphdr*)msg;
+			p = msg + nbudphdrsize;
+			len -= nbudphdrsize;
+			s = nbnsconvM2S(p, len);
+			if (s) {
+//print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
+//nbnsdumpmessage(s);
+				if (s->response) {
+					NbnsTransaction *t;
+					qlock(&transactionlist);
+					for (t = transactionlist.head; t; t = t->next)
+						if (t->id == s->id)
+							break;
+					if (t)
+						sendp(t->c, s);
+					else
+						nbnsmessagefree(&s);
+					qunlock(&transactionlist);
+				}
+				else
+					nbnsmessagefree(&s);
+			}
+		}
+	}
+}
+
+static char *
+startlistener(void)
+{
+	qlock(&udp);
+	if (udp.thread < 0) {
+		char *e;
+		e = nbudpannounce(NbnsPort, &udp.fd);
+		if (e) {
+			qunlock(&udp);
+			return e;
+		}
+		udp.thread = proccreate(udplistener, nil, 16384);
+	}
+	qunlock(&udp);
+	return nil;
+}
+
+ushort
+nbnsnextid(void)
+{
+	ushort rv;
+	lock(&id);
+	rv = id.id++;
+	unlock(&id);
+	return rv;
+}
+	
+NbnsTransaction *
+nbnstransactionnew(NbnsMessage *s, uchar *ipaddr)
+{
+	NbnsTransaction *t;
+	uchar msg[Udphdrsize + 576];
+	Udphdr *u;
+	int len;
+
+	startlistener();
+	len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize);
+	if (len == 0)
+		return 0;
+	t = mallocz(sizeof(*t), 1);
+	if (t == nil)
+		return nil;
+	t->id = s->id;	
+	t->c = chancreate(sizeof(NbnsMessage *), 3);
+	if (t->c == nil) {
+		free(t);
+		return nil;
+	}
+	qlock(&transactionlist);
+	t->next = transactionlist.head;
+	transactionlist.head = t;
+	qunlock(&transactionlist);
+	u = (Udphdr *)msg;
+	ipmove(u->laddr, nbglobals.myipaddr);
+	hnputs(u->lport, NbnsPort);
+	if (s->broadcast || ipaddr == nil)
+		ipmove(u->raddr, nbglobals.bcastaddr);
+	else
+		ipmove(u->raddr, ipaddr);
+	hnputs(u->rport, NbnsPort);
+	write(udp.fd, msg, len + nbudphdrsize);
+	return t;
+}
+
+void
+nbnstransactionfree(NbnsTransaction **tp)
+{
+	NbnsTransaction **tp2;
+	NbnsMessage *s;
+	NbnsTransaction *t;
+
+	t = *tp;
+	if (t) {
+		qlock(&transactionlist);
+		while ((s = nbrecvp(t->c)) != nil)
+			nbnsmessagefree(&s);
+		for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
+			;
+		if (*tp2) {
+			*tp2 = t->next;
+			free(t);
+		}
+		qunlock(&transactionlist);
+		*tp = nil;
+	}
+}

+ 314 - 0
sys/src/cmd/aquarela/nbnsconv.c

@@ -0,0 +1,314 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+void
+nbnsmessagequestionfree(NbnsMessageQuestion **qp)
+{
+	NbnsMessageQuestion *q = *qp;
+	if (q) {
+		free(q);
+		*qp = nil;
+	}
+}
+
+void
+nbnsmessageresourcefree(NbnsMessageResource **rp)
+{
+	NbnsMessageResource *r = *rp;
+	if (r) {
+		free(r->rdata);
+		free(r);
+		*rp = nil;
+	}
+}
+
+static void
+questionfree(NbnsMessageQuestion **qp)
+{
+	while (*qp) {
+		NbnsMessageQuestion *next = (*qp)->next;
+		nbnsmessagequestionfree(qp);
+		*qp = next;
+	}
+}
+
+static void
+resourcefree(NbnsMessageResource **rp)
+{
+	while (*rp) {
+		NbnsMessageResource *next = (*rp)->next;
+		nbnsmessageresourcefree(rp);
+		*rp = next;
+	}
+}
+
+void
+nbnsmessagefree(NbnsMessage **sp)
+{
+	NbnsMessage *s = *sp;
+	if (s) {
+		questionfree(&s->q);
+		resourcefree(&s->an);
+		resourcefree(&s->ns);
+		resourcefree(&s->ar);
+		free(s);
+		*sp = nil;
+	}
+}
+
+void
+nbnsmessageaddquestion(NbnsMessage *s, NbnsMessageQuestion *q)
+{
+	NbnsMessageQuestion **qp;
+	for (qp = &s->q; *qp; qp = &(*qp)->next)
+		;
+	*qp = q;
+}
+
+NbnsMessageQuestion *
+nbnsmessagequestionnew(NbName name, ushort type, ushort class)
+{
+	NbnsMessageQuestion *q;
+	q = mallocz(sizeof(*q), 1);
+	if (q == nil)
+		return nil;
+	nbnamecpy(q->name, name);
+	q->type = type;
+	q->class = class;
+	return q;
+}
+
+NbnsMessageResource *
+nbnsmessageresourcenew(NbName name, ushort type, ushort class, ulong ttl, int rdlength, uchar *rdata)
+{
+	NbnsMessageResource *r;
+	r= mallocz(sizeof(*r), 1);
+	if (r == nil)
+		return nil;
+	nbnamecpy(r->name, name);
+	r->type = type;
+	r->class = class;
+	r->ttl = ttl;
+	r->rdlength = rdlength;
+	if (rdlength) {
+		r->rdata = malloc(rdlength);
+		if (r->rdata == nil) {
+			free(r);
+			return nil;
+		}
+		memcpy(r->rdata, rdata, rdlength);
+	}
+	return r;
+}
+
+void
+nbnsmessageaddresource(NbnsMessageResource **rp, NbnsMessageResource *r)
+{
+	for (; *rp; rp = &(*rp)->next)
+		;
+	*rp = r;
+}
+
+NbnsMessage *
+nbnsmessagenew(void)
+{
+	return mallocz(sizeof(NbnsMessage), 1);
+}
+
+static int
+resourcedecode(NbnsMessageResource **headp, int count, uchar *ap, uchar *pp, uchar *ep)
+{
+	uchar *p = pp;
+	int i;
+	for (i = 0; i < count; i++) {
+		int n;
+		NbnsMessageResource *r, **rp;
+		r = mallocz(sizeof(NbnsMessageResource), 1);
+		if (r == nil)
+			return -1;
+		for (rp = headp; *rp; rp = &(*rp)->next)
+			;
+		*rp = r;
+		n = nbnamedecode(ap, p, ep, r->name);
+		if (n == 0)
+			return -1;
+		p += n;
+		if (p + 10 > ep)
+			return -1;
+		r->type = nhgets(p); p += 2;
+		r->class = nhgets(p); p += 2;
+		r->ttl = nhgetl(p); p += 4;
+		r->rdlength = nhgets(p); p += 2;
+//print("rdlength %d\n", r->rdlength);
+		if (r->rdlength) {
+			if (p + r->rdlength > ep)
+				return -1;
+			r->rdata = malloc(r->rdlength);
+			if (r == nil)
+				return -1;
+			memcpy(r->rdata, p, r->rdlength);
+			p += r->rdlength;
+		}
+	}
+	return p - pp;
+}
+
+NbnsMessage *
+nbnsconvM2S(uchar *ap, int nap)
+{
+	uchar *p, *ep;
+	ushort qdcount, ancount, nscount, arcount, ctrl;
+	int i;
+	NbnsMessage *s;
+	int n;
+
+	if (nap < 12)
+		return nil;
+	p = ap;
+	ep = ap + nap;
+	s = nbnsmessagenew();
+	if (s == nil)
+		return nil;
+	s->id = nhgets(p); p+= 2;
+	ctrl = nhgets(p); p += 2;
+	qdcount = nhgets(p); p += 2;
+	ancount = nhgets(p); p += 2;
+	nscount = nhgets(p); p += 2;
+	arcount = nhgets(p); p += 2;
+	s->response = (ctrl & NbnsResponse) != 0;
+	s->opcode = (ctrl >> NbnsOpShift) & NbnsOpMask;
+	s->broadcast = (ctrl & NbnsFlagBroadcast) != 0;
+	s->recursionavailable = (ctrl & NbnsFlagRecursionAvailable) != 0;
+	s->recursiondesired = (ctrl & NbnsFlagRecursionDesired) != 0;
+	s->truncation = (ctrl & NbnsFlagTruncation) != 0;
+	s->authoritativeanswer = (ctrl & NbnsFlagAuthoritativeAnswer) != 0;
+	s->rcode = s->response ? (ctrl & NbnsRcodeMask) : 0;
+	for (i = 0; i < qdcount; i++) {
+		int n;
+		NbName nbname;
+		NbnsMessageQuestion *q;
+		ushort type, class;
+		n = nbnamedecode(ap, p, ep, nbname);
+		if (n == 0)
+			goto fail;
+		p += n;
+		if (p + 4 > ep)
+			goto fail;
+		type = nhgets(p); p += 2;
+		class = nhgets(p); p += 2;
+		q = nbnsmessagequestionnew(nbname, type, class);
+		if (q == nil)
+			goto fail;
+		nbnsmessageaddquestion(s, q);
+	}
+	n = resourcedecode(&s->an, ancount, ap, p, ep);
+	if (n < 0)
+		goto fail;
+	p += n;
+	n = resourcedecode(&s->ns, nscount, ap, p, ep);
+	if (n < 0)
+		goto fail;
+	p += n;
+	n = resourcedecode(&s->ar, arcount, ap, p, ep);
+	if (n < 0)
+		goto fail;
+//print("arcount %d\n", arcount);
+	return s;
+fail:
+	nbnsmessagefree(&s);
+	return nil;
+}
+
+static int
+resourceencode(NbnsMessageResource *r, uchar *ap, uchar *ep)
+{
+	uchar *p = ap;
+	for (; r; r = r->next) {
+		int n = nbnameencode(p, ep, r->name);
+		if (n == 0)
+			return -1;
+		p += n;
+		if (p + 10 > ep)
+			return -1;
+		hnputs(p, r->type); p += 2;
+		hnputs(p, r->class); p += 2;
+		hnputl(p, r->ttl); p += 4;
+		hnputs(p, r->rdlength); p += 2;
+		if (p + r->rdlength > ep)
+			return -1;
+		memcpy(p, r->rdata, r->rdlength);
+		p += r->rdlength;
+	}
+	return p - ap;
+}
+
+int
+nbnsconvS2M(NbnsMessage *s, uchar *ap, int nap)
+{
+	uchar *p = ap;
+	uchar *ep = ap + nap;
+	ushort ctrl;
+	NbnsMessageQuestion *q;
+	NbnsMessageResource *r;
+	int k;
+	int n;
+
+	if (p + 12 > ep)
+		return 0;
+	hnputs(p, s->id); p+= 2;
+	ctrl = (s->opcode & NbnsOpMask) << NbnsOpShift;
+	if (s->response) {
+		ctrl |= s->rcode & NbnsRcodeMask;
+		ctrl |= NbnsResponse;
+	}
+	if (s->broadcast)
+		ctrl |= NbnsFlagBroadcast;
+	if (s->recursionavailable)
+		ctrl |= NbnsFlagRecursionAvailable;
+	if (s->recursiondesired)
+		ctrl |= NbnsFlagRecursionDesired;
+	if (s->truncation)
+		ctrl |= NbnsFlagTruncation;
+	if (s->authoritativeanswer)
+		ctrl |= NbnsFlagAuthoritativeAnswer;
+	hnputs(p, ctrl); p += 2;
+	for (q = s->q, k = 0; q; k++, q = q->next)
+		;
+	hnputs(p, k); p += 2;
+	for (r = s->an, k = 0; r; k++, r = r->next)
+		;
+	hnputs(p, k); p += 2;
+	for (r = s->ns, k = 0; r; k++, r = r->next)
+		;
+	hnputs(p, k); p += 2;
+	for (r = s->ar, k = 0; r; k++, r = r->next)
+		;
+	hnputs(p, k); p += 2;
+	for (q = s->q; q; q = q->next) {
+		int n = nbnameencode(p, ep, q->name);
+		if (n == 0)
+			return 0;
+		p += n;
+		if (p + 4 > ep)
+			return 0;
+		hnputs(p, q->type); p += 2;
+		hnputs(p, q->class); p += 2;
+	}
+	n = resourceencode(s->an, p, ep);
+	if (n < 0)
+		return 0;
+	p += n;
+	n = resourceencode(s->ns, p, ep);
+	if (n < 0)
+		return 0;
+	p += n;
+	n = resourceencode(s->ar, p, ep);
+	if (n < 0)
+		return 0;
+	p += n;
+	return p - ap;
+}
+

+ 33 - 0
sys/src/cmd/aquarela/nbresolve.c

@@ -0,0 +1,33 @@
+#include "headers.h"
+#include <bio.h>
+#include <ndb.h>
+
+int
+nbnameresolve(NbName nbname, uchar *ipaddr)
+{
+	/* for now, just use dns */
+	Ndbtuple *t;
+	NbName copy;
+	char name[NETPATHLEN];
+	ulong ttl;
+	if (nbremotenametablefind(nbname, ipaddr)) {
+//print("%B found in cache\n", nbname);
+		return 1;
+	}
+	if (nbnsfindname(nil, nbname, ipaddr, &ttl) == 0) {
+		nbremotenametableadd(nbname, ipaddr, ttl);
+		return 1;
+	}
+	nbnamecpy(copy, nbname);
+	copy[NbNameLen - 1] = 0;
+	nbmkstringfromname(name, sizeof(name), copy);
+	t = dnsquery("/net", name, "ip");
+	if (t == nil)
+		return 0;
+	if (parseip(ipaddr, t->line->val) == 0) {
+		ndbfree(t);
+		return 0;
+	}
+	ndbfree(t);
+	return 1;
+}

+ 428 - 0
sys/src/cmd/aquarela/nbss.c

@@ -0,0 +1,428 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <thread.h>
+#include "netbios.h"
+
+static struct {
+	int thread;
+	QLock;
+	char adir[NETPATHLEN];
+	int acfd;
+	char ldir[NETPATHLEN];
+	int lcfd;
+} tcp = { -1 };
+
+typedef struct Session Session;
+
+enum { NeedSessionRequest, Connected, Dead };
+
+struct Session {
+	NbSession;
+	int thread;
+	Session *next;
+	int state;
+	NBSSWRITEFN *write;
+};
+
+static struct {
+	QLock;
+	Session *head;
+} sessions;
+
+typedef struct Listen Listen;
+
+struct Listen {
+	NbName to;
+	NbName from;
+	int (*accept)(void *magic, NbSession *s, NBSSWRITEFN **writep);
+	void *magic;
+	Listen *next;
+};
+
+static struct {
+	QLock;
+	Listen *head;
+} listens;
+
+static void
+deletesession(Session *s)
+{
+	Session **sp;
+	close(s->fd);
+	qlock(&sessions);
+	for (sp = &sessions.head; *sp && *sp != s; sp = &(*sp)->next)
+		;
+	if (*sp)
+		*sp = s->next;
+	qunlock(&sessions);
+	free(s);
+}
+
+static void
+tcpreader(void *a)
+{
+	Session *s = a;
+	uchar *buf;
+	int buflen = 0x1ffff + 4;
+	buf = nbemalloc(buflen);
+	for (;;) {
+		int n;
+		uchar flags;
+		ushort length;
+
+		n = readn(s->fd, buf, 4);
+		if (n != 4) {
+		die:
+			free(buf);
+			if (s->state == Connected)
+				(*s->write)(s, nil, -1);
+			deletesession(s);
+			return;
+		}
+		flags = buf[1];
+		length = nhgets(buf + 2) | ((flags & 1) << 16);
+		n = readn(s->fd, buf + 4, length);
+		if (n != length)
+			goto die;
+		if (flags & 0xfe) {
+			print("nbss: invalid flags field 0x%.2ux\n", flags);
+			goto die;
+		}
+		switch (buf[0]) {
+		case 0: /* session message */
+			if (s->state != Connected && s->state != Dead) {
+				print("nbss: unexpected session message\n");
+				goto die;
+			}
+			if (s->state == Connected) {
+				if ((*s->write)(s, buf + 4, length) != 0) {
+					s->state = Dead;
+					goto die;
+				}
+			}
+			break;
+		case 0x81: /* session request */ {
+			uchar *p, *ep;
+			Listen *l;
+			int k;
+			int called_found;
+			uchar error_code;
+
+			if (s->state == Connected) {
+				print("nbss: unexpected session request\n");
+				goto die;
+			}
+			p = buf + 4;
+			ep = p + length;
+			k = nbnamedecode(p, p, ep, s->to);
+			if (k == 0) {
+				print("nbss: malformed called name in session request\n");
+				goto die;
+			}
+			p += k;
+			k = nbnamedecode(p, p, ep, s->from);
+			if (k == 0) {
+				print("nbss: malformed calling name in session request\n");
+				goto die;
+			}
+/*
+			p += k;
+			if (p != ep) {
+				print("nbss: extra data at end of session request\n");
+				goto die;
+			}
+*/
+			called_found = 0;
+//print("nbss: called %B calling %B\n", s->to, s->from);
+			qlock(&listens);
+			for (l = listens.head; l; l = l->next)
+				if (nbnameequal(l->to, s->to)) {
+					called_found = 1;
+					if (nbnameequal(l->from, s->from))
+						break;
+				}
+			if (l == nil) {
+				qunlock(&listens);
+				error_code  = called_found ? 0x81 : 0x80;
+			replydie:
+				buf[0] = 0x83;
+				buf[1] = 0;
+				hnputs(buf + 2, 1);
+				buf[4] = error_code;
+				write(s->fd, buf, 5);
+				goto die;
+			}
+			if (!(*l->accept)(l->magic, s, &s->write)) {
+				qunlock(&listens);
+				error_code = 0x83;
+				goto replydie;
+			}
+			buf[0] = 0x82;
+			buf[1] = 0;
+			hnputs(buf + 2, 0);
+			if (write(s->fd, buf, 4) != 4) {
+				qunlock(&listens);
+				goto die;
+			}
+			s->state = Connected;
+			qunlock(&listens);
+			break;
+		}
+		case 0x85: /* keep awake */
+			break;
+		default:
+			print("nbss: opcode 0x%.2ux unexpected\n", buf[0]);
+			goto die;
+		}
+	}
+}
+
+static NbSession *
+createsession(int fd)
+{
+	Session *s;
+	s = nbemalloc(sizeof(Session));
+	s->fd = fd;
+	s->state = NeedSessionRequest;
+	qlock(&sessions);
+	s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
+	if (s->thread < 0) {
+		qunlock(&sessions);
+		free(s);
+		return nil;
+	}
+	s->next = sessions.head;
+	sessions.head = s;
+	qunlock(&sessions);
+	return s;
+}
+
+static void
+tcplistener(void *)
+{
+	for (;;) {
+		int dfd;
+		char ldir[NETPATHLEN];
+		int lcfd;
+//print("tcplistener: listening\n");
+		lcfd = listen(tcp.adir, ldir);
+//print("tcplistener: contact\n");
+		if (lcfd < 0) {
+		die:
+			qlock(&tcp);
+			close(tcp.acfd);
+			tcp.thread = -1;
+			qunlock(&tcp);
+			return;
+		}
+		dfd = accept(lcfd, ldir);
+		close(lcfd);
+		if (dfd < 0)
+			goto die;
+		if (createsession(dfd) == nil)
+			close(dfd);
+	}
+}
+
+int
+nbsslisten(NbName to, NbName from,int (*accept)(void *magic, NbSession *s, NBSSWRITEFN **writep), void *magic)
+{
+	Listen *l;
+	qlock(&tcp);
+	if (tcp.thread < 0) {
+		fmtinstall('B', nbnamefmt);
+		tcp.acfd = announce("tcp!*!netbios", tcp.adir);
+		if (tcp.acfd < 0) {
+			print("nbsslisten: can't announce: %r\n");
+			qunlock(&tcp);
+			return -1;
+		}
+		tcp.thread = proccreate(tcplistener, nil, 16384);
+	}
+	qunlock(&tcp);
+	l = nbemalloc(sizeof(Listen));
+	nbnamecpy(l->to, to);
+	nbnamecpy(l->from, from);
+	l->accept = accept;
+	l->magic = magic;
+	qlock(&listens);
+	l->next = listens.head;
+	listens.head = l;
+	qunlock(&listens);
+	return 0;
+}
+
+void
+nbssfree(NbSession *s)
+{	
+	deletesession((Session *)s);
+}
+
+int
+nbssgatherwrite(NbSession *s, NbScatterGather *a)
+{
+	uchar hdr[4];
+	NbScatterGather *ap;
+	long l = 0;
+	for (ap = a; ap->p; ap++)
+		l += ap->l;
+//print("nbssgatherwrite %ld bytes\n", l);
+	hnputl(hdr, l);
+//nbdumpdata(hdr, sizeof(hdr));
+	if (write(s->fd, hdr, sizeof(hdr)) != sizeof(hdr))
+		return -1;
+	for (ap = a; ap->p; ap++) {
+//nbdumpdata(ap->p, ap->l);
+		if (write(s->fd, ap->p, ap->l) != ap->l)
+			return -1;
+	}
+	return 0;
+}
+
+NbSession *
+nbssconnect(NbName to, NbName from)
+{
+	Session *s;
+	uchar ipaddr[IPaddrlen];
+	char dialaddress[100];
+	char dir[NETPATHLEN];
+	uchar msg[576];
+	int fd;
+	long o;
+	uchar flags;
+	long length;
+
+	if (!nbnameresolve(to, ipaddr))
+		return nil;
+	fmtinstall('I', eipfmt);
+	snprint(dialaddress, sizeof(dialaddress), "tcp!%I!netbios", ipaddr);
+	fd = dial(dialaddress, nil, dir, nil);
+	if (fd < 0)
+		return nil;
+	msg[0] = 0x81;
+	msg[1] = 0;
+	o = 4;
+	o += nbnameencode(msg + o, msg + sizeof(msg) - o, to);
+	o += nbnameencode(msg + o, msg + sizeof(msg) - o, from);
+	hnputs(msg + 2, o - 4);
+	if (write(fd, msg, o) != o) {
+		close(fd);
+		return nil;
+	}
+	if (readn(fd, msg, 4) != 4) {
+		close(fd);
+		return nil;
+	}
+	flags = msg[1];
+	length = nhgets(msg + 2) | ((flags & 1) << 16);
+	switch (msg[0]) {
+	default:
+		close(fd);
+		werrstr("unexpected session message code 0x%.2ux", msg[0]);
+		return nil;
+	case 0x82:
+		if (length != 0) {
+			close(fd);
+			werrstr("length not 0 in positive session response");
+			return nil;
+		}
+		break;
+	case 0x83:
+		if (length != 1) {
+			close(fd);
+			werrstr("length not 1 in negative session response");
+			return nil;
+		}
+		if (readn(fd, msg + 4, 1) != 1) {
+			close(fd);
+			return nil;
+		}
+		close(fd);
+		werrstr("negative session response 0x%.2ux", msg[4]);
+		return nil;
+	}
+	s = nbemalloc(sizeof(Session));
+	s->fd = fd;
+	s->state = Connected;
+	qlock(&sessions);
+	s->next = sessions.head;
+	sessions.head = s;
+	qunlock(&sessions);
+	return s;
+}
+
+long
+nbssscatterread(NbSession *nbs, NbScatterGather *a)
+{
+	uchar hdr[4];
+	uchar flags;
+	long length, total;
+	NbScatterGather *ap;
+	Session *s = (Session *)nbs;
+
+	long l = 0;
+	for (ap = a; ap->p; ap++)
+		l += ap->l;
+//print("nbssscatterread %ld bytes\n", l);
+again:
+	if (readn(s->fd, hdr, 4) != 4) {
+	dead:
+		s->state = Dead;
+		return -1;
+	}
+	flags = hdr[1];
+	length = nhgets(hdr + 2) | ((flags & 1) << 16);
+//print("%.2ux: %d\n", hdr[0], length);
+	switch (hdr[0]) {
+	case 0x85:
+		if (length != 0) {
+			werrstr("length in keepalive not 0");
+			goto dead;
+		}
+		goto again;
+	case 0x00:
+		break;
+	default:
+		werrstr("unexpected session message code 0x%.2ux", hdr[0]);
+		goto dead;
+	}
+	if (length > l) {
+		werrstr("message too big (%ld)", length);
+		goto dead;
+	}
+	total = length;
+	for (ap = a; length && ap->p; ap++) {
+		long thistime;
+		long n;
+		thistime = length;
+		if (thistime > ap->l)
+			thistime = ap->l;
+//print("reading %d\n", length);
+		n = readn(s->fd, ap->p, thistime);
+		if (n != thistime)
+			goto dead;
+		length -= thistime;
+	}
+	return total;
+}
+
+int
+nbsswrite(NbSession *s, void *buf, long maxlen)
+{
+	NbScatterGather a[2];
+	a[0].l = maxlen;
+	a[0].p = buf;
+	a[1].p = nil;
+	return nbssgatherwrite(s, a);
+}
+
+long
+nbssread(NbSession *s, void *buf, long maxlen)
+{
+	NbScatterGather a[2];
+	a[0].l = maxlen;
+	a[0].p = buf;
+	a[1].p = nil;
+	return nbssscatterread(s, a);
+}

+ 251 - 0
sys/src/cmd/aquarela/netbios.h

@@ -0,0 +1,251 @@
+enum {
+	NbNameLen = 16,	
+	NbnsTimeoutBroadcast = 1000,
+	NbnsRetryBroadcast = 3,
+	NbnsPort = 137,
+	NbDgramMaxLen = 576,
+};
+
+typedef struct NbnsHdr {
+	uchar name_trn_id[2];
+	uchar ctrl[2];
+	uchar qdcount[2];
+	uchar ancount[2];
+	uchar nscount[2];
+	uchar arcount[2];
+} NbnsHdr;
+
+enum {
+	NbnsResponse = 1 << 15
+};
+
+enum {
+	NbnsOpShift = 11,
+	NbnsOpMask = 0xf,
+	NbnsOpQuery = 0,
+	NbnsOpRegistration = 5,
+	NbnsOpRelease = 6,
+	NbnsOpWack = 7,
+	NbnsOpRefresh = 8
+};
+
+enum {
+	NbnsFlagBroadcast = (1 << 4),
+	NbnsFlagRecursionAvailable = (1 << 7),
+	NbnsFlagRecursionDesired = (1 << 8),
+	NbnsFlagTruncation = (1 << 9),
+	NbnsFlagAuthoritativeAnswer = (1 << 10),
+};
+
+enum {
+	NbnsRcodeShift = 0,
+	NbnsRcodeMask = 0xf,
+};
+
+enum {
+	NbnsQuestionTypeNb = 0x0020,
+	NbnsQuestionTypeNbStat = 0x0021,
+	NbnsQuestionClassIn = 0x0001,
+};
+
+enum {
+	NbnsResourceTypeA = 0x0001,
+	NbnsResourceTypeNs = 0x0002,
+	NbnsResourceTypeNull = 0x000a,
+	NbnsResourceTypeNb = 0x0020,
+	NbnsResourceTypeNbStat = 0x0021,
+	NbnsResourceClassIn = 0x0001,
+};
+
+typedef struct NbnsMessageQuestion NbnsMessageQuestion;
+typedef struct NbnsMessageResource NbnsMessageResource;
+
+typedef uchar NbName[NbNameLen];
+int nbnamedecode(uchar *base, uchar *p, uchar *ep, NbName name);
+int nbnameencode(uchar *p, uchar *ep, NbName name);
+int nbnameequal(NbName name1, NbName name2);
+void nbnamecpy(NbName n1, NbName n2);
+void nbmknamefromstring(NbName nbname, char *string);
+void nbmknamefromstringandtype(NbName nbname, char *string, uchar type);
+void nbmkstringfromname(char *buf, int buflen, NbName name);
+#pragma varargck type "B" uchar *
+
+int nbnamefmt(Fmt *);
+
+struct NbnsMessageQuestion {
+	NbName name;
+	ushort type;
+	ushort class;
+	NbnsMessageQuestion *next;
+};
+
+NbnsMessageQuestion *nbnsmessagequestionnew(NbName name, ushort type, ushort class);
+
+struct NbnsMessageResource {
+	NbName name;
+	ushort type;
+	ushort class;
+	ulong ttl;
+	ushort rdlength;
+	uchar *rdata;
+	NbnsMessageResource *next;
+};
+NbnsMessageResource *nbnsmessageresourcenew(NbName name, ushort type, ushort class, ulong ttl, int rdcount, uchar *rdata);
+
+typedef struct NbnsMessage {
+	ushort id;
+	int response;
+	int opcode;
+	int broadcast;
+	int recursionavailable;
+	int recursiondesired;
+	int truncation;
+	int authoritativeanswer;
+	int rcode;
+	NbnsMessageQuestion *q;
+	NbnsMessageResource *an;
+	NbnsMessageResource *ns;
+	NbnsMessageResource *ar;
+} NbnsMessage;
+
+NbnsMessage *nbnsmessagenew(void);
+void nbnsmessageaddquestion(NbnsMessage *s, NbnsMessageQuestion *q);
+void nbnsmessageaddresource(NbnsMessageResource **rp, NbnsMessageResource *r);
+NbnsMessage *nbnsconvM2S(uchar *ap, int nap);
+void nbnsmessagefree(NbnsMessage **sp);
+void nbnsdumpmessage(NbnsMessage *s);
+int nbnsconvS2M(NbnsMessage *s, uchar *ap, int nap);
+
+
+NbnsMessage *nbnsmessagenamequeryrequestnew(ushort id, int broadcast, NbName name);
+NbnsMessage *nbnsmessagenameregistrationrequestnew(ushort id, int broadcast, NbName name, ulong ttl, uchar *ipaddr);
+
+typedef struct NbnsTransaction NbnsTransaction;
+
+struct NbnsTransaction {
+	ushort id;
+	Channel *c;
+	NbnsTransaction *next;
+};
+ushort nbnsnextid(void);
+
+int nbnsfindname(uchar *serveripaddr, NbName name, uchar *ipaddr, ulong *ttlp);
+int nbnsaddname(uchar *serveripaddr, NbName name, ulong ttl, uchar *ipaddr);
+
+NbnsTransaction *nbnstransactionnew(NbnsMessage *request, uchar *ipaddr);
+void nbnstransactionfree(NbnsTransaction **tp);
+
+typedef struct NbnsAlarm NbnsAlarm;
+
+struct NbnsAlarm {
+	Channel *c;
+	vlong expirems;
+	NbnsAlarm *next;
+};
+
+void nbnsalarmset(NbnsAlarm *a, ulong millisec);
+void nbnsalarmcancel(NbnsAlarm *a);
+void nbnsalarmfree(NbnsAlarm **ap);
+NbnsAlarm *nbnsalarmnew(void);
+void nbnsalarmend(void);
+
+typedef struct NbSession NbSession;
+typedef int NBSSWRITEFN(NbSession *s, void *buf, long n);
+
+struct NbSession {
+	int fd;
+	void *magic;
+	NbName from;
+	NbName to;
+};
+
+int nbsslisten(NbName to, NbName from, int (*accept)(void *magic, NbSession *s, NBSSWRITEFN **write), void *magic);
+NbSession *nbssconnect(NbName to, NbName from);
+void nbssfree(NbSession *s);
+
+typedef struct NbScatterGather NbScatterGather;
+
+struct NbScatterGather {
+	void *p;
+	long l;
+};
+
+int nbssgatherwrite(NbSession *s, NbScatterGather *a);
+long nbssscatterread(NbSession *, NbScatterGather *a);
+int nbsswrite(NbSession *s, void *buf, long n);
+long nbssread(NbSession *s, void *buf, long n);
+void *nbemalloc(ulong);
+
+int nbnameresolve(NbName name, uchar *ipaddr);
+
+void nbdumpdata(void *data, long datalen);
+
+typedef struct NbDgram {
+	uchar type;
+	uchar flags;
+	ushort id;
+	uchar srcip[IPaddrlen];
+	ushort srcport;
+	union {
+		struct {
+			ushort length;
+			ushort offset;
+			NbName srcname;
+			NbName dstname;
+			uchar *data;
+		} datagram;
+		struct {
+			uchar code;
+		} error;
+		struct {
+			NbName dstname;
+		} query;
+	};
+} NbDgram;
+
+enum {
+	NbDgramDirectUnique = 0x10,
+	NbDgramDirectGroup,
+	NbDgramBroadcast,
+	NbDgramError,
+	NbDgramQueryRequest,
+	NbDgramPositiveQueryResponse,
+	NbDgramNegativeQueryResponse,
+	NbDgramMore = 1,
+	NbDgramFirst = 2,
+	NbDgramPort = 138,
+	NbDgramErrorDestinationNameNotPresent = 0x82,
+	NbDgramMaxPacket = 576,
+};
+
+typedef struct NbDgramSendParameters {
+	NbName to;
+	uchar type;
+} NbDgramSendParameters;
+
+int nbdgramconvM2S(NbDgram *s, uchar *p, uchar *ep);
+int nbdgramconvS2M(uchar *p, uchar *ep, NbDgram *s);
+void nbdgramdump(NbDgram *s);
+int nbdgramsendto(uchar *ipaddr, ushort port, NbDgram *s);
+int nbdgramsend(NbDgramSendParameters *p, unsigned char *data, long datalen);
+char *nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic);
+
+int nbnametablefind(NbName name, int add);
+int nbnameisany(NbName name);
+
+int nbremotenametablefind(NbName name, uchar *ipaddr);
+int nbremotenametableadd(NbName name, uchar *ipaddr, ulong ttl);
+
+typedef struct NbGlobals {
+	uchar myipaddr[IPaddrlen];
+	uchar bcastaddr[IPaddrlen];
+	NbName myname;
+} NbGlobals;
+
+extern NbGlobals nbglobals;
+extern NbName nbnameany;
+
+int nbinit(void);
+char *nbudpannounce(ushort port, int *fdp);
+
+extern int nbudphdrsize;

+ 387 - 0
sys/src/cmd/aquarela/smb.h

@@ -0,0 +1,387 @@
+typedef struct SmbRawHeader {
+	uchar protocol[4];
+	uchar command;
+//	union {
+//		struct {
+//			uchar errorclass;
+//			uchar reserved;
+//			uchar error[2];
+//		} doserror;
+		uchar status[4];
+//	};
+	uchar flags;
+	uchar flags2[2];
+//	union {
+		uchar extra[12];
+//		struct {
+//			uchar pidhigh[2];
+//			uchar securitysignature[8];
+//		};
+//	};
+	uchar tid[2];
+	uchar pid[2];
+	uchar uid[2];
+	uchar mid[2];
+	uchar wordcount;
+	uchar parameterwords[1];
+} SmbRawHeader;
+
+enum {
+	SmbHeaderFlagReserved = (3 << 1),
+	SmbHeaderFlagCaseless = (1 << 3),
+	SmbHeaderFlagServerIgnore = (1 << 4),
+	SMB_FLAGS_SERVER_TO_REDIR = (1 << 7),
+};
+
+enum {
+	SMB_FLAGS2_KNOWS_LONG_NAMES = (1 << 0),
+	SMB_FLAGS2_KNOWS_EAS = (1 << 1),
+	SMB_FLAGS2_SECURITY_SIGNATURE = (1 << 2),
+	SMB_FLAGS2_RESERVED1 = (1 << 3),
+	SMB_FLAGS2_IS_LONG_NAME = (1 << 6),
+	SMB_FLAGS2_EXT_SEC = (1 << 1),
+	SMB_FLAGS2_DFS = (1 << 12),
+	SMB_FLAGS2_PAGING_IO = (1 << 13),
+	SMB_FLAGS2_ERR_STATUS = (1 << 14),
+	SMB_FLAGS2_UNICODE = (1 << 15),
+};
+
+enum {
+	SMB_COM_CREATE_DIRECTORY = 0x00,
+	SMB_COM_DELETE_DIRECTORY = 0x01,
+	SMB_COM_OPEN = 0x02,
+	SMB_COM_CREATE = 0x03,
+	SMB_COM_CLOSE = 0x04,
+	SMB_COM_FLUSH = 0x05,
+	SMB_COM_DELETE = 0x06,
+	SMB_COM_RENAME = 0x07,
+	SMB_COM_QUERY_INFORMATION = 0x08,
+	SMB_COM_SET_INFORMATION = 0x09,
+	SMB_COM_READ = 0x0A,
+	SMB_COM_WRITE = 0x0B,
+	SMB_COM_LOCK_BYTE_RANGE = 0x0C,
+	SMB_COM_UNLOCK_BYTE_RANGE = 0x0D,
+	SMB_COM_CREATE_TEMPORARY = 0x0E,
+	SMB_COM_CREATE_NEW = 0x0F,
+	SMB_COM_CHECK_DIRECTORY = 0x10,
+	SMB_COM_PROCESS_EXIT = 0x11,
+	SMB_COM_SEEK = 0x12,
+	SMB_COM_LOCK_AND_READ = 0x13,
+	SMB_COM_WRITE_AND_UNLOCK = 0x14,
+	SMB_COM_READ_RAW = 0x1A,
+	SMB_COM_READ_MPX = 0x1B,
+	SMB_COM_READ_MPX_SECONDARY = 0x1C,
+	SMB_COM_WRITE_RAW = 0x1D,
+	SMB_COM_WRITE_MPX = 0x1E,
+	SMB_COM_WRITE_MPX_SECONDARY = 0x1F,
+	SMB_COM_WRITE_COMPLETE = 0x20,
+	SMB_COM_QUERY_SERVER = 0x21,
+	SMB_COM_SET_INFORMATION2 = 0x22,
+	SMB_COM_QUERY_INFORMATION2 = 0x23,
+	SMB_COM_LOCKING_ANDX = 0x24,
+	SMB_COM_TRANSACTION = 0x25,
+	SMB_COM_TRANSACTION_SECONDARY = 0x26,
+	SMB_COM_IOCTL = 0x27,
+	SMB_COM_IOCTL_SECONDARY = 0x28,
+	SMB_COM_COPY = 0x29,
+	SMB_COM_MOVE = 0x2A,
+	SMB_COM_ECHO = 0x2B,
+	SMB_COM_WRITE_AND_CLOSE = 0x2C,
+	SMB_COM_OPEN_ANDX = 0x2D,
+	SMB_COM_READ_ANDX = 0x2E,
+	SMB_COM_WRITE_ANDX = 0x2F,
+	SMB_COM_NEW_FILE_SIZE = 0x30,
+	SMB_COM_CLOSE_AND_TREE_DISC = 0x31,
+	SMB_COM_TRANSACTION2 = 0x32,
+	SMB_COM_TRANSACTION2_SECONDARY = 0x33,
+	SMB_COM_FIND_CLOSE2 = 0x34,
+	SMB_COM_FIND_NOTIFY_CLOSE = 0x35,
+/* Used by Xenix/Unix 0x60 - 0x6E */,
+	SMB_COM_TREE_CONNECT = 0x70,
+	SMB_COM_TREE_DISCONNECT = 0x71,
+	SMB_COM_NEGOTIATE = 0x72,
+	SMB_COM_SESSION_SETUP_ANDX = 0x73,
+	SMB_COM_LOGOFF_ANDX = 0x74,
+	SMB_COM_TREE_CONNECT_ANDX = 0x75,
+	SMB_COM_QUERY_INFORMATION_DISK = 0x80,
+	SMB_COM_SEARCH = 0x81,
+	SMB_COM_FIND = 0x82,
+	SMB_COM_FIND_UNIQUE = 0x83,
+	SMB_COM_FIND_CLOSE = 0x84,
+	SMB_COM_NT_TRANSACT = 0xA0,
+	SMB_COM_NT_TRANSACT_SECONDARY = 0xA1,
+	SMB_COM_NT_CREATE_ANDX = 0xA2,
+	SMB_COM_NT_CANCEL = 0xA4,
+	SMB_COM_NT_RENAME = 0xA5,
+	SMB_COM_OPEN_PRINT_FILE = 0xC0,
+	SMB_COM_WRITE_PRINT_FILE = 0xC1,
+	SMB_COM_CLOSE_PRINT_FILE = 0xC2,
+	SMB_COM_GET_PRINT_QUEUE = 0xC3,
+	SMB_COM_READ_BULK = 0xD8,
+	SMB_COM_WRITE_BULK = 0xD9,
+	SMB_COM_NO_ANDX_COMMAND = 0xff,
+};
+
+enum {
+	SUCCESS = 0,
+	ERRDOS = 0x01,
+	ERRSRV = 0x02,
+	ERRHRD = 0x03,
+	ERRCMD = 0xff,
+};
+
+enum {
+	ERRbadfunc = 1,
+	ERRbadfile = 2,
+	ERRbadpath = 3,
+	ERRnofids = 4,
+	ERRnoaccess = 5,
+	ERRbadfid = 6,
+	ERRbadmcb = 7,
+	ERRnomem = 8,
+	ERRbadmem = 9,
+	ERRbadenv = 10,
+	ERRbadformat = 11,
+	ERRbadaccess = 12,
+	ERRbaddata  =13,
+	ERRbaddrive = 15,
+	ERRremcd = 16,
+	ERRdiffdevice = 17,
+	ERRnofiles = 18,
+	ERRbadshare = 32,
+	ERRlock = 33,
+	ERRunsup = 50,
+	ERRfilexists = 80,
+	ERRunknownlevel = 124,
+	ERRquota = 512,
+	ERRnotalink = 513,
+};
+
+enum {
+	ERRerror = 1,
+	ERRbadpw = 2,
+	ERRaccess = 4,
+	ERRinvtid = 5,
+	ERRsmbcmd = 64,
+	ERRtoomanyuids = 90,
+	ERRbaduid = 91,
+	ERRnosupport = 65535,
+};
+
+enum {
+	CAP_RAW_MODE = 0x0001,
+	CAP_MPX_MODE = 0x0002,
+	CAP_UNICODE = 0x0004,
+	CAP_LARGE_FILES =  0x0008,
+	CAP_NT_SMBS = 0x0010,
+	CAP_RPC_REMOTE_APIS = 0x0020,
+	CAP_STATUS32 = 0x0040,
+	CAP_LEVEL_II_OPLOCKS = 0x0080,
+	CAP_LOCK_AND_READ = 0x0100,
+	CAP_NT_FIND = 0x0200,
+	CAP_DFS = 0x1000,
+	CAP_INFOLEVEL_PASSTHRU = 0x2000,
+	CAP_W2K_SMBS = 0x2000,
+	CAP_LARGE_READX = 0x4000,
+	CAP_LARGE_WRITEX = 0x8000,
+	CAP_UNIX = 0x00800000,
+	CAP_BULK_TRANSFER = 0x20000000,
+	CAP_COMPRESSED_DATA = 0x40000000,
+	CAP_EXTENDED_SECURITY = 0x80000000
+};
+
+enum {
+	RapNetShareEnum = 0,
+	RapNetShareGetInfo = 1,
+	RapNetServerGetInfo = 13,
+	RapNetWkstaGetInfo = 63,
+	RapNetServerEnum2 = 104,
+};
+
+enum {
+	SMB_RAP_NERR_SUCCESS = 0,
+	SMB_RAP_ERROR_MORE_DATA = 234,
+};
+
+enum {
+	STYPE_DISKTREE,
+	STYPE_PRINTQ,
+	STYPE_DEVICE,
+	STYPE_IPC
+};
+
+enum {
+	SV_TYPE_WORKSTATION = 0x00000001,
+	SV_TYPE_SERVER = 0x00000002,
+	SV_TYPE_SQLSERVER = 0x00000004,
+	SV_TYPE_DOMAIN_CTRL = 0x00000008,
+	SV_TYPE_DOMAIN_BAKCTRL = 0x00000010,
+	SV_TYPE_TIME_SOURCE = 0x00000020,
+	SV_TYPE_AFP = 0x00000040,
+	SV_TYPE_NOVELL = 0x00000080,
+	SV_TYPE_DOMAIN_MEMBER = 0x00000100,
+	SV_TYPE_PRINTQ_SERVER = 0x00000200,
+	SV_TYPE_DIALIN_SERVER = 0x00000400,
+	SV_TYPE_SERVER_UNIX = 0x00000800,
+	SV_TYPE_NT = 0x00001000,
+	SV_TYPE_WFW = 0x00002000,
+	SV_TYPE_SERVER_MFPN = 0x00004000,
+	SV_TYPE_SERVER_NT = 0x00008000,
+	SV_TYPE_POTENTIAL_BROWSER = 0x00010000,
+	SV_TYPE_BACKUP_BROWSER = 0x00020000,
+	SV_TYPE_MASTER_BROWSER = 0x00040000,
+	SV_TYPE_DOMAIN_MASTER = 0x00080000,
+	SV_TYPE_SERVER_OSF = 0x00100000,
+	SV_TYPE_SERVER_VMS = 0x00200000,
+	SV_TYPE_WIN95_PLUS = 0x00400000,
+	SV_TYPE_DFS_SERVER = 0x00800000,
+	SV_TYPE_ALTERNATE_XPORT = 0x20000000,
+	SV_TYPE_LOCAL_LIST_ONLY = 0x40000000,
+	SV_TYPE_DOMAIN_ENUM = 0x80000000,
+	SV_TYPE_ALL = 0xFFFFFFFF,
+};
+
+enum {
+	SMB_TRANS2_OPEN = 0,
+	SMB_TRANS2_FIND_FIRST2 = 1,
+	SMB_TRANS2_FIND_NEXT2 = 2,
+	SMB_TRANS2_QUERY_FS_INFORMATION = 3,
+	SMB_TRANS2_SET_FS_INFORMATION = 4,
+	SMB_TRANS2_QUERY_PATH_INFORMATION = 5,
+	SMB_TRANS2_SET_PATH_INFORMATION = 6,
+	SMB_TRANS2_QUERY_FILE_INFORMATION = 7,
+	SMB_TRANS2_SET_FILE_INFORMATION = 8,
+	SMB_TRANS2_FSCTL = 9,
+	SMB_TRANS2_IOCTL2 = 0xA,
+	SMB_TRANS2_FIND_NOTIFY_FIRST = 0xB,
+	SMB_TRANS2_FIND_NOTIFY_NEXT = 0xC,
+	SMB_TRANS2_CREATE_DIRECTORY = 0xD,
+	SMB_TRANS2_SESSION_SETUP = 0xE,
+	SMB_TRANS2_GET_DFS_REFERRAL = 0x10,
+	SMB_TRANS2_REPORT_DFS_INCONSISTENCY = 0x11,
+};
+
+enum {
+	SMB_FIND_CLOSE = 1,
+	SMB_FIND_CLOSE_EOS = 2,
+	SMB_FIND_RETURN_RESUME_KEYS = 4,
+	SMB_FIND_CONTINUE = 8,
+	SMB_FIND_BACKUP = 16
+};
+
+enum {
+	SMB_INFO_STANDARD = 1,
+	SMB_FIND_FILE_BOTH_DIRECTORY_INFO = 0x104,
+	SMB_QUERY_FILE_BASIC_INFO = 0x101,
+	SMB_QUERY_FILE_STANDARD_INFO = 0x102,
+	SMB_QUERY_FILE_EA_INFO = 0x103,
+	SMB_QUERY_FILE_ALL_INFO = 0x107,
+	SMB_QUERY_FILE_STREAM_INFO = 0x109,
+};
+
+enum {
+	SMB_SET_FILE_BASIC_INFO = 0x101,
+	SMB_SET_FILE_DISPOSITION_INFO = 0x102,
+	SMB_SET_FILE_ALLOCATION_INFO = 0x103,
+	SMB_SET_FILE_END_OF_FILE_INFO = 0x104,
+};
+
+enum {
+	SMB_ATTR_READ_ONLY = (1 << 0),
+	SMB_ATTR_HIDDEN = (1 << 1),
+	SMB_ATTR_SYSTEM = (1 << 2),
+	SMB_ATTR_DIRECTORY = (1 << 4),
+	SMB_ATTR_ARCHIVE = (1 << 5),
+	SMB_ATTR_NORMAL = (1 << 7),
+	SMB_ATTR_COMPRESSED = 0x800,
+	SMB_ATTR_TEMPORARY = 0x100,
+	SMB_ATTR_WRITETHROUGH = 0x80000000,
+	SMB_ATTR_NO_BUFFERING = 0x20000000,
+	SMB_ATTR_RANDOM_ACCESS = 0x10000000,
+};
+
+enum {
+	SMB_OFUN_EXIST_SHIFT = 0,
+	SMB_OFUN_EXIST_MASK = 3,
+	SMB_OFUN_EXIST_FAIL = 0,
+	SMB_OFUN_EXIST_OPEN = 1,
+	SMB_OFUN_EXIST_TRUNCATE = 2,
+	SMB_OFUN_NOEXIST_CREATE = (1 << 4),
+};
+
+enum {
+	SMB_OPEN_FLAGS_ADDITIONAL = 1,
+	SMB_OPEN_FLAGS_OPLOCK = 2,
+	SMB_OPEN_FLAGS_OPBATCH = 4,
+	SMB_OPEN_MODE_ACCESS_SHIFT = 0,
+	SMB_OPEN_MODE_ACCESS_MASK = 7,
+	SMB_OPEN_MODE_SHARE_SHIFT = 4,
+	SMB_OPEN_MODE_SHARE_MASK = 7,
+	SMB_OPEN_MODE_SHARE_COMPATIBILITY  = 0,
+	SMB_OPEN_MODE_SHARE_EXCLUSIVE = 1,
+	SMB_OPEN_MODE_SHARE_DENY_WRITE = 2,
+	SMB_OPEN_MODE_SHARE_DENY_READOREXEC = 3,
+	SMB_OPEN_MODE_SHARE_DENY_NONE = 4,
+	SMB_OPEN_MODE_WRITE_THROUGH = (1 << 14),
+};
+
+enum {
+	SMB_INFO_ALLOCATION = 1,
+	SMB_INFO_VOLUME = 2,
+	SMB_QUERY_FS_VOLUME_INFO = 0x102,
+	SMB_QUERY_FS_SIZE_INFO = 0x103,
+	SMB_QUERY_FS_ATTRIBUTE_INFO = 0x105,
+};
+
+enum {
+	SMB_CD_SUPERCEDE = 0,
+	SMB_CD_OPEN = 1,
+	SMB_CD_CREATE = 2,
+	SMB_CD_OPEN_IF = 3,
+	SMB_CD_OVERWRITE = 4,
+	SMB_CD_OVERWRITE_IF = 5,
+	SMB_CD_MAX = 5,
+};
+
+enum {
+	SMB_DA_SPECIFIC_MASK = 0x0000ffff,
+	SMB_DA_SPECIFIC_READ_DATA = 0x00000001,
+	SMB_DA_SPECIFIC_WRITE_DATA = 0x00000002,
+	SMB_DA_SPECIFIC_APPEND_DATA = 0x00000004,
+	SMB_DA_SPECIFIC_READ_EA = 0x00000008,
+	SMB_DA_SPECIFIC_WRITE_EA = 0x00000010,
+	SMB_DA_SPECIFIC_EXECUTE = 0x00000020,
+	SMB_DA_SPECIFIC_DELETE_CHILD = 0x00000040,
+	SMB_DA_SPECIFIC_READ_ATTRIBUTES = 0x00000080,
+	SMB_DA_SPECIFIC_WRITE_ATTRIBUTES = 0x00000100,
+	SMB_DA_STANDARD_MASK = 0x00ff0000,
+	SMB_DA_STANDARD_DELETE_ACCESS = 0x00010000,
+	SMB_DA_STANDARD_READ_CONTROL_ACCESS = 0x00020000,
+	SMB_DA_STANDARD_WRITE_DAC_ACCESS = 0x00040000,
+	SMB_DA_STANDARD_WRITE_OWNER_ACCESS = 0x00080000,
+	SMB_DA_STANDARD_SYNCHRONIZE_ACCESS = 0x00100000,
+	SMB_DA_GENERIC_MASK = 0xf0000000,
+	SMB_DA_GENERIC_ALL_ACCESS = 0x10000000,
+	SMB_DA_GENERIC_EXECUTE_ACCESS = 0x20000000,
+	SMB_DA_GENERIC_WRITE_ACCESS = 0x40000000,
+	SMB_DA_GENERIC_READ_ACCESS = 0x80000000
+};
+
+enum {
+	SMB_SA_NO_SHARE = 0x00000000,
+	SMB_SA_SHARE_READ = 0x00000001,
+	SMB_SA_SHARE_WRITE = 0x00000002,
+	SMB_SA_SHARE_DELETE = 0x00000004,
+};
+
+enum {
+	SMB_CO_DIRECTORY = 0x00000001,
+	SMB_CO_WRITETHROUGH = 0x00000002,
+	SMB_CO_SEQUENTIAL_ONLY = 0x00000004,
+	SMB_CO_FILE = 0x00000040,
+	SMB_CO_NO_EA_KNOWLEDGE = 0x00000200,
+	SMB_CO_EIGHT_DOT_THREE_ONLY = 0x00000400,
+	SMB_CO_RANDOM_ACCESS = 0x00000800,
+	SMB_CO_DELETE_ON_CLOSE = 0x00001000,
+};
+

+ 43 - 0
sys/src/cmd/aquarela/smballoc.c

@@ -0,0 +1,43 @@
+#include "headers.h"
+
+#ifndef LEAK
+void *
+smbemallocz(ulong size, int clear)
+{
+	void *p = nbemalloc(size);
+	if (clear && p)
+		memset(p, 0, size);
+	return p;
+}
+
+void *
+smbemalloc(ulong size)
+{
+	return smbemallocz(size, 0);
+}
+
+char *
+smbestrdup(char *p)
+{
+	char *q;
+	q = smbemalloc(strlen(p) + 1);
+	return strcpy(q, p);
+}
+#endif
+
+void
+smbfree(void **pp)
+{
+	void *p = *pp;
+	if (p) {
+		free(p);
+		*pp = nil;
+	}
+}
+
+void
+smberealloc(void **pp, ulong size)
+{
+	*pp = realloc(*pp, size);
+	assert(size == 0 || *pp);
+}

+ 56 - 0
sys/src/cmd/aquarela/smbbrowse.c

@@ -0,0 +1,56 @@
+#include "headers.h"
+
+int
+smbmailslotsend(NbDgramSendParameters *p, SmbBuffer *msg, char **errmsgp)
+{
+	ushort setup[3];
+	int rv;
+	SmbTransaction transaction;
+	SmbBuffer *b;
+	SmbHeader h;
+	setup[0] = 1;
+	setup[1] = 0;
+	setup[2] = 0;
+	memset(&transaction, 0, sizeof(transaction));
+	transaction.in.name = smbglobals.mailslotbrowse;
+	transaction.in.scount = 3;
+	transaction.in.setup = setup;
+	transaction.in.tdcount = smbbufferreadspace(msg);
+	transaction.in.data = smbbufferreadpointer(msg);
+	b = smbbuffernew(NbDgramMaxLen);
+	memset(&h, 0, sizeof(h));
+	rv = smbtransactionexecute(&transaction, &h, nil, b, &smbtransactionmethoddgram, p, nil, errmsgp);
+	smbbufferfree(&b);
+	return rv;
+}
+
+int
+smbbrowsesendhostannouncement(char *name, ulong periodms, ulong type, char *comment, char **errmsgp)
+{
+	NbDgramSendParameters p;
+	SmbBuffer *b;
+	int rv;
+//	NbName msbrowse;
+
+//	msbrowse[0] = 1;
+//	msbrowse[1] = 2;
+//	memcpy(msbrowse + 2, "__MSBROWSE__", 12);
+//	msbrowse[14] = 2;
+//	msbrowse[15] = 1;
+//	nbnamecpy(p.to, msbrowse);
+	nbmknamefromstringandtype(p.to, smbglobals.primarydomain, 0x1d);
+	p.type = NbDgramDirectUnique;
+	b = smbbuffernew(NbDgramMaxLen);
+	smbbufferputb(b, 1);
+	smbbufferputb(b, 0);
+	smbbufferputl(b, periodms);
+	smbbufferputstrn(b, name, 16, 1);
+	smbbufferputb(b, 4);
+	smbbufferputb(b, 0);
+	smbbufferputl(b, type);
+	smbbufferputl(b, 0xaa55011f);
+	smbbufferputstring(b, nil, 0, comment);
+	rv = smbmailslotsend(&p, b, errmsgp);
+	smbbufferfree(&b);
+	return rv;
+}

+ 579 - 0
sys/src/cmd/aquarela/smbbuffer.c

@@ -0,0 +1,579 @@
+#include "headers.h"
+
+#define BUFFER 1
+#define STRUCT 2
+#define PUSHED 4
+
+struct SmbBuffer {
+	uchar *buf;
+	ulong realmaxlen;
+	ulong maxlen;
+	ulong rn;
+	ulong wn;
+	ulong savewn;
+	int flags;
+};
+
+void
+smbbufferreset(SmbBuffer *s)
+{
+	if (s == nil)
+		return;
+	s->rn = 0;
+	s->wn = 0;
+	s->flags &= ~PUSHED;
+}
+
+void
+smbbuffersetbuf(SmbBuffer *s, void *p, ulong maxlen)
+{
+	s->realmaxlen = s->maxlen = maxlen;
+	if (s->buf) {
+		if (s->flags & BUFFER)
+			free(s->buf);
+		s->buf = nil;
+	}
+	s->flags &= ~BUFFER;
+	if (p)
+		s->buf = p;
+	else {
+		s->buf = smbemalloc(maxlen);
+		s->flags |= BUFFER;
+	}
+	smbbufferreset(s);
+}
+
+SmbBuffer *
+smbbufferinit(void *base, void *bdata, ulong blen)
+{
+	SmbBuffer *b;
+	b = smbemalloc(sizeof(*b));
+	b->buf = base;
+	b->flags = STRUCT;	
+	b->rn = (uchar *)bdata - (uchar *)base;
+	b->wn = b->rn + blen;
+	b->realmaxlen = b->maxlen = b->wn;
+	return b;
+}
+
+int
+smbbufferalignl2(SmbBuffer *s, int al2)
+{
+	ulong mask, newn;
+	mask = (1 << al2) - 1;
+	newn = (s->wn + mask) & ~mask;
+	if (newn != s->wn) {
+		if (newn > s->maxlen)
+			return 0;
+		s->wn = newn;
+	}
+	return 1;
+}
+
+int
+smbbufferputb(SmbBuffer *s, uchar b)
+{
+	if (s->wn >= s->maxlen)
+		return 0;
+	s->buf[s->wn++] = b;
+	return 1;
+}
+
+ulong
+smbbufferspace(SmbBuffer *sess)
+{
+	return sess->maxlen - sess->wn;
+}
+
+int
+smbbufferoffsetputs(SmbBuffer *sess, ulong offset, ushort s)
+{
+	if (offset + 2 > sess->wn)
+		return 0;
+	smbhnputs(sess->buf + offset, s);
+	return 1;
+}
+
+int
+smbbufferputs(SmbBuffer *sess, ushort s)
+{
+	if (sess->wn + sizeof(ushort) > sess->maxlen)
+		return 0;
+	smbhnputs(sess->buf + sess->wn, s);
+	sess->wn += sizeof(ushort);
+	return 1;
+}
+
+int
+smbbufferputl(SmbBuffer *s, ulong l)
+{
+	if (s->wn + sizeof(ulong) > s->maxlen)
+		return 0;
+	smbhnputl(s->buf + s->wn, l);
+	s->wn += sizeof(ulong);
+	return 1;
+}
+
+int
+smbbufferputv(SmbBuffer *s, vlong v)
+{
+	if (s->wn + sizeof(vlong) > s->maxlen)
+		return 0;
+	smbhnputv(s->buf + s->wn, v);
+	s->wn += sizeof(vlong);
+	return 1;
+}
+
+int
+smbbufferputbytes(SmbBuffer *s, void *data, ulong datalen)
+{
+	if (s->wn + datalen > s->maxlen)
+		return 0;
+	if (data)
+		memcpy(s->buf + s->wn, data, datalen);
+	s->wn += datalen;
+	return 1;
+}
+
+int
+smbbufferputstring(SmbBuffer *b, SmbPeerInfo *p, ulong flags, char *string)
+{
+	int n = smbstringput(p, flags, b->buf, b->wn, b->maxlen, string);
+	if (n <= 0)
+		return 0;
+	b->wn += n;
+	return 1;
+}
+
+int
+smbbufferputstrn(SmbBuffer *s, char *string, int size, int upcase)
+{
+	int n = smbstrnput(s->buf, s->wn, s->maxlen, string, size, upcase);
+	if (n <= 0)
+		return 0;
+	s->wn += n;
+	return 1;
+}
+
+ulong
+smbbufferwriteoffset(SmbBuffer *s)
+{
+	return s->wn;
+}
+
+ulong
+smbbufferwritemaxoffset(SmbBuffer *s)
+{
+	return s->maxlen;
+}
+
+ulong
+smbbufferreadoffset(SmbBuffer *s)
+{
+	return s->rn;
+}
+
+void *
+smbbufferreadpointer(SmbBuffer *s)
+{
+	return s->buf + s->rn;
+}
+
+void *
+smbbufferwritepointer(SmbBuffer *s)
+{
+	return s->buf + s->wn;
+}
+
+ulong
+smbbufferwritespace(SmbBuffer *b)
+{
+	return b->maxlen - b->wn;
+}
+
+SmbBuffer *
+smbbuffernew(ulong maxlen)
+{
+	SmbBuffer *b;
+	b = smbemalloc(sizeof(SmbBuffer));
+	b->buf = smbemalloc(maxlen);
+	b->realmaxlen = b->maxlen = maxlen;
+	b->rn = 0;
+	b->wn = 0;
+	b->flags = STRUCT | BUFFER;
+	return b;
+}
+
+void
+smbbufferfree(SmbBuffer **bp)
+{
+	SmbBuffer *b = *bp;
+	if (b) {
+		if (b->flags & BUFFER) {
+			free(b->buf);
+			b->buf = nil;
+			b->flags &= ~BUFFER;
+		}
+		if (b->flags & STRUCT)
+			free(b);
+		*bp = nil;
+	}
+}
+
+uchar *
+smbbufferbase(SmbBuffer *b)
+{
+	return b->buf;
+}
+
+int
+smbbuffergetbytes(SmbBuffer *b, void *buf, ulong len)
+{
+	if (b->rn + len > b->wn)
+		return 0;
+	if (buf)
+		memcpy(buf, b->buf + b->rn, len);
+	b->rn += len;
+	return 1;
+}
+
+void
+smbbuffersetreadlen(SmbBuffer *b, ulong len)
+{
+	b->wn = b->rn + len;
+}
+
+int
+smbbuffertrimreadlen(SmbBuffer *b, ulong len)
+{
+	if (b->rn + len > b->wn)
+		return 0;
+	else if (b->rn + len < b->wn)
+		b->wn = b->rn + len;
+	return 1;
+}
+
+int
+smbbuffergets(SmbBuffer *b, ushort *sp)
+{
+	if (b->rn + 2 > b->wn)
+		return 0;
+	*sp = smbnhgets(b->buf + b->rn);
+	b->rn += 2;
+	return 1;
+}
+
+int
+smbbuffergetstrn(SmbBuffer *b, ushort size, char **sp)
+{
+	uchar *np;
+	if (size > b->wn - b->rn)
+		return 0;
+	np = memchr(b->buf + b->rn, 0, size);
+	if (np == nil)
+		return 0;
+	*sp = strdup((char *)b->buf + b->rn);
+	b->rn += size;
+	return 1;
+}
+
+int
+smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp)
+{
+	uchar *np;
+	USED(flags);
+	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
+	if (np == nil)
+		return 0;
+	*sp = strdup((char *)b->buf + b->rn);
+	b->rn = np - b->buf + 1;
+	return 1;
+}
+
+int
+smbbuffergetstrinline(SmbBuffer *b, char **sp)
+{
+	uchar *np;
+	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
+	if (np == nil)
+		return 0;
+	*sp = (char *)b->buf + b->rn;
+	b->rn = np - b->buf + 1;
+	return 1;
+}
+
+int
+smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp)
+{
+	uchar *bdata = b->buf + b->rn;
+	uchar *edata = b->buf + b->wn;
+	Rune r;
+	int l;
+	char *p, *q;
+	uchar *savebdata;
+	int first;
+
+	l = 0;
+	if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1)
+		bdata++;
+	savebdata = bdata;
+	first = 1;
+	do {
+		if (bdata + 2 > edata) {
+			l++;
+			break;
+		}
+		r = smbnhgets(bdata); bdata += 2;
+		if (first && (flags & SMB_STRING_PATH) && r != '\\')
+			l++;
+		first = 0;
+		if (flags & SMB_STRING_CONVERT_MASK)
+			r = smbruneconvert(r, flags);
+		l += runelen(r);
+	} while (r != 0);
+	p = smbemalloc(l);
+	bdata = savebdata;
+	q = p;
+	first = 1;
+	do {
+		if (bdata + 2 > edata) {
+			*q = 0;
+			break;
+		}
+		r = smbnhgets(bdata); bdata += 2;
+		if (first && (flags & SMB_STRING_PATH) && r != '\\')
+			*q++ = '/';
+		first = 0;
+		if (flags & SMB_STRING_CONVERT_MASK)
+			r = smbruneconvert(r, flags);
+		q += runetochar(q, &r);
+	} while (r != 0);
+	b->rn = bdata - b->buf;
+	*sp = p;
+	return 1;
+}
+
+int
+smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp)
+{
+	if (flags & SMB_STRING_UNICODE)
+		return smbbuffergetucs2(b, flags, sp);
+	else if (flags & SMB_STRING_ASCII)
+		return smbbuffergetstr(b, flags, sp);
+	else if (h->flags2 & SMB_FLAGS2_UNICODE)
+		return smbbuffergetucs2(b, flags, sp);
+	else
+		return smbbuffergetstr(b, flags, sp);
+}
+
+void *
+smbbufferpointer(SmbBuffer *b, ulong offset)
+{
+	return b->buf + offset;
+}
+
+int
+smbbuffergetb(SmbBuffer *b, uchar *bp)
+{
+	if (b->rn < b->wn) {
+		*bp = b->buf[b->rn++];
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbuffergetl(SmbBuffer *b, ulong *lp)
+{
+	if (b->rn + 4 <= b->wn) {
+		*lp = smbnhgetl(b->buf + b->rn);
+		b->rn += 4;
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbuffergetv(SmbBuffer *b, vlong *vp)
+{
+	if (b->rn + 8 <= b->wn) {
+		*vp = smbnhgetv(b->buf + b->rn);
+		b->rn += 8;
+		return 1;
+	}
+}
+
+ulong
+smbbufferreadspace(SmbBuffer *b)
+{
+	return b->wn - b->rn;
+}
+
+void
+smbbufferwritelimit(SmbBuffer *b, ulong limit)
+{
+	if (b->rn + limit < b->maxlen)
+		b->maxlen = b->rn + limit;
+}
+
+int
+smbbufferreadskipto(SmbBuffer *b, ulong offset)
+{
+	if (offset < b->rn || offset >= b->wn)
+		return 0;
+	b->rn = offset;
+	return 1;
+}
+
+int
+smbbufferpushreadlimit(SmbBuffer *b, ulong limit)
+{
+	if (b->flags & PUSHED)
+		return 0;
+	if (limit > b->wn || limit < b->rn)
+		return 0;
+	b->savewn = b->wn;
+	b->wn = limit;
+	b->flags |= PUSHED;
+	return 1;
+}
+
+int
+smbbufferpopreadlimit(SmbBuffer *b)
+{
+	if ((b->flags & PUSHED) == 0)
+		return 0;
+	b->wn = b->savewn;
+	b->flags &= ~PUSHED;
+	return 1;
+}
+
+int
+smbbufferwritebackup(SmbBuffer *b, ulong offset)
+{
+	if (offset >= b->rn && offset <= b->wn) {
+		b->wn = offset;
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbufferreadbackup(SmbBuffer *b, ulong offset)
+{
+	if (offset <= b->rn) {
+		b->rn = offset;
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset)
+{
+	ulong fixval;
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
+		return 0;
+	fixval = b->wn - fixupoffset - 2;
+	if (fixval > 65535)
+		return 0;
+	smbhnputs(b->buf + fixupoffset, fixval);
+	return 1;
+}
+
+int
+smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset)
+{
+	ulong fixval;
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
+		return 0;
+	fixval = b->wn - fixupoffset - 4;
+	smbhnputl(b->buf + fixupoffset, fixval);
+	return 1;
+}
+
+int
+smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset)
+{
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
+		return 0;
+	if (b->wn > 65535)
+		return 0;
+	smbhnputs(b->buf + fixupoffset, b->wn);
+	return 1;
+}
+
+int
+smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval)
+{
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
+		return 0;
+	smbhnputl(b->buf + fixupoffset, fixupval);
+	return 1;
+}
+
+int
+smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset)
+{
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
+		return 0;
+	smbhnputl(b->buf + fixupoffset, b->wn);
+	return 1;
+}
+
+int
+smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset)
+{
+	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
+		return 0;
+	smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset);
+	return 1;
+}
+
+int
+smbbufferfill(SmbBuffer *b, uchar val, ulong len)
+{
+	if (b->maxlen - b->wn < len)
+		return 0;
+	memset(b->buf + b->wn, val, len);
+	b->wn += len;
+	return 1;
+}
+
+int
+smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp)
+{
+	if (offset >= b->rn && offset + 1 <= b->wn) {
+		*bp = b->buf[b->rn + offset];
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount)
+{
+	if (smbbufferreadspace(from) < amount)
+		return 0;
+	if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) {
+		assert(smbbuffergetbytes(from, nil, amount));
+		return 1;
+	}
+	return 0;
+}
+
+int
+smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp)
+{
+	uchar *np;
+	if (offset < b->rn || offset >= b->wn)
+		return 0;
+	np = memchr(b->buf + offset, 0, b->wn - offset);
+	if (np == nil)
+		return 0;
+	*lenp = np - (b->buf + offset) + 1;
+	if (*lenp > buflen)
+		return 0;
+	memcpy(buf, b->buf + offset, *lenp);
+	return 1;
+}

+ 53 - 0
sys/src/cmd/aquarela/smbclientopen.c

@@ -0,0 +1,53 @@
+#include "headers.h"
+
+int
+smbclientopen(SmbClient *c, ushort mode, char *name, uchar *errclassp, ushort *errorp,
+	ushort *fidp, ushort *attrp, ulong *mtimep, ulong *sizep, ushort *accessallowedp, char **errmsgp)
+{
+	SmbBuffer *b;
+	SmbHeader h;
+	ulong bytecountfixup;
+	long n;
+	uchar *pdata;
+	ushort bytecount;
+
+	b = smbbuffernew(65535);
+	h = c->protoh;
+	h.tid = c->sharetid;
+	h.command = SMB_COM_OPEN;
+	h.wordcount = 2;
+	smbbufferputheader(b, &h, &c->peerinfo);
+	smbbufferputs(b, mode);
+	smbbufferputs(b, 0);
+	bytecountfixup = smbbufferwriteoffset(b);
+	smbbufferputs(b, 0);
+	smbbufferputb(b, 4);
+	smbbufferputstring(b, &c->peerinfo, SMB_STRING_REVPATH, name);
+	smbbufferfixuprelatives(b, bytecountfixup);
+	nbsswrite(c->nbss, smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	smbbufferreset(b);
+	n = nbssread(c->nbss, smbbufferwritepointer(b), smbbufferwritespace(b));
+	if (n < 0) {
+		smbstringprint(errmsgp, "read error: %r");
+		smbbufferfree(&b);
+		return 0;
+	}
+	smbbuffersetreadlen(b, n);
+	if (!smbbuffergetandcheckheader(b, &h, h.command, 7, &pdata, &bytecount, errmsgp)) {
+		smbbufferfree(&b);
+		return 0;
+	}
+	if (h.errclass) {
+		*errclassp = h.errclass;
+		*errorp = h.error;
+		smbbufferfree(&b);
+		return 0;
+	}
+	*fidp = smbnhgets(pdata); pdata += 2;
+	*attrp = smbnhgets(pdata); pdata += 2;
+	*mtimep = smbnhgetl(pdata); pdata += 4;
+	*sizep = smbnhgets(pdata); pdata += 4;
+	*accessallowedp = smbnhgets(pdata);
+	return 1;
+}
+

+ 24 - 0
sys/src/cmd/aquarela/smbcomclose.c

@@ -0,0 +1,24 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomclose(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
+{
+	SmbTree *t;
+	SmbFile *f;
+	ushort fid;
+	if (!smbcheckwordcount("comclose", h, 3))
+		return SmbProcessResultFormat;
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	fid = smbnhgets(pdata);
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	smbfileclose(s, f);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 25 - 0
sys/src/cmd/aquarela/smbcomcreatedir.c

@@ -0,0 +1,25 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomcreatedirectory(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	int fd;
+	char *path;
+	uchar fmt;
+
+	if (h->wordcount != 0)
+		return SmbProcessResultFormat;
+	if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path))
+		return SmbProcessResultFormat;
+	smblogprint(h->command, "smbcomcreatedirectory: %s\n", path);
+	fd = create(path, OREAD, DMDIR | 0775);
+	if (fd < 0) {
+		smblogprint(h->command, "smbcomcreatedirectory failed: %r\n");
+		smbseterror(s, ERRDOS, ERRnoaccess);
+		free(path);
+		return SmbProcessResultError;
+	}
+	close(fd);
+	free(path);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 76 - 0
sys/src/cmd/aquarela/smbcomdelete.c

@@ -0,0 +1,76 @@
+#include "headers.h"
+#include <String.h>
+
+int
+smbremovefile(SmbTree *t, char *dir, char *name)
+{
+	String *s;
+	int rv;
+	s = s_new();
+	s_append(s, t->serv->path);
+	s_append(s, "/");
+	if (dir) {
+		s_append(s, dir);
+		s_append(s, "/");
+	}
+	s_append(s, name);
+	rv = remove(s_to_c(s));
+	s_free(s);
+	return rv;
+}
+
+SmbProcessResult
+smbcomdelete(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	SmbProcessResult pr;
+	ushort sattr;
+	uchar fmt;
+	char *pattern = nil;
+	char *dir = nil;
+	char *name = nil;
+	Reprog *r = nil;
+	SmbTree *t;
+	int x, count;
+	SmbDirCache *dc = nil;
+
+	if (h->wordcount != 1)
+		return SmbProcessResultFormat;
+	sattr = smbnhgets(pdata);
+	if (!smbbuffergetb(b, &fmt) || fmt != 0x04
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern))
+		return SmbProcessResultFormat;
+	smblogprint(SMB_COM_DELETE, "searchattributes: 0x%.4ux\npattern:%s\n", sattr, pattern);
+	smbpathsplit(pattern, &dir, &name);
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	dc = smbmkdircache(t, dir);
+	if (dc == nil) {
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	r = smbmkrep(name);
+	count = 0;
+	for (x = 0; x < dc->n; x++) {
+		if (!smbmatch(dc->buf[x].name, r))
+			continue;
+		if (smbremovefile(t, dir, dc->buf[x].name) == 0)
+			count++;
+	}
+	if (count == 0) {
+		smbseterror(s, ERRDOS, ERRnoaccess);
+		pr = SmbProcessResultError;
+	}
+	else
+		pr = smbbufferputack(s->response,h, &s->peerinfo);
+done:
+	free(pattern);
+	free(dir);
+	free(name);
+	smbdircachefree(&dc);
+	free(r);
+	return pr;
+}

+ 24 - 0
sys/src/cmd/aquarela/smbcomdeletedir.c

@@ -0,0 +1,24 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomdeletedirectory(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	int rv;
+	char *path;
+	uchar fmt;
+
+	if (h->wordcount != 0)
+		return SmbProcessResultFormat;
+	if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path))
+		return SmbProcessResultFormat;
+	smblogprint(h->command, "smbcomdeletedirectory: %s\n", path);
+	rv = remove(path);
+	if (rv < 0) {
+		smblogprint(h->command, "smbcomdeletedirectory failed: %r\n");
+		smbseterror(s, ERRDOS, ERRnoaccess);
+		free(path);
+		return SmbProcessResultError;
+	}
+	free(path);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 49 - 0
sys/src/cmd/aquarela/smbcomdir.c

@@ -0,0 +1,49 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomcheckdirectory(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	char *path;
+	Dir *d;
+	uchar fmt;
+	SmbProcessResult pr;
+	SmbTree *t;
+	char *fullpath = nil;
+
+	if (!smbcheckwordcount("comcheckdirectory", h, 0))
+		return SmbProcessResultFormat;
+
+	if (!smbbuffergetb(b, &fmt)
+		|| fmt != 4
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path))
+		return SmbProcessResultFormat;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	
+	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
+smblogprintif(1, "smbcomcheckdirectory: statting %s\n", fullpath);
+	d = dirstat(fullpath);
+
+	if (d == nil || (d->mode & DMDIR) == 0) {
+		smbseterror(s, ERRDOS, ERRbadpath);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	if (access(fullpath, AREAD) < 0) {
+		smbseterror(s, ERRDOS, ERRbadpath);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	pr = smbbufferputack(s->response, h, &s->peerinfo) ? SmbProcessResultReply : SmbProcessResultMisc;
+done:
+	free(fullpath);
+	free(path);
+	free(d);
+	return pr;
+}

+ 25 - 0
sys/src/cmd/aquarela/smbcomecho.c

@@ -0,0 +1,25 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomecho(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	ushort echocount, e;
+	if (!smbcheckwordcount("comecho", h, 1))
+		return SmbProcessResultFormat;
+	echocount = smbnhgets(pdata);
+	for (e = 0; e < echocount; e++) {
+		ulong bytecountfixupoffset;
+		SmbProcessResult pr;
+		if (!smbbufferputheader(s->response, h, &s->peerinfo)
+			|| !smbbufferputs(s->response, e))
+			return SmbProcessResultMisc;
+		bytecountfixupoffset = smbbufferwriteoffset(s->response);
+		if (!smbbufferputbytes(s->response, smbbufferreadpointer(b), smbbufferreadspace(b))
+			|| !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
+			return SmbProcessResultMisc;
+		pr = smbresponsesend(s);
+		if (pr != SmbProcessResultOk)
+			return SmbProcessResultDie;
+	}
+	return SmbProcessResultOk;
+}

+ 12 - 0
sys/src/cmd/aquarela/smbcomfindclose2.c

@@ -0,0 +1,12 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomfindclose2(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
+{
+	ushort sid;
+	if (!smbcheckwordcount("comfindclose2", h, 1))
+		return SmbProcessResultFormat;
+	sid = smbnhgets(pdata);
+	smbsearchclosebyid(s, sid);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 28 - 0
sys/src/cmd/aquarela/smbcomflush.c

@@ -0,0 +1,28 @@
+#include "headers.h"
+#include <String.h>
+
+SmbProcessResult
+smbcomflush(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
+{
+	SmbTree *t;
+	SmbFile *f;
+	ushort fid;
+	Dir nulldir;
+	if (h->wordcount != 1)
+		return SmbProcessResultFormat;
+	fid = smbnhgets(pdata);
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	memset(&nulldir, 0xff, sizeof(nulldir));
+	nulldir.name = nulldir.uid = nulldir.gid = nulldir.muid = nil;
+	dirfwstat(f->fd, &nulldir);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 132 - 0
sys/src/cmd/aquarela/smbcomlocking.c

@@ -0,0 +1,132 @@
+#include "headers.h"
+
+static int
+getlock(SmbBuffer *b, int large, ushort *pidp, uvlong *offsetp, uvlong *lengthp)
+{
+	ulong ohigh, olow;
+	ulong lhigh, llow;
+	if (!smbbuffergets(b, pidp))
+		return 0;
+	if (large && !smbbuffergetbytes(b, nil, 2))
+		return 0;
+	if (large) {
+		if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow)
+			|| !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow))
+			return 0;
+		*offsetp = ((uvlong)ohigh << 32) | olow;
+		*lengthp = ((uvlong)lhigh << 32) | llow;
+		return 1;
+	}
+	if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow))
+		return 0;
+	*offsetp = olow;
+	*lengthp = llow;
+	return 1;
+}
+
+SmbProcessResult
+smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset;
+	ulong andxoffsetfixup;
+	ushort fid;
+	uchar locktype;
+	uchar oplocklevel;
+	ulong timeout;
+	ushort numberofunlocks;
+	ushort numberoflocks;
+	SmbTree *t;
+	SmbFile *f;
+	int l;
+	SmbProcessResult pr;
+	ulong backupoffset;
+	int large;
+
+	if (!smbcheckwordcount("comlockingandx", h, 8))
+		return SmbProcessResultFormat;
+
+	andxcommand = *pdata++;
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	fid = smbnhgets(pdata); pdata += 2;
+	locktype = *pdata++;
+	oplocklevel = *pdata++;
+	timeout = smbnhgetl(pdata); pdata += 4;
+	numberofunlocks = smbnhgets(pdata); pdata += 2;
+	numberoflocks = smbnhgets(pdata);
+	smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n",
+		fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks);
+	large = locktype & 0x10;
+	locktype &= ~0x10;
+	if (locktype != 0 || oplocklevel != 0) {
+		smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype);
+		return SmbProcessResultUnimp;
+	}
+	if (oplocklevel != 0) {
+		smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel);
+		return SmbProcessResultUnimp;
+	}
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+	error:
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		goto error;
+	}
+	backupoffset = smbbufferreadoffset(b);
+	for (l = 0; l < numberofunlocks; l++) {
+		ushort pid;
+		uvlong offset;
+		uvlong length;
+		if (!getlock(b, large, &pid, &offset, &length)) {
+			pr = SmbProcessResultFormat;
+			goto done;
+		}
+		smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n",
+			pid, offset, length);
+		smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
+	}
+	for (l = 0; l < numberoflocks; l++) {
+		ushort pid;
+		uvlong offset;
+		uvlong length;
+		if (!getlock(b, large, &pid, &offset, &length)) {
+			pr = SmbProcessResultFormat;
+			goto done;
+		}
+		smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n",
+			pid, offset, length);
+		if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length))
+			break;
+	}
+	if (l < numberoflocks) {
+		ushort i;
+		ushort pid;
+		uvlong offset;
+		uvlong length;
+		smbbufferreadbackup(b, backupoffset);
+		for (i  = 0; i < l; i++) {
+			assert(getlock(b, large, &pid, &offset, &length));
+			smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
+		}
+		smbseterror(s, ERRDOS, ERRlock);
+		goto error;
+	}
+	h->wordcount = 2;
+	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
+		|| !smbbufferputs(s->response, 0)) {	// bytecount 0
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
+		pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
+	else
+		pr = SmbProcessResultReply;
+done:
+	return pr;
+}

+ 335 - 0
sys/src/cmd/aquarela/smbcommon.c

@@ -0,0 +1,335 @@
+#include "headers.h"
+
+int
+smbsendunicode(SmbPeerInfo *i)
+{
+	return smbglobals.unicode && (i == nil || (i->capabilities & CAP_UNICODE) != 0);
+}
+
+int
+smbcheckwordcount(char *name, SmbHeader *h, ushort wordcount)
+{
+	if (h->wordcount != wordcount) {
+		smblogprint(-1, "smb%s: word count not %ud\n", name, wordcount);
+		return 0;
+	}
+	return 1;
+}
+
+int
+smbcheckwordandbytecount(char *name, SmbHeader *h, ushort wordcount, uchar **bdatap, uchar **edatap)
+{
+	ushort bytecount;
+	uchar *bdata;
+	if (h->wordcount != wordcount) {
+		smblogprint(-1, "smb%s: word count not %ud\n", name, wordcount);
+		return 0;
+	}
+	bdata = *bdatap;
+	if (bdata + 2 > *edatap) {
+		smblogprint(-1, "smb%s: not enough data for byte count\n", name);
+		return 0;
+	}
+	bytecount = smbnhgets(bdata); bdata += 2;
+	if (bdata + bytecount > *edatap) {
+		smblogprint(-1, "smb%s: not enough data for bytes\n", name);
+		return 0;
+	}
+	*edatap = bdata + bytecount;
+	*bdatap = bdata;
+	return 1;
+}
+
+SmbProcessResult
+smbchaincommand(SmbSession *s, SmbHeader *h, ulong andxoffsetfixup, uchar cmd, ushort offset, SmbBuffer *b)
+{
+	SmbOpTableEntry *ote;
+	uchar *pdata;
+	ushort bytecount;
+
+	h->command = cmd;
+	ote = smboptable + cmd;
+	if (ote->process == nil) {
+		smblogprint(-1, "smbchaincommand: %s (0x%.2ux) not implemented\n", ote->name, cmd);
+		return SmbProcessResultUnimp;
+	}
+	if (!smbresponsealignl2(s, 2)
+		|| !smbresponseoffsetputs(s, andxoffsetfixup, smbresponseoffset(s))
+		|| !smbbufferpopreadlimit(b))
+		return SmbProcessResultMisc;
+	if (!smbbufferreadskipto(b, offset)) {
+		smblogprint(-1, "smbchaincommand: illegal offset\n");
+		return SmbProcessResultFormat;
+	}
+	if (!smbbuffergetb(b, &h->wordcount)) {
+		smblogprint(-1, "smbchaincommand: not enough space for wordcount\n");
+		return SmbProcessResultFormat;
+	}
+	pdata = smbbufferreadpointer(b);
+	if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) {
+		smblogprint(-1, "smbchaincommand: not enough space for parameters\n");
+		return SmbProcessResultFormat;
+	}
+	if (!smbbuffergets(b, &bytecount)) {
+		smblogprint(-1, "smbchaincommand: not enough space for bytecount\n");
+		return SmbProcessResultFormat;
+	}
+	if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + bytecount)) {
+		smblogprint(-1, "smbchaincommand: not enough space for bytes\n");
+		return SmbProcessResultFormat;
+	}
+smblogprint(cmd, "chaining to %s\n", ote->name);
+	return (*ote->process)(s, h, pdata, b);
+}
+
+int
+smbbuffergetheader(SmbBuffer *b, SmbHeader *h, uchar **parametersp, ushort *bytecountp)
+{
+	SmbOpTableEntry *ote;
+	SmbRawHeader *rh;
+	rh = (SmbRawHeader *)smbbufferreadpointer(b);
+	if (!smbbuffergetbytes(b, nil, (long)offsetof(SmbRawHeader, parameterwords[0]))) {
+		smblogprint(-1, "smbgetheader: short packet\n");
+		return 0;
+	}
+	if (rh->protocol[0] != 0xff || memcmp(rh->protocol + 1, "SMB", 3) != 0) {
+		smblogprint(-1, "smbgetheader: invalid protocol\n");
+		return 0;
+	}
+	h->command = rh->command;
+	ote = smboptable + h->command;
+	if (ote->name == nil) {
+		smblogprint(-1, "smbgetheader: illegal opcode 0x%.2ux\n", h->command);
+		return 0;
+	}
+	h->errclass = rh->status[0];
+	h->error = smbnhgets(rh->status + 2);
+	h->flags = rh->flags;
+	h->flags2 = smbnhgets(rh->flags2);
+	if (h->flags & ~(SmbHeaderFlagCaseless | SMB_FLAGS_SERVER_TO_REDIR | SmbHeaderFlagReserved | SmbHeaderFlagServerIgnore))
+		smblogprint(-1, "smbgetheader: warning: unexpected flags 0x%.2ux\n", h->flags);
+	h->wordcount = rh->wordcount;
+	if (parametersp)
+		*parametersp = smbbufferreadpointer(b);
+	if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) {
+		smblogprint(-1, "smbgetheader: not enough data for parameter words\n");
+		return 0;
+	}
+	h->tid = smbnhgets(rh->tid);
+	h->pid = smbnhgets(rh->pid);
+	h->uid = smbnhgets(rh->uid);
+	h->mid = smbnhgets(rh->mid);
+	if (!smbbuffergets(b, bytecountp))
+		*bytecountp = 0;
+	if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + *bytecountp))
+		return 0;
+
+smblogprint(h->command, "%s %s: tid 0x%.4ux pid 0x%.4ux uid 0x%.4ux mid 0x%.4ux\n", ote->name,
+	(h->flags & SMB_FLAGS_SERVER_TO_REDIR) ? "response" : "request", h->tid, h->pid, h->uid, h->mid);
+	return 1;
+}
+
+int
+smbcheckheaderdirection(SmbHeader *h, int response, char **errmsgp)
+{
+	if (((h->flags & SMB_FLAGS_SERVER_TO_REDIR) == 0) == response) {
+		smbstringprint(errmsgp, "unexpected %s", response ? "request" : "response");
+		return 0;
+	}
+	return 1;
+}
+
+int
+smbcheckheader(SmbHeader *h, uchar command, int response, char **errmsgp)
+{
+	if (response && h->command != command) {
+		smbstringprint(errmsgp, "sent %.2uc request, got %.2ux response", command, h->command);
+		return 0;
+	}
+	if (!smbcheckheaderdirection(h, response, errmsgp))
+		return 0;
+	return 1;
+}
+
+int
+smbbuffergetandcheckheader(SmbBuffer *b, SmbHeader *h, uchar command, int response, uchar **pdatap, ushort *bytecountp, char **errmsgp)
+{
+	if (!smbbuffergetheader(b, h, pdatap, bytecountp)) {
+		smbstringprint(errmsgp, "smbbuffergetandcheckheader: not enough data for header");
+		return 0;
+	}
+	return smbcheckheader(h, command, response, errmsgp);
+}
+
+int
+smbsuccess(SmbHeader *h, char **errmsgp)
+{
+	if (h->errclass != SUCCESS) {
+		smbstringprint(errmsgp, "%s returned error %d/%d", smboptable[h->command].name, h->errclass, h->error);
+		return 0;
+	}
+	return 1;
+}
+
+#define BASE_FLAGS (0)
+
+int
+smbbufferputheader(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p)
+{
+	SmbRawHeader *rh;
+	if (offsetof(SmbRawHeader, parameterwords[0]) > smbbufferwritespace(b))
+		return 0;
+	if (smbbufferwriteoffset(b) == 0) {
+		rh = (SmbRawHeader *)smbbufferwritepointer(b);
+		rh->protocol[0] = 0xff;
+		memcpy(rh->protocol + 1, "SMB", 3);
+		rh->flags = SMB_FLAGS_SERVER_TO_REDIR | SmbHeaderFlagCaseless;
+		rh->command = h->command;
+		smbhnputs(rh->flags2, BASE_FLAGS | (smbsendunicode(p) ? SMB_FLAGS2_UNICODE : 0));
+		memset(rh->extra, 0, sizeof(rh->extra));
+		if (!smbbufferputbytes(b, nil, offsetof(SmbRawHeader, parameterwords[0])))
+			return 0;
+		rh->wordcount = h->wordcount;
+	}
+	else {
+		rh = (SmbRawHeader *)smbbufferreadpointer(b);
+		smbbufferputb(b, h->wordcount);
+	}
+	rh->status[0] = h->errclass;
+	rh->status[1] = 0;
+	smbhnputs(rh->status + 2, h->error);
+	smbhnputs(rh->tid, h->tid);
+	smbhnputs(rh->pid, h->pid);
+	smbhnputs(rh->uid, h->uid);
+	smbhnputs(rh->mid, h->mid);
+	return 1;
+}
+
+int
+smbbufferputerror(SmbBuffer *s, SmbHeader *h, SmbPeerInfo *p, uchar errclass, ushort error)
+{
+	h->errclass = errclass;
+	h->error = error;
+	return smbbufferputheader(s, h, p);
+}
+
+int
+smbbufferputandxheader(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p, uchar andxcommand, ulong *andxoffsetfixupp)
+{
+	if (!smbbufferputheader(b, h, p)
+		|| !smbbufferputb(b, andxcommand)
+		|| !smbbufferputb(b, 0))
+		return 0;
+	*andxoffsetfixupp = smbbufferwriteoffset(b);
+	return smbbufferputbytes(b, nil, 2);
+}
+
+void
+smbseterror(SmbSession *s, uchar errclass, ushort error)
+{
+	s->errclass = errclass;
+	s->error = error;
+}
+
+SmbProcessResult
+smbbufferputack(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p)
+{
+	h->wordcount = 0;
+	return smbbufferputheader(b, h, p) && smbbufferputs(b, 0) ? SmbProcessResultReply : SmbProcessResultMisc;
+}
+
+ushort
+smbplan9mode2dosattr(ulong mode)
+{
+	if (mode & DMDIR)
+		return SMB_ATTR_DIRECTORY;
+	return SMB_ATTR_NORMAL;
+}
+
+ulong
+smbdosattr2plan9mode(ushort attr)
+{
+	ulong mode = 0444;
+	if ((attr & SMB_ATTR_READ_ONLY) == 0)
+		mode |= 0222;
+	if (attr & SMB_ATTR_DIRECTORY) {
+		mode |= DMDIR | 0711;
+		mode &= DMDIR | 0755;
+	}
+	else
+		mode &= 0744;
+	return mode;
+}
+
+ulong
+smbdosattr2plan9wstatmode(ulong oldmode, ushort attr)
+{
+	ulong mode;
+	if (oldmode & DMDIR)
+		attr |= SMB_ATTR_DIRECTORY;
+	else
+		attr &= ~SMB_ATTR_DIRECTORY;
+	mode = smbdosattr2plan9mode(attr);
+	if (oldmode & 0444)
+		mode = (mode & ~0444) | (mode & 0444);
+	if ((attr & SMB_ATTR_READ_ONLY) == 0)
+		mode |= oldmode & 0222;
+	if (mode == oldmode)
+		mode = 0xffffffff;
+	return mode;
+}
+
+ulong
+smbplan9length2size32(vlong length)
+{
+	if (length > 0xffffffff)
+		return 0xffffffff;
+	return length;
+}
+
+vlong
+smbl2roundupvlong(vlong v, int l2)
+{
+	ulong mask;
+	mask = (1 << l2) - 1;
+	return (v + mask) & ~mask;
+}
+
+SmbSlut smbsharemodeslut[] = {
+	{ "compatibility", SMB_OPEN_MODE_SHARE_COMPATIBILITY },
+	{ "exclusive", SMB_OPEN_MODE_SHARE_EXCLUSIVE },
+	{ "denywrite", SMB_OPEN_MODE_SHARE_DENY_WRITE },
+	{ "denyread", SMB_OPEN_MODE_SHARE_DENY_READOREXEC },
+	{ "denynone", SMB_OPEN_MODE_SHARE_DENY_NONE },
+	{ 0 }
+};
+
+SmbSlut smbopenmodeslut[] = {
+	{ "oread", OREAD },
+	{ "owrite", OWRITE },
+	{ "ordwr", ORDWR },
+	{ "oexec", OEXEC },
+	{ 0 }
+};
+
+int
+smbslut(SmbSlut *s, char *pat)
+{
+	while (s->name) {
+		if (cistrcmp(s->name, pat) == 0)
+			return s->val;
+		s++;
+	}
+	return -1;
+}
+
+char *
+smbrevslut(SmbSlut *s, int val)
+{
+	while (s->name) {
+		if (s->val == val)
+			return s->name;
+		s++;
+	}
+	return nil;
+}

+ 617 - 0
sys/src/cmd/aquarela/smbcomopen.c

@@ -0,0 +1,617 @@
+#include "headers.h"
+
+static void
+smblogprintattr(int cmd, ushort attr)
+{
+	if (attr & SMB_ATTR_READ_ONLY)
+		smblogprint(cmd, " readonly");
+	if (attr & SMB_ATTR_HIDDEN)
+		smblogprint(cmd, " hidden");
+	if (attr & SMB_ATTR_SYSTEM)
+		smblogprint(cmd, " system");
+	if (attr & SMB_ATTR_DIRECTORY)
+		smblogprint(cmd, " directory");
+	if (attr & SMB_ATTR_ARCHIVE)
+		smblogprint(cmd, " archive");
+}
+
+static SmbFile *
+openfile(SmbSession *s, SmbTree *t, char *path, ushort mode, ushort attr, ushort ofun, ulong createoptions, uvlong createsize,
+	ushort *fidp, Dir **dp, ushort *actionp)
+{
+	int p9mode;
+	int share;
+	Dir *d = nil;
+	int fd = -1;
+	ushort action;
+	SmbFile *f = nil;
+	SmbSharedFile *sf = nil;
+	char *fullpath = nil;
+	int diropen = 0;
+
+	p9mode = (mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK;	
+	share = (mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK;	
+	if (share == SMB_OPEN_MODE_SHARE_COMPATIBILITY) {
+	badshare:
+		smbseterror(s, ERRDOS, ERRbadshare);
+		goto done;
+	}
+	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
+	d = dirstat(fullpath);
+	if (d) {
+		/* file exists */
+		int ofunexist;
+		if (d->mode & DMDIR) {
+			if (createoptions & SMB_CO_FILE) {
+				smbseterror(s, ERRDOS, ERRnoaccess);
+				goto done;
+			}
+		}
+		else if (createoptions & SMB_CO_DIRECTORY) {
+			smbseterror(s, ERRDOS, ERRnoaccess);
+			goto done;
+		}
+			
+		sf = smbsharedfileget(d, p9mode, &share);
+		if (sf == nil)
+			goto badshare;
+		action = 1;
+		ofunexist = (ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK;
+		if (ofunexist == SMB_OFUN_EXIST_FAIL) {
+			smbseterror(s, ERRDOS, ERRfilexists);
+			goto done;
+		}
+		else if (ofunexist == SMB_OFUN_EXIST_TRUNCATE) {
+			if ((d->mode & DMDIR) || (p9mode != OWRITE && p9mode != ORDWR)) {
+				smbseterror(s, ERRDOS, ERRbadaccess);
+				goto done;
+			}
+			p9mode |= OTRUNC;
+			action = 3;
+		}
+		else if (ofunexist != SMB_OFUN_EXIST_OPEN) {
+			smbseterror(s, ERRDOS, ERRbadaccess);
+			goto done;
+		}
+		if (d->mode & DMDIR)
+			diropen = 1;
+		else
+			fd = open(fullpath, p9mode);
+	}
+	else {
+		/* file does not exist */
+		ulong p9attr;
+		action = 3;
+		if ((ofun & SMB_OFUN_NOEXIST_CREATE) == 0) {
+			smbseterror(s, ERRDOS, ERRbadfile);
+			goto done;
+		}
+		if (createsize != 0) {
+			smbseterror(s, ERRDOS, ERRunsup);
+			goto done;
+		}
+//smblogprint(-1, "creating: attr 0x%.4ux co 0x%.8lux\n", attr, createoptions);
+		if (createoptions & SMB_CO_FILE) {
+			attr &= SMB_ATTR_DIRECTORY;
+			if (attr == 0)
+				attr = SMB_ATTR_NORMAL;
+		}
+		else if (createoptions & SMB_CO_DIRECTORY) {
+			attr &= ~SMB_ATTR_NORMAL;
+			attr |= SMB_ATTR_DIRECTORY;
+		}
+//smblogprint(-1, "creating: before conversion attr 0x%.4ux\n", attr);
+		p9attr = smbdosattr2plan9mode(attr);
+//smblogprint(-1, "creating: after conversion p9attr 0%.uo\n", p9attr);
+		fd = create(fullpath, p9mode, p9attr);
+		if (fd >= 0) {
+			d = dirfstat(fd);
+			sf = smbsharedfileget(d, p9mode, &share);
+			if (sf == nil) {
+				close(fd);
+				remove(path);
+				goto badshare;
+			}
+		}
+	}
+	if (!diropen && fd < 0) {
+		smbseterror(s, ERRSRV, ERRaccess);
+		goto done;
+	}
+	f = smbemalloc(sizeof(SmbFile));
+	if (diropen) {
+		f->ioallowed = 0;
+		f->fd = -1;
+	}
+	else {
+		f->ioallowed = 1;
+		f->fd = fd;
+	}
+	f->name = smbestrdup(path);
+	f->sf = sf;
+	sf = nil;
+	f->share = share;
+	f->p9mode = p9mode;
+	f->t = t;
+	if (s->fidmap == nil)
+		s->fidmap = smbidmapnew();
+	*fidp = smbidmapadd(s->fidmap, f);
+	smblogprintif(smbglobals.log.fids, "openfile: 0x%.4ux/0x%.4ux %s\n", t->id, *fidp, path);
+	if (actionp)
+		*actionp = action;
+	if (dp) {
+		*dp = d;
+		d = nil;
+	}
+done:
+	if (sf)
+		smbsharedfileput(nil, sf, share);
+	free(d);
+	free(fullpath);
+	return f;
+}
+
+SmbProcessResult
+smbcomopenandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset, flags, mode, sattr, attr;
+	ulong createtime;	
+	ushort ofun;
+	ulong createsize, timeout;
+	char *path = nil;
+	ulong andxoffsetfixupoffset;
+	SmbProcessResult pr;
+	ushort action;
+	Dir *d = nil;
+	SmbFile *f;
+	SmbTree *t;
+	ushort fid;
+
+	if (!smbcheckwordcount("comopenandx", h, 15))
+		return SmbProcessResultFormat;
+
+	andxcommand = *pdata++;
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	flags = smbnhgets(pdata); pdata += 2;
+	mode = smbnhgets(pdata); pdata += 2;
+	sattr = smbnhgets(pdata); pdata += 2;
+	attr = smbnhgets(pdata); pdata += 2;
+	createtime = smbnhgetl(pdata); pdata += 4;
+	ofun = smbnhgets(pdata); pdata += 2;
+	createsize = smbnhgetl(pdata); pdata += 4;
+	timeout = smbnhgetl(pdata); pdata += 4;
+	pdata += 4;
+	USED(pdata);
+	if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+
+	smbloglock();
+	smblogprint(h->command, "flags 0x%.4ux", flags);
+	if (flags & SMB_OPEN_FLAGS_ADDITIONAL)
+		smblogprint(h->command, " additional");
+	if (flags & SMB_OPEN_FLAGS_OPLOCK)
+		smblogprint(h->command, " oplock");
+	if (flags & SMB_OPEN_FLAGS_OPBATCH)
+		smblogprint(h->command, " opbatch");
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "mode 0x%.4ux", mode);
+	switch ((mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK) {
+	case OREAD:
+		smblogprint(h->command, " OREAD");
+		break;
+	case OWRITE:
+		smblogprint(h->command, " OWRITE");
+		break;
+	case ORDWR:
+		smblogprint(h->command, " ORDWR");
+		break;
+	case OEXEC:
+		smblogprint(h->command, " OEXEC");
+		break;
+	}
+	switch ((mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK) {
+	case SMB_OPEN_MODE_SHARE_COMPATIBILITY:
+		smblogprint(h->command, " compatinility");
+		break;
+	case SMB_OPEN_MODE_SHARE_EXCLUSIVE:
+		smblogprint(h->command, " exclusive");
+		break;
+	case SMB_OPEN_MODE_SHARE_DENY_WRITE:
+		smblogprint(h->command, " deny write");
+		break;
+	case SMB_OPEN_MODE_SHARE_DENY_READOREXEC:
+		smblogprint(h->command, " deny readorxec");
+		break;
+	case SMB_OPEN_MODE_SHARE_DENY_NONE:
+		smblogprint(h->command, " deny none");
+		break;
+	}
+	if (mode & SMB_OPEN_MODE_WRITE_THROUGH)
+		smblogprint(h->command, " write through");
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "sattr 0x%.4ux", sattr);
+	smblogprintattr(h->command, sattr);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "attr 0x%.4ux", attr);
+	smblogprintattr(h->command, attr);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "createtime 0x%.8lux\n", createtime);
+	smblogprint(h->command, "ofun 0x%.4ux", ofun);
+	if (ofun & SMB_OFUN_NOEXIST_CREATE)
+		smblogprint(h->command, " noexistscreate");
+	else
+		smblogprint(h->command, " noexistfail");
+	switch ((ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK) {
+	case SMB_OFUN_EXIST_FAIL:
+		smblogprint(h->command, " existfail");
+		break;
+	case SMB_OFUN_EXIST_OPEN:
+		smblogprint(h->command, " existopen");
+		break;
+	case SMB_OFUN_EXIST_TRUNCATE:
+		smblogprint(h->command, " existtruncate");
+		break;
+	}
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "createsize 0x%.8lux\n", createsize);
+	smblogprint(h->command, "timeout 0x%.8lux\n", timeout);
+	smblogprint(h->command, "path %s\n", path);
+	smblogunlock();
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		goto errordone;
+	}
+
+	f = openfile(s, t, path, mode, attr, ofun, 0, createsize, &fid, &d, &action);
+	if (f == nil) {
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	h->wordcount = 15;
+	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixupoffset)
+		|| !smbbufferputs(s->response, fid)
+		|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
+		|| !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
+		|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
+		|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) // probbaly bogus
+		|| !smbbufferputs(s->response, 0)	// all files are files
+		|| !smbbufferputs(s->response, 0)	// pipe state
+		|| !smbbufferputs(s->response, action)
+		|| !smbbufferputl(s->response, 0)	// fileID
+		|| !smbbufferputs(s->response, 0)
+		|| !smbbufferputs(s->response, 0)) {	// bytecount 0
+		smbfileclose(s, f);
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
+		pr = smbchaincommand(s, h, andxoffsetfixupoffset, andxcommand, andxoffset, b);
+	else
+		pr = SmbProcessResultReply;
+	goto done;	
+errordone:
+	pr = SmbProcessResultError;
+done:
+	free(path);
+	free(d);
+	return pr;
+}
+
+SmbProcessResult
+smbcomopen(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar fmt;
+	char *path;
+	ushort mode, attr;
+	SmbTree *t;
+	ushort fid;
+	Dir *d = nil;
+	SmbFile *f;
+	SmbProcessResult pr;
+
+	if (!smbcheckwordcount("comopen", h, 2))
+		return SmbProcessResultFormat;
+	mode = smbnhgets(pdata);
+	attr = smbnhgets(pdata + 2);
+	if (!smbbuffergetb(b, &fmt)
+		|| fmt != 4
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+	error:
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	f = openfile(s, t, path, mode, attr,
+		SMB_OFUN_EXIST_OPEN << SMB_OFUN_EXIST_SHIFT,
+		0, 0, &fid, &d, nil);
+	if (f == nil)
+		goto error;
+	h->wordcount = 7;
+	if (!smbbufferputheader(s->response, h, &s->peerinfo)
+		|| !smbbufferputs(s->response, fid)
+		|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
+		|| !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
+		|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
+		|| !smbbufferputs(s->response, 2)		// lies - this should be the actual access allowed
+		|| !smbbufferputs(s->response, 0))
+		pr = SmbProcessResultMisc;
+	else
+		pr = SmbProcessResultReply;
+done:
+	free(path);
+	free(d);
+	return pr;
+}
+
+typedef struct SmbSblut {
+	char *s;
+	ulong mask;
+} SmbSblut;
+
+static SmbSblut dasblut[] = {
+	{ "SMB_DA_SPECIFIC_READ_DATA", SMB_DA_SPECIFIC_READ_DATA },
+	{ "SMB_DA_SPECIFIC_WRITE_DATA", SMB_DA_SPECIFIC_WRITE_DATA },
+	{ "SMB_DA_SPECIFIC_APPEND_DATA", SMB_DA_SPECIFIC_APPEND_DATA },
+	{ "SMB_DA_SPECIFIC_READ_EA", SMB_DA_SPECIFIC_READ_EA },
+	{ "SMB_DA_SPECIFIC_WRITE_EA", SMB_DA_SPECIFIC_WRITE_EA },
+	{ "SMB_DA_SPECIFIC_EXECUTE", SMB_DA_SPECIFIC_EXECUTE },
+	{ "SMB_DA_SPECIFIC_DELETE_CHILD", SMB_DA_SPECIFIC_DELETE_CHILD },
+	{ "SMB_DA_SPECIFIC_READ_ATTRIBUTES", SMB_DA_SPECIFIC_READ_ATTRIBUTES },
+	{ "SMB_DA_SPECIFIC_WRITE_ATTRIBUTES", SMB_DA_SPECIFIC_WRITE_ATTRIBUTES },
+	{ "SMB_DA_STANDARD_DELETE_ACCESS", SMB_DA_STANDARD_DELETE_ACCESS },
+	{ "SMB_DA_STANDARD_READ_CONTROL_ACCESS", SMB_DA_STANDARD_READ_CONTROL_ACCESS },
+	{ "SMB_DA_STANDARD_WRITE_DAC_ACCESS", SMB_DA_STANDARD_WRITE_DAC_ACCESS },
+	{ "SMB_DA_STANDARD_WRITE_OWNER_ACCESS", SMB_DA_STANDARD_WRITE_OWNER_ACCESS },
+	{ "SMB_DA_STANDARD_SYNCHRONIZE_ACCESS", SMB_DA_STANDARD_SYNCHRONIZE_ACCESS },
+	{ "SMB_DA_GENERIC_ALL_ACCESS", SMB_DA_GENERIC_ALL_ACCESS },
+	{ "SMB_DA_GENERIC_EXECUTE_ACCESS", SMB_DA_GENERIC_EXECUTE_ACCESS },
+	{ "SMB_DA_GENERIC_WRITE_ACCESS", SMB_DA_GENERIC_WRITE_ACCESS },
+	{ "SMB_DA_GENERIC_READ_ACCESS", SMB_DA_GENERIC_READ_ACCESS },
+	{ 0 }
+};
+
+static SmbSblut efasblut[] = {
+	{ "SMB_ATTR_READ_ONLY", SMB_ATTR_READ_ONLY },
+	{ "SMB_ATTR_HIDDEN", SMB_ATTR_HIDDEN },
+	{ "SMB_ATTR_SYSTEM", SMB_ATTR_SYSTEM },
+	{ "SMB_ATTR_DIRECTORY", SMB_ATTR_DIRECTORY },
+	{ "SMB_ATTR_ARCHIVE", SMB_ATTR_ARCHIVE },
+	{ "SMB_ATTR_NORMAL", SMB_ATTR_NORMAL },
+	{ "SMB_ATTR_COMPRESSED", SMB_ATTR_COMPRESSED },
+	{ "SMB_ATTR_TEMPORARY", SMB_ATTR_TEMPORARY },
+	{ "SMB_ATTR_WRITETHROUGH", SMB_ATTR_WRITETHROUGH },
+	{ "SMB_ATTR_NO_BUFFERING", SMB_ATTR_NO_BUFFERING },
+	{ "SMB_ATTR_RANDOM_ACCESS", SMB_ATTR_RANDOM_ACCESS },
+	{ 0 }
+};
+
+static SmbSblut sasblut[] = {
+	{ "SMB_SA_SHARE_READ", SMB_SA_SHARE_READ },
+	{ "SMB_SA_SHARE_WRITE", SMB_SA_SHARE_WRITE },
+	{ "SMB_SA_SHARE_DELETE", SMB_SA_SHARE_DELETE },
+	{ "SMB_SA_NO_SHARE", SMB_SA_NO_SHARE },
+	{ 0 }
+};
+
+static SmbSblut cosblut[] = {
+	{ "SMB_CO_DIRECTORY", SMB_CO_DIRECTORY },
+	{ "SMB_CO_WRITETHROUGH", SMB_CO_WRITETHROUGH },
+	{ "SMB_CO_SEQUENTIAL_ONLY", SMB_CO_SEQUENTIAL_ONLY },
+	{ "SMB_CO_FILE", SMB_CO_FILE },
+	{ "SMB_CO_NO_EA_KNOWLEDGE", SMB_CO_NO_EA_KNOWLEDGE },
+	{ "SMB_CO_EIGHT_DOT_THREE_ONLY", SMB_CO_EIGHT_DOT_THREE_ONLY },
+	{ "SMB_CO_RANDOM_ACCESS", SMB_CO_RANDOM_ACCESS },
+	{ "SMB_CO_DELETE_ON_CLOSE", SMB_CO_DELETE_ON_CLOSE },
+	{ 0 }
+};
+
+static SmbSlut cdslut[] = {
+	{ "SMB_CD_SUPERCEDE", SMB_CD_SUPERCEDE },
+	{ "SMB_CD_OPEN", SMB_CD_OPEN },
+	{ "SMB_CD_CREATE", SMB_CD_CREATE },
+	{ "SMB_CD_OPEN_IF", SMB_CD_OPEN_IF },
+	{ "SMB_CD_OVERWRITE", SMB_CD_OVERWRITE },
+	{ "SMB_CD_OVERWRITE_IF", SMB_CD_OVERWRITE_IF },
+	{ 0 }
+};
+
+static void
+smbsblutlogprint(uchar cmd, SmbSblut *sblut, ulong mask)
+{
+	while (sblut->s) {
+		if (mask && (sblut->mask & mask) || (mask == 0 && sblut->mask == 0))
+			smblogprint(cmd, " %s", sblut->s);
+		sblut++;
+	}
+}
+
+SmbProcessResult
+smbcomntcreateandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset;
+	char *path = nil;
+	SmbProcessResult pr;
+	ulong namelength;
+	ulong flags;
+	ulong rootdirectoryfid, desiredaccess;
+	uvlong allocationsize;
+	ulong extfileattributes, shareaccess, createdisposition, createoptions, impersonationlevel;
+	uchar securityflags;
+	int p9mode;
+	int sharemode;
+	ushort mode;
+	SmbTree *t;
+	ushort ofun;
+	SmbFile *f;
+	ushort fid;
+	Dir *d = nil;
+	ushort action;
+	uvlong mtime;
+	ulong andxoffsetfixup;
+
+	if (!smbcheckwordcount("comntcreateandx", h, 24))
+		return SmbProcessResultFormat;
+
+	andxcommand = *pdata++;
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	pdata++;
+	namelength = smbnhgets(pdata); pdata += 2;
+	flags = smbnhgetl(pdata); pdata += 4;
+	rootdirectoryfid = smbnhgetl(pdata); pdata += 4;
+	desiredaccess = smbnhgetl(pdata); pdata += 4;
+	allocationsize = smbnhgetv(pdata); pdata += 8;
+	extfileattributes = smbnhgetl(pdata); pdata += 4;
+	shareaccess = smbnhgetl(pdata); pdata += 4;
+	createdisposition = smbnhgetl(pdata); pdata += 4;
+	createoptions = smbnhgetl(pdata); pdata += 4;
+	impersonationlevel = smbnhgetl(pdata); pdata += 4;
+	securityflags = *pdata++;
+	USED(pdata);
+
+	if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+
+	smblogprint(h->command, "namelength %d\n", namelength);
+	smblogprint(h->command, "flags 0x%.8lux\n", flags);
+	smblogprint(h->command, "rootdirectoryfid %lud\n", rootdirectoryfid);
+	smblogprint(h->command, "desiredaccess 0x%.8lux", desiredaccess);
+	smbsblutlogprint(h->command, dasblut, desiredaccess);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "allocationsize %llud\n", allocationsize);
+	smblogprint(h->command, "extfileattributes 0x%.8lux", extfileattributes);
+	smbsblutlogprint(h->command, efasblut, extfileattributes);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "shareaccess 0x%.8lux", shareaccess);
+	smbsblutlogprint(h->command, sasblut, shareaccess);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "createdisposition 0x%.8lux %s\n",
+		createdisposition, smbrevslut(cdslut, createdisposition));
+	smblogprint(h->command, "createoptions 0x%.8lux", createoptions);
+	smbsblutlogprint(h->command, cosblut, createoptions);
+	smblogprint(h->command, "\n");
+	smblogprint(h->command, "impersonationlevel 0x%.8lux\n", impersonationlevel);
+	smblogprint(h->command, "securityflags 0x%.2ux\n", securityflags);
+	smblogprint(h->command, "path %s\n", path);
+
+	if (rootdirectoryfid != 0) {
+		smblogprint(-1, "smbcomntcreateandx: fid relative not implemented\n");
+		goto unimp;
+	}
+
+	if (desiredaccess & SMB_DA_GENERIC_MASK) {
+		smblogprint(-1, "smbcomntcreateandx: generic bits in desiredaccess not implemented\n");
+		goto unimp;
+	}
+
+	if (desiredaccess & SMB_DA_SPECIFIC_READ_DATA)
+		if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
+			p9mode = ORDWR;
+		else
+			p9mode = OREAD;
+	else if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
+		p9mode = ORDWR;
+	else
+		p9mode = OREAD;
+
+	if (shareaccess == SMB_SA_NO_SHARE)
+		sharemode = SMB_OPEN_MODE_SHARE_EXCLUSIVE;
+	else if (shareaccess & (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE) ==
+		(SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE))
+		sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
+	else if (shareaccess & SMB_SA_SHARE_READ)
+		sharemode = SMB_OPEN_MODE_SHARE_DENY_WRITE;
+	else if (shareaccess & SMB_SA_SHARE_WRITE)
+		sharemode = SMB_OPEN_MODE_SHARE_DENY_READOREXEC;
+	else
+		sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
+
+	mode = (sharemode << SMB_OPEN_MODE_SHARE_SHIFT) | (p9mode << SMB_OPEN_MODE_ACCESS_SHIFT);
+
+	switch (createdisposition) {
+	default:
+		smblogprint(-1, "smbcomntcreateandx: createdisposition 0x%.8lux not implemented\n", createdisposition);
+		goto unimp;
+	case SMB_CD_OPEN:
+		ofun = SMB_OFUN_EXIST_OPEN;
+		break;
+	case SMB_CD_CREATE:
+		ofun = SMB_OFUN_EXIST_FAIL | SMB_OFUN_NOEXIST_CREATE;
+		break;
+	case SMB_CD_OPEN_IF:
+		ofun = SMB_OFUN_EXIST_OPEN | SMB_OFUN_NOEXIST_CREATE;
+		break;
+	case SMB_CD_OVERWRITE:
+		ofun = SMB_OFUN_EXIST_TRUNCATE;
+		break;
+	case SMB_CD_OVERWRITE_IF:
+		ofun = SMB_OFUN_EXIST_TRUNCATE | SMB_OFUN_NOEXIST_CREATE;
+		break;
+	}
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	f = openfile(s, t, path, mode, extfileattributes, ofun, createoptions, allocationsize, &fid, &d, &action);
+
+	if (f == nil) {
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	h->wordcount = 42;
+	mtime =  smbplan9time2time(d->mtime);
+	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
+		|| !smbbufferputb(s->response, 0)		// oplocks? pah
+		|| !smbbufferputs(s->response, fid)
+		|| !smbbufferputl(s->response, action)
+		|| !smbbufferputv(s->response, mtime)
+		|| !smbbufferputv(s->response, smbplan9time2time(d->atime))
+		|| !smbbufferputv(s->response, mtime)
+		|| !smbbufferputv(s->response, mtime)
+		|| !smbbufferputl(s->response, smbplan9mode2dosattr(d->mode))
+		|| !smbbufferputv(s->response, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
+		|| !smbbufferputv(s->response, d->length)
+		|| !smbbufferputbytes(s->response, nil, 4)
+		|| !smbbufferputb(s->response, (d->qid.type & QTDIR) != 0)
+		|| !smbbufferputbytes(s->response, nil, 8)
+		|| !smbbufferputs(s->response, 0)) {
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
+		pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
+	else
+		pr = SmbProcessResultReply;
+
+	goto done;
+
+unimp:
+	pr = SmbProcessResultUnimp;
+
+done:
+	free(path);
+	free(d);
+
+	return pr;
+}
+

+ 95 - 0
sys/src/cmd/aquarela/smbcomquery.c

@@ -0,0 +1,95 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomqueryinformation(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	SmbTree *t;
+	uchar fmt;
+	char *path;
+	Dir *d;
+	char *fullpath;
+
+	if (!smbcheckwordcount("comqueryinformation", h, 0)
+		|| !smbbuffergetb(b, &fmt)
+		|| fmt != 4
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path))
+		return SmbProcessResultFormat;
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		free(path);
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	smblogprint(h->command, "smbcomqueryinformation: %s\n", path);
+	fullpath = nil;
+	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
+	d = dirstat(fullpath);
+	free(fullpath);
+	free(path);
+	if (d == nil) {
+		smbseterror(s, ERRDOS, ERRbadpath);
+		return SmbProcessResultError;
+	}
+	h->wordcount = 10;
+	if (!smbbufferputheader(s->response, h, &s->peerinfo)
+		|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
+		|| !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
+		|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
+		|| !smbbufferfill(s->response, 0, 10)
+		|| !smbbufferputs(s->response, 0)) {
+		free(d);
+		return SmbProcessResultMisc;
+	}
+	free(d);
+	return SmbProcessResultReply;
+}
+
+SmbProcessResult
+smbcomqueryinformation2(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
+{
+	SmbTree *t;
+	Dir *d;
+	ushort fid;
+	ushort mtime, mdate;
+	ushort atime, adate;
+	SmbFile *f;
+
+	if (!smbcheckwordcount("comqueryinformation2", h, 1))
+		return SmbProcessResultFormat;
+	fid = smbnhgets(pdata);
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	d = dirfstat(f->fd);
+	if (d == nil) {
+		smbseterror(s, ERRDOS, ERRbadpath);
+		return SmbProcessResultError;
+	}
+	h->wordcount = 11;
+	smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
+	smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
+	if (!smbbufferputheader(s->response, h, &s->peerinfo)
+		|| !smbbufferputs(s->response, mdate)
+		|| !smbbufferputs(s->response, mtime)
+		|| !smbbufferputs(s->response, adate)
+		|| !smbbufferputs(s->response, atime)
+		|| !smbbufferputs(s->response, mdate)
+		|| !smbbufferputs(s->response, mtime)
+		|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
+		|| !smbbufferputl(s->response,
+			smbplan9length2size32(smbl2roundupvlong(d->length, smbglobals.l2allocationsize)))
+		|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
+		|| !smbbufferputs(s->response, 0)) {
+		free(d);
+		return SmbProcessResultMisc;
+	}
+	free(d);
+	return SmbProcessResultReply;
+}

+ 84 - 0
sys/src/cmd/aquarela/smbcomread.c

@@ -0,0 +1,84 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomreadandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset;
+	ulong andxoffsetfixup;
+	ulong datafixup;
+	ulong bytecountfixup;
+	ushort fid;
+	SmbTree *t;
+	SmbFile *f;
+	vlong offset;
+	ushort maxcount;
+	long toread;
+	long nb;
+
+	if (h->wordcount != 10 && h->wordcount != 12)
+		return SmbProcessResultFormat;
+
+	andxcommand = *pdata++;
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	fid = smbnhgets(pdata); pdata += 2;
+	offset = smbnhgetl(pdata); pdata += 4;
+	maxcount = smbnhgets(pdata); pdata += 2;
+	pdata += 2;	// mincount
+	pdata += 4;	// timeout ?
+	pdata += 2;	// remaining
+	if (h->wordcount == 12)
+		offset |= (vlong)smbnhgetl(pdata) << 32;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	
+	if (!f->ioallowed) {
+		smbseterror(s, ERRDOS, ERRbadaccess);
+		return SmbProcessResultError;
+	}
+
+	h->wordcount = 12;
+	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
+		return SmbProcessResultMisc;
+	if (!smbbufferputs(s->response, -1)			// remaining
+		|| !smbbufferputs(s->response, 0)		// datacompactionmode
+		|| !smbbufferputs(s->response, 0))		// reserved
+		return SmbProcessResultMisc;
+	datafixup = smbbufferwriteoffset(s->response);
+	if (!smbbufferputbytes(s->response, nil, 6)
+		|| !smbbufferfill(s->response, 0, 8))		// reserved
+		return SmbProcessResultMisc;
+	bytecountfixup = smbbufferwriteoffset(s->response);
+	if (!smbbufferputs(s->response, 0)
+		|| !smbbufferputb(s->response, 0))
+		return SmbProcessResultMisc;
+	smbbufferwritelimit(s->response, smbbufferwriteoffset(s->response) + 65535);
+	smbbufferoffsetputs(s->response, datafixup + 2, smbbufferwriteoffset(s->response));
+	seek(f->fd, offset, 0);
+	toread = smbbufferwritespace(s->response);	
+	if (toread > maxcount)
+		toread = maxcount;
+	nb = readn(f->fd, smbbufferwritepointer(s->response), toread);
+	if (nb < 0) {
+		smbseterror(s, ERRDOS, ERRbadaccess);
+		return SmbProcessResultError;
+	}
+	if (!smbbufferputbytes(s->response, nil, nb)
+		|| !smbbufferfixuprelatives(s->response, bytecountfixup)
+		|| !smbbufferoffsetputs(s->response, datafixup, nb)
+		|| !smbbufferoffsetputs(s->response, datafixup + 4, nb >> 16))
+		return SmbProcessResultMisc;
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
+		return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
+	return SmbProcessResultReply;
+}

+ 45 - 0
sys/src/cmd/aquarela/smbcomrename.c

@@ -0,0 +1,45 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomrename(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	int rv;
+	char *oldpath, *newpath;
+	char *olddir, *newdir;
+	char *oldname, *newname;
+	uchar oldfmt, newfmt;
+	Dir d;
+	SmbProcessResult pr;
+
+	if (h->wordcount != 1)
+		return SmbProcessResultFormat;
+	if (!smbbuffergetb(b, &oldfmt) || oldfmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &oldpath)
+		|| !smbbuffergetb(b, &newfmt) || newfmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &newpath))
+		return SmbProcessResultFormat;
+	smblogprint(h->command, "smbcomrename: %s to %s\n", oldpath, newpath);
+	smbpathsplit(oldpath, &olddir, &oldname);
+	smbpathsplit(newpath, &newdir, &newname);
+	if (strcmp(olddir, newdir) != 0) {
+		smblogprint(h->command, "smbcomrename: directories differ\n");
+		goto noaccess;
+	}
+	memset(&d, 0xff, sizeof(d));
+	d.uid = d.gid = d.muid = nil;
+	d.name = newname;
+	rv = dirwstat(oldpath, &d);
+	if (rv < 0) {
+		smblogprint(h->command, "smbcomrename failed: %r\n");
+	noaccess:
+		smbseterror(s, ERRDOS, ERRnoaccess);
+		pr =  SmbProcessResultError;
+	}
+	else
+		pr = smbbufferputack(s->response, h, &s->peerinfo);
+	free(oldpath);
+	free(olddir);
+	free(oldname);
+	free(newpath);
+	free(newdir);
+	free(newname);
+	return pr;
+}

+ 186 - 0
sys/src/cmd/aquarela/smbcomsessionsetupandx.c

@@ -0,0 +1,186 @@
+#include "headers.h"
+#include <mp.h>
+#include <libsec.h>
+
+SmbProcessResult
+smbcomsessionsetupandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset;
+	ulong andxfixupoffset;
+	ushort vcnumber;
+	ulong sessionkey;
+	ushort caseinsensitivepasswordlength;
+	ushort casesensitivepasswordlength;
+	ushort bytecountfixup, offset;
+	uchar *mschapreply;
+	AuthInfo *ai;
+	char *sp;
+	SmbProcessResult pr;
+	char *accountname = nil;
+	char *primarydomain = nil;
+	char *nativeos = nil;
+	char *nativelanman = nil;
+
+	if (!smbcheckwordcount("comsessionsetupandx", h, 13)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+
+	andxcommand = *pdata++;
+	switch (andxcommand) {
+	case SMB_COM_TREE_CONNECT_ANDX:
+	case SMB_COM_OPEN_ANDX:
+	case SMB_COM_CREATE_NEW:
+	case SMB_COM_DELETE:
+	case SMB_COM_FIND:
+	case SMB_COM_COPY:
+	case SMB_COM_NT_RENAME:
+	case SMB_COM_QUERY_INFORMATION:
+	case SMB_COM_NO_ANDX_COMMAND:
+	case SMB_COM_OPEN:
+	case SMB_COM_CREATE:
+	case SMB_COM_CREATE_DIRECTORY:
+	case SMB_COM_DELETE_DIRECTORY:
+	case SMB_COM_FIND_UNIQUE:
+	case SMB_COM_RENAME:
+	case SMB_COM_CHECK_DIRECTORY:
+	case SMB_COM_SET_INFORMATION:
+	case SMB_COM_OPEN_PRINT_FILE:
+		break;
+	default:
+		smblogprint(h->command, "smbcomsessionsetupandx: invalid andxcommand %s (0x%.2ux)\n",
+			smboptable[andxcommand].name, andxcommand);
+		goto fmtfail;
+	}
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	s->peerinfo.maxlen = smbnhgets(pdata); pdata += 2;
+	smbresponseinit(s, s->peerinfo.maxlen);
+	s->client.maxmpxcount = smbnhgets(pdata); pdata += 2;
+	vcnumber = smbnhgets(pdata); pdata += 2;
+	sessionkey = smbnhgetl(pdata); pdata += 4;
+	caseinsensitivepasswordlength = smbnhgets(pdata); pdata += 2;
+	casesensitivepasswordlength = smbnhgets(pdata); pdata += 2;
+	pdata += 4;
+	s->peerinfo.capabilities = smbnhgetl(pdata); /*pdata += 4;*/
+smbloglock();
+smblogprint(h->command, "andxcommand: %s offset %ud\n", smboptable[andxcommand].name, andxoffset);
+smblogprint(h->command, "client.maxbuffersize: %ud\n", s->peerinfo.maxlen);
+smblogprint(h->command, "client.maxmpxcount: %ud\n", s->client.maxmpxcount);
+smblogprint(h->command, "vcnumber: %ud\n", vcnumber);
+smblogprint(h->command, "sessionkey: 0x%.8lux\n", sessionkey);
+smblogprint(h->command, "caseinsensitivepasswordlength: %ud\n", caseinsensitivepasswordlength);
+smblogprint(h->command, "casesensitivepasswordlength: %ud\n", casesensitivepasswordlength);
+smblogprint(h->command, "clientcapabilities: 0x%.8lux\n", s->peerinfo.capabilities);
+smblogunlock();
+
+	mschapreply = smbbufferreadpointer(b);
+
+	if (!smbbuffergetbytes(b, nil, caseinsensitivepasswordlength + casesensitivepasswordlength)) {
+		smblogprint(h->command, "smbcomsessionsetupandx: not enough bdata for passwords\n");
+		goto fmtfail;
+	}
+	if (!smbbuffergetstring(b, h, 0, &accountname)
+		|| !smbbuffergetstring(b, h, 0, &primarydomain)
+		|| !smbbuffergetstring(b, h, 0, &nativeos)
+		|| !smbbuffergetstring(b, h, 0, &nativelanman)) {
+		smblogprint(h->command, "smbcomsessionsetupandx: not enough bytes for strings\n");
+		goto fmtfail;
+	}
+
+	for (sp = accountname; *sp; sp++)
+		*sp = tolower(*sp);
+
+smblogprint(h->command, "account: %s\n", accountname);
+smblogprint(h->command, "primarydomain: %s\n", primarydomain);
+smblogprint(h->command, "nativeos: %s\n", nativeos);
+smblogprint(h->command, "nativelanman: %s\n", nativelanman);
+
+	if (s->client.accountname && accountname[0] && strcmp(s->client.accountname, accountname) != 0) {
+		smblogprint(h->command, "smbcomsessionsetupandx: more than one user on VC (before %s, now %s)\n",
+			s->client.accountname, accountname);
+		smbseterror(s, ERRSRV, ERRtoomanyuids);
+	errordone:
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	if (s->client.accountname == nil) {
+		/* first time */
+		if (accountname[0] == 0) {
+			smbseterror(s, ERRSRV, ERRbaduid);
+			goto errordone;
+		}
+		if ((casesensitivepasswordlength != 24 || caseinsensitivepasswordlength != 24)) {
+			smblogprint(h->command,
+				"smbcomsessionsetupandx: case sensitive/insensitive password length not 24\n");
+			smbseterror(s, ERRSRV, ERRbadpw);
+			goto errordone;
+		}
+		memcpy(&s->client.mschapreply, mschapreply, sizeof(s->client.mschapreply));
+		s->cs->user = accountname;
+		s->cs->resp = &s->client.mschapreply;
+		s->cs->nresp = sizeof(MSchapreply);
+		ai = auth_response(s->cs);
+		if (ai == nil) {
+			smblogprint(h->command, "authentication failed\n");
+			smbseterror(s, ERRSRV, ERRbadpw);
+			goto errordone;
+		}
+		smblogprint(h->command, "authentication succeeded\n");
+		if (auth_chuid(ai, nil) < 0) {
+			smblogprint(h->command, "smbcomsessionsetupandx: chuid failed: %r\n");
+			auth_freeAI(ai);
+		miscerror:
+			pr = SmbProcessResultMisc;
+			goto done;
+		}
+		auth_freeAI(ai);
+		h->uid = 1;
+		s->client.accountname = accountname;
+		s->client.primarydomain = primarydomain;
+		s->client.nativeos = nativeos;
+		s->client.nativelanman = nativelanman;
+		accountname = nil;
+		primarydomain = nil;
+		nativeos = nil;
+		nativelanman = nil;
+	}
+	else {
+		if (caseinsensitivepasswordlength == 24 && casesensitivepasswordlength == 24
+			&& memcmp(&s->client.mschapreply, mschapreply, sizeof(MSchapreply)) != 0) {
+			smblogprint(h->command, "second time authentication failed\n");
+			smbseterror(s, ERRSRV, ERRbadpw);
+			goto errordone;
+		}
+	}
+
+	/* CIFS says 4 with or without extended security, samba/ms says 3 without */
+	h->wordcount = 3;
+	if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset))
+		goto miscerror;
+	if (!smbresponseputs(s, 0))
+		goto miscerror;
+	bytecountfixup = smbresponseoffset(s);
+	if (!smbresponseputs(s, 0))
+		goto miscerror;
+	if (!smbresponseputstring(s, 1, smbglobals.nativeos)
+		|| !smbresponseputstring(s, 1, smbglobals.serverinfo.nativelanman)
+		|| !smbresponseputstring(s, 1, smbglobals.primarydomain))
+		goto miscerror;
+	offset = smbresponseoffset(s);
+	smbresponseoffsetputs(s, bytecountfixup, offset - bytecountfixup - 2);
+	s->state = SmbSessionEstablished;
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
+		pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
+	else
+		pr = SmbProcessResultReply;
+done:
+	free(accountname);
+	free(primarydomain);
+	free(nativeos);
+	free(nativelanman);
+	return pr;
+}

+ 107 - 0
sys/src/cmd/aquarela/smbcomsetinfo.c

@@ -0,0 +1,107 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomsetinformation2(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
+{
+	ushort fid, adate, atime, mdate, mtime;
+	SmbTree *t;
+	SmbFile *f;
+	Dir d;
+
+	if (h->wordcount != 7)
+		return SmbProcessResultFormat;
+	fid = smbnhgets(pdata);
+	adate = smbnhgets(pdata + 6);
+	atime = smbnhgets(pdata + 8);
+	mdate = smbnhgets(pdata + 10);
+	mtime = smbnhgets(pdata + 12);
+	smblogprint(h->command,
+		"smbcomsetinformation2: fid 0x%.4ux adate 0x%.4ux atime 0x%.4ux mdate 0x%.4ux mtime 0x%.4ux\n",
+		fid, adate, atime, mdate, mtime);
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	memset(&d, 0xff, sizeof(d));
+	d.name = d.uid = d.gid = d.muid = nil;
+	if (adate || atime || mdate || mtime) {
+//smblogprint(-1, "smbcomsetinformation2: changing times not implemented\n");
+//		return SmbProcessResultUnimp;
+		/* something to change */
+		if (!(adate && atime && mdate && mtime)) {
+			/* some null entries */
+			ushort odate, otime;
+			Dir *od = dirfstat(f->fd);
+			if (od == nil) {
+				smbseterror(s, ERRDOS, ERRnoaccess);
+				return SmbProcessResultError;
+			}
+			if (adate || atime) {
+				/* something changed in access time */
+				if (!(adate && atime)) {
+					/* some nulls in access time */
+					smbplan9time2datetime(d.atime, s->tzoff, &odate, &otime);
+					if (adate == 0)
+						adate = odate;
+					if (atime == 0)
+						atime = otime;
+				}
+				d.atime = smbdatetime2plan9time(adate, atime, s->tzoff);
+			}
+			if (mdate || mtime) {
+				/* something changed in modify time */
+				if (!(mdate && mtime)) {
+					/* some nulls in modify time */
+					smbplan9time2datetime(d.mtime, s->tzoff, &odate, &otime);
+					if (mdate == 0)
+						mdate = odate;
+					if (mtime == 0)
+						mtime = otime;
+				}
+				d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff);
+			}
+			free(od);
+		}
+		if (dirfwstat(f->fd, &d) < 0) {
+			smbseterror(s, ERRDOS, ERRnoaccess);
+			return SmbProcessResultError;
+		}
+	}
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}
+
+SmbProcessResult
+smbcomsetinformation(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	ushort attr;
+	ulong utime;
+	char *name;
+	if (h->wordcount != 8)
+		return SmbProcessResultFormat;
+	attr = smbnhgets(pdata); pdata += 2;
+	utime = smbnhgetl(pdata);
+	if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &name))
+		return SmbProcessResultFormat;
+	smblogprint(h->command,
+		"smbcomsetinformation: attr 0x%.4ux utime %lud path %s\n",
+		attr, utime, name);
+	if (utime) {
+		Dir d;
+		memset(&d, 0xff, sizeof(d));
+		d.name = d.uid = d.gid = d.muid = nil;
+		d.mtime = smbutime2plan9time(utime, s->tzoff);
+		if (dirwstat(name, &d) < 0) {
+			smbseterror(s, ERRDOS, ERRnoaccess);
+			free(name);
+			return SmbProcessResultError;
+		}
+	}
+	free(name);		
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 137 - 0
sys/src/cmd/aquarela/smbcomtransaction.c

@@ -0,0 +1,137 @@
+#include "headers.h"
+
+static int
+sendresponse(void *magic, SmbBuffer *, char **errmsgp)
+{
+	int rv;
+	SmbSession *s = magic;
+	rv = smbresponsesend(s);
+	if (rv < 0) {
+		smbstringprint(errmsgp, "sendresponse failed");
+		return 0;
+	}
+	return 1;
+}
+
+SmbTransactionMethod smbtransactionmethod = {
+	.encoderesponse = smbtransactionencoderesponse,
+	.sendresponse = sendresponse,
+};
+
+SmbTransactionMethod smbtransactionmethod2 = {
+	.encoderesponse = smbtransactionencoderesponse2,
+	.sendresponse = sendresponse,
+};
+
+int
+smbcomtransaction(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	int rv;
+	char *errmsg;
+	SmbProcessResult pr = SmbProcessResultDie;
+	errmsg = nil;
+	rv = smbtransactiondecodeprimary(&s->transaction, h, pdata, b, &errmsg);
+	if (rv < 0) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	if (rv == 0) {
+		h->wordcount = 0;
+		if (smbbufferputack(s->response, h, &s->peerinfo)) {
+			pr = SmbProcessResultReply;
+			s->nextcommand = SMB_COM_TRANSACTION_SECONDARY;
+		}
+		goto done;
+	}
+	smblogprint(h->command, "smbcomtransaction: %s scount %ud tpcount %lud tdcount %lud maxscount %lud maxpcount %lud maxdcount %lud\n",
+		s->transaction.in.name, s->transaction.in.scount, s->transaction.in.tpcount, s->transaction.in.tdcount,
+		s->transaction.in.maxscount, s->transaction.in.maxpcount, s->transaction.in.maxdcount);
+	smbbufferfree(&s->transaction.out.parameters);
+	smbbufferfree(&s->transaction.out.data);
+	s->transaction.out.parameters = smbbuffernew(s->transaction.in.maxpcount);
+	s->transaction.out.data = smbbuffernew(s->transaction.in.maxdcount);
+	if (strcmp(s->transaction.in.name, smbglobals.pipelanman) == 0)
+		pr = smbrap2(s);
+	else {
+		smbseterror(s, ERRDOS, ERRbadpath);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	if (pr == SmbProcessResultReply) {
+		char *errmsg;
+		errmsg = nil;
+		rv = smbtransactionrespond(&s->transaction, h, &s->peerinfo, s->response, &smbtransactionmethod, s, &errmsg);
+		if (!rv) {
+			smblogprint(h->command, "smbcomtransaction: failed: %s\n", errmsg);
+			pr = SmbProcessResultMisc;
+		}
+		else
+			pr = SmbProcessResultOk;
+	}
+done:
+	free(errmsg);
+	return pr;
+}
+
+int
+smbcomtransaction2(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	int rv;
+	char *errmsg;
+	SmbProcessResult pr = SmbProcessResultDie;
+	ushort op;
+
+	errmsg = nil;
+	rv = smbtransactiondecodeprimary2(&s->transaction, h, pdata, b, &errmsg);
+	if (rv < 0) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	if (rv == 0) {
+		h->wordcount = 0;
+		if (smbbufferputack(s->response, h, &s->peerinfo)) {
+			pr = SmbProcessResultReply;
+			s->nextcommand = SMB_COM_TRANSACTION2_SECONDARY;
+		}
+		goto done;
+	}
+	smblogprint(h->command, "smbcomtransaction2: scount %ud tpcount %lud tdcount %lud maxscount %lud maxpcount %lud maxdcount %lud\n",
+		s->transaction.in.scount, s->transaction.in.tpcount, s->transaction.in.tdcount,
+		s->transaction.in.maxscount, s->transaction.in.maxpcount, s->transaction.in.maxdcount);
+	smbbufferfree(&s->transaction.out.parameters);
+	smbbufferfree(&s->transaction.out.data);
+	s->transaction.out.parameters = smbbuffernew(s->transaction.in.maxpcount);
+	s->transaction.out.data = smbbuffernew(s->transaction.in.maxdcount);
+	if (s->transaction.in.scount != 1)
+		goto fmtfail;
+	op = s->transaction.in.setup[0];
+	if (op >= smbtrans2optablesize || smbtrans2optable[op].name == nil) {
+		smblogprint(-1, "smbcomtransaction2: function %d unknown\n", op);
+		pr = SmbProcessResultUnimp;
+		goto done;
+	}
+	if (smbtrans2optable[op].process == nil) {
+		smblogprint(-1, "smbcomtransaction2: %s unimplemented\n", smbtrans2optable[op].name);
+		pr = SmbProcessResultUnimp;
+		goto done;
+	}
+	pr = (*smbtrans2optable[op].process)(s, h);
+	if (pr == SmbProcessResultReply) {
+		char *errmsg;
+		errmsg = nil;
+		rv = smbtransactionrespond(&s->transaction, h, &s->peerinfo, s->response, &smbtransactionmethod2, s, &errmsg);
+		if (!rv) {
+			smblogprint(h->command, "smbcomtransaction2: failed: %s\n", errmsg);
+			pr = SmbProcessResultMisc;
+		}
+		else
+			pr = SmbProcessResultOk;
+	}
+done:
+	free(errmsg);
+	return pr;
+}
+
+
+

+ 116 - 0
sys/src/cmd/aquarela/smbcomtreeconnectandx.c

@@ -0,0 +1,116 @@
+#include "headers.h"
+
+static char *s9p2000 = "9p2000";
+
+SmbProcessResult
+smbcomtreeconnectandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	uchar andxcommand;
+	ushort andxoffset;
+	char *path = nil;
+	char *service = nil;
+	ushort flags;
+	ushort passwordlength;
+//	ushort bytecount;
+	uchar errclass;
+	ushort error;
+	SmbService *serv;
+	SmbTree *tree;
+	ulong andxfixupoffset, bytecountfixup;
+	SmbProcessResult pr;
+
+	if (!smbcheckwordcount("comtreeconnectandx", h, 4)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+
+	switch (s->state) {
+	case SmbSessionNeedNegotiate:
+		smblogprint(-1, "smbcomtreeconnectandx: called when negotiate expected\n");
+		return SmbProcessResultUnimp;
+	case SmbSessionNeedSetup:
+		smbseterror(s, ERRDOS, ERRbadpw);
+		return SmbProcessResultError;
+	}
+
+	andxcommand = *pdata++;
+	switch (andxcommand) {
+	case SMB_COM_OPEN:
+	case SMB_COM_CREATE_NEW:
+	case SMB_COM_DELETE_DIRECTORY:
+	case SMB_COM_FIND_UNIQUE:
+	case SMB_COM_CHECK_DIRECTORY:
+	case SMB_COM_GET_PRINT_QUEUE:
+	case SMB_COM_TRANSACTION:
+	case SMB_COM_SET_INFORMATION:
+	case SMB_COM_OPEN_ANDX:
+	case SMB_COM_CREATE_DIRECTORY:
+	case SMB_COM_FIND:
+	case SMB_COM_RENAME:
+	case SMB_COM_QUERY_INFORMATION:
+	case SMB_COM_OPEN_PRINT_FILE:
+	case SMB_COM_NO_ANDX_COMMAND:
+	case SMB_COM_NT_RENAME:
+	case SMB_COM_CREATE:
+	case SMB_COM_DELETE:
+	case SMB_COM_COPY:
+		break;
+	default:
+		smblogprint(h->command, "smbcomtreeconnectandx: invalid andxcommand %s (0x%.2ux)\n",
+			smboptable[andxcommand].name, andxcommand);
+		goto fmtfail;
+	}
+	pdata++;
+	andxoffset = smbnhgets(pdata); pdata += 2;
+	flags = smbnhgets(pdata); pdata += 2;
+	passwordlength = smbnhgets(pdata); //pdata += 2;
+//	bytecount = smbnhgets(pdata); pdata += 2;
+smblogprint(h->command, "passwordlength: %ud\n", passwordlength);
+smblogprint(h->command, "flags: 0x%.4ux\n", flags);
+	if (!smbbuffergetbytes(b, nil, passwordlength)) {
+		smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for password\n");
+		goto fmtfail;
+	}
+smblogprint(h->command, "offset %lud limit %lud\n", smbbufferreadoffset(b), smbbufferwriteoffset(b));
+	if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)
+		|| !smbbuffergetstr(b, 0, &service)) {
+		smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for strings\n");
+		goto fmtfail;
+	}
+smblogprint(h->command, "path: %s\n", path);
+smblogprint(h->command, "service: %s\n", service);
+	if (flags & 1)
+		smbtreedisconnectbyid(s, h->tid);
+	serv = smbservicefind(s, path, service, &errclass, &error);
+	if (serv == nil) {
+		pr = SmbProcessResultError;
+		smbseterror(s, errclass, error);
+		goto done;
+	}
+	tree = smbtreeconnect(s, serv);
+	h->tid = tree->id;
+	h->wordcount = 3;
+	if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset)
+		|| !smbresponseputs(s, 1)) {
+	misc:
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	bytecountfixup = smbresponseoffset(s);
+	if (!smbresponseputs(s, 0)
+		|| !smbresponseputstr(s, serv->type)
+		|| !smbresponseputstring(s, 1, s9p2000))
+		goto misc;
+	if (!smbbufferfixuprelatives(s->response, bytecountfixup))
+		goto misc;
+	if (andxcommand != SMB_COM_NO_ANDX_COMMAND) {
+		pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
+	}
+	else
+		pr = SmbProcessResultReply;
+done:
+	free(path);
+	free(service);
+	return pr;
+}

+ 10 - 0
sys/src/cmd/aquarela/smbcomtreedisconnect.c

@@ -0,0 +1,10 @@
+#include "headers.h"
+
+SmbProcessResult
+smbcomtreedisconnect(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *)
+{
+	if (!smbcheckwordcount("comtreedisconnect", h, 0))
+		return SmbProcessResultFormat;
+	smbtreedisconnectbyid(s, h->tid);
+	return smbbufferputack(s->response, h, &s->peerinfo);
+}

+ 155 - 0
sys/src/cmd/aquarela/smbcomwrite.c

@@ -0,0 +1,155 @@
+#include "headers.h"
+
+#define INMEMORYTRUNCTHRESH (256 * 1024)
+
+static int
+dirfwstatlength(int fd, vlong offset)
+{
+	Dir d;
+	memset(&d, 0xff, sizeof(d));
+	d.name = d.uid = d.gid = d.muid = nil;
+	d.length = offset;
+	return dirfwstat(fd, &d);
+}
+
+SmbProcessResult
+smbtruncatefile(SmbSession *s, SmbFile *f, vlong offset)
+{
+	Dir *d;
+	ulong o;
+	uchar *db = nil;
+	vlong length;
+	int rv;
+	SmbProcessResult pr;
+
+	d = dirfstat(f->fd);
+	assert(d);
+	length = d->length;
+	free(d);
+
+	if (length == offset)
+		return SmbProcessResultReply;
+
+	rv = dirfwstatlength(f->fd, offset);
+	if (rv == 0) {
+		pr = SmbProcessResultReply;
+		goto done;
+	}
+//smblogprint(-1, "dirfwstatlength failed: %r\n");
+	if (length > offset) {
+		int nfd;
+		char *fullpath;
+		if (offset > INMEMORYTRUNCTHRESH) {
+			smblogprint(-1, "smbcomwrite: truncation beyond %lud not supported\n", offset);
+			pr = SmbProcessResultUnimp;
+			goto done;
+		}
+		db = smbemalloc(offset);
+		if (pread(f->fd, db, offset, 0) != offset) {
+			pr = SmbProcessResultMisc;
+			goto done;
+		}
+		fullpath = nil;
+		smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
+		nfd = open(fullpath, f->p9mode | OTRUNC);
+		free(fullpath);
+		if (nfd < 0) {
+			smbseterror(s, ERRDOS, ERRnoaccess);
+			pr = SmbProcessResultError;
+			goto done;
+		}
+		close(nfd);
+		if (pwrite(f->fd, db, offset, 0) != offset) {
+			pr = SmbProcessResultMisc;
+			goto done;
+		}
+		pr = SmbProcessResultReply;
+	}
+	else {
+		db = smbemalloc(16384);
+		memset(db, 0, 16384);
+		o = length;
+		while (o < offset) {
+			long tt = 16384;
+			if (tt > offset - o)
+				tt = offset - o;
+			if (pwrite(f->fd, db, tt, o) != tt) {
+				smbseterror(s, ERRDOS, ERRnoaccess);
+				pr = SmbProcessResultError;
+				goto done;
+			}
+			o += tt;
+		}
+		pr = SmbProcessResultReply;
+	}
+done:
+	free(db);
+	return pr;
+}
+
+SmbProcessResult
+smbcomwrite(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
+{
+	SmbTree *t;
+	SmbFile *f;
+	ushort fid;
+	ushort count;
+	ulong offset;
+	long nb;
+	ushort yacount;
+	uchar fmt;
+
+	if (h->wordcount != 5)
+		return SmbProcessResultFormat;
+
+	fid = smbnhgets(pdata); pdata += 2;
+	count = smbnhgets(pdata); pdata += 2;
+	offset = smbnhgetl(pdata);
+
+	smblogprint(SMB_COM_WRITE, "smbcomwrite: fid 0x%.4ux count 0x%.4ux offset 0x%.8lux\n",
+		fid, count, offset);
+
+	if (!smbbuffergetb(b, &fmt)
+		|| fmt != 1
+		|| !smbbuffergets(b, &yacount)
+		|| yacount != count
+		|| smbbufferreadspace(b) < count)
+		return SmbProcessResultFormat;
+	
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		return SmbProcessResultError;
+	}
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		return SmbProcessResultError;
+	}
+	
+	if (!f->ioallowed) {
+		smbseterror(s, ERRDOS, ERRbadaccess);
+		return SmbProcessResultError;
+	}
+
+	if (count == 0) {
+		SmbProcessResult pr = smbtruncatefile(s, f, offset);
+		if (pr != SmbProcessResultReply)
+			return pr;
+		nb = 0;
+	}
+	else {
+		seek(f->fd, offset, 0);
+		nb = write(f->fd, smbbufferreadpointer(b), count);
+		if (nb < 0) {
+			smbseterror(s, ERRDOS, ERRnoaccess);
+			return SmbProcessResultError;
+		}
+	}
+	h->wordcount = 1;
+	if (!smbbufferputheader(s->response, h, &s->peerinfo)
+		|| !smbbufferputs(s->response, nb)
+		|| !smbbufferputs(s->response, 0))
+		return SmbProcessResultMisc;
+	return SmbProcessResultReply;
+}

+ 275 - 0
sys/src/cmd/aquarela/smbconnect.c

@@ -0,0 +1,275 @@
+#include "headers.h"
+
+SmbClient *
+smbconnect(char *to, char *share, char **errmsgp)
+{
+	NbSession *nbs;
+	SmbBuffer *b;
+	SmbHeader h, rh;
+	long n;
+	ushort bytecountfixupoffset;
+	ushort andxfixupoffset;
+	uchar *pdata;
+	SmbPeerInfo peerinfo;
+	ushort index;
+	vlong utcintenthsofaus;
+	ulong secssince1970;
+	ushort bytecount;
+	int x;
+	MSchapreply mschapreply;
+	NbName nbto;
+	SmbClient *c;
+	char namebuf[100];
+	ushort ipctid, sharetid;
+
+	nbmknamefromstringandtype(nbto, to, 0x20);
+
+	peerinfo.encryptionkey = nil;
+	peerinfo.oemdomainname = nil;
+	assert(smbglobals.nbname[0] != 0);
+	nbs = nbssconnect(nbto, smbglobals.nbname);
+	if (nbs == nil)
+		return nil;
+print("netbios session established\n");
+	b = smbbuffernew(65535);
+	memset(&h, 0, sizeof(h));
+	h.command = SMB_COM_NEGOTIATE;
+	h.flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_UNICODE;
+	h.wordcount = 0;
+	h.pid = 42;
+	smbbufferputheader(b, &h, &peerinfo);
+	bytecountfixupoffset = smbbufferwriteoffset(b);
+	smbbufferputbytes(b, nil, 2);
+	smbbufferputb(b, 2);
+	smbbufferputstring(b, nil, SMB_STRING_ASCII, "NT LM 0.12");
+	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
+	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	/*
+	 * now receive a reply
+	 */
+	smbbufferreset(b);
+	n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
+	if (n < 0) {
+		smbstringprint(errmsgp, "smbconnect: read error: %r");
+		goto fail;
+	}
+	smbbuffersetreadlen(b, n);
+	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
+		goto fail;
+	if (!smbsuccess(&rh, errmsgp))
+		goto fail;
+	if (rh.wordcount == 0) {
+		smbstringprint(errmsgp, "no parameters in negotiate response");
+		goto fail;
+	}
+	index = smbnhgets(pdata); pdata += 2;
+	if (index != 0) {
+		smbstringprint(errmsgp, "no agreement on protocol");
+		goto fail;
+	}
+	if (rh.wordcount != 17) {
+		smbstringprint(errmsgp, "wrong number of parameters for negotiate response");
+		goto fail;
+	}
+	peerinfo.securitymode = *pdata++;
+	peerinfo.maxmpxcount = smbnhgets(pdata); pdata += 2;
+	peerinfo.maxnumbervcs = smbnhgets(pdata); pdata += 2;
+	peerinfo.maxbuffersize = smbnhgetl(pdata); pdata += 4;
+	peerinfo.maxrawsize = smbnhgetl(pdata); pdata += 4;
+	peerinfo.sessionkey = smbnhgets(pdata); pdata += 4;
+	peerinfo.capabilities = smbnhgets(pdata); pdata += 4;
+	utcintenthsofaus = smbnhgetv(pdata); pdata += 8;
+	secssince1970 = utcintenthsofaus / 10000000 - 11644473600LL;
+	peerinfo.utc =  (vlong)secssince1970 * (vlong)1000000000 + (utcintenthsofaus % 10000000) * 100;
+	peerinfo.tzoff = -smbnhgets(pdata) * 60; pdata += 2;
+	peerinfo.encryptionkeylength = *pdata++;
+	print("securitymode: 0x%.2ux\n", peerinfo.securitymode);
+	print("maxmpxcount: 0x%.4ux\n", peerinfo.maxmpxcount);
+	print("maxnumbervcs: 0x%.4ux\n", peerinfo.maxnumbervcs);
+	print("maxbuffersize: 0x%.8lux\n", peerinfo.maxbuffersize);
+	print("maxrawsize: 0x%.8lux\n", peerinfo.maxrawsize);
+	print("sessionkey: 0x%.8lux\n", peerinfo.sessionkey);
+	print("capabilities: 0x%.8lux\n", peerinfo.capabilities);
+	print("utc: %s(and %lld μs)\n", asctime(gmtime(peerinfo.utc / 1000000000)), peerinfo.utc % 1000000000);
+	print("tzoff: %d\n", peerinfo.tzoff);
+	print("encryptionkeylength: %d\n", peerinfo.encryptionkeylength);
+	smberealloc(&peerinfo.encryptionkey, peerinfo.encryptionkeylength);
+	if (!smbbuffergetbytes(b, peerinfo.encryptionkey, peerinfo.encryptionkeylength)) {
+		smbstringprint(errmsgp, "not enough data for encryption key");
+		goto fail;
+	}
+	print("encryptionkey: ");
+	for (x = 0; x < peerinfo.encryptionkeylength; x++)
+		print("%.2ux", peerinfo.encryptionkey[x]);
+	print("\n");
+	if (!smbbuffergetucs2(b, 0, &peerinfo.oemdomainname)) {
+		smbstringprint(errmsgp, "not enough data for oemdomainname");
+		goto fail;
+	}
+	print("oemdomainname: %s\n", peerinfo.oemdomainname);
+	if (peerinfo.capabilities & CAP_EXTENDED_SECURITY) {
+		smbstringprint(errmsgp, "server wants extended security");
+		goto fail;
+	}
+	/*
+	 * ok - now send SMB_COM_SESSION_SETUP_ANDX
+	 * fix the flags to reflect what the peer can do
+	 */
+	smbbufferreset(b);
+	h.command = SMB_COM_SESSION_SETUP_ANDX;
+	h.wordcount = 13;
+	h.flags2 &= ~SMB_FLAGS2_UNICODE;
+	if (smbsendunicode(&peerinfo))
+		h.flags2 |= SMB_FLAGS2_UNICODE;
+	smbbufferputheader(b, &h, &peerinfo);
+	smbbufferputb(b, SMB_COM_TREE_CONNECT_ANDX);
+	smbbufferputb(b, 0);
+	andxfixupoffset = smbbufferwriteoffset(b);
+	smbbufferputs(b, 0);
+	smbbufferputs(b, 0xffff);
+	smbbufferputs(b, 1);
+	smbbufferputs(b, 0);
+	smbbufferputl(b, peerinfo.sessionkey);
+	smbbufferputs(b, sizeof(mschapreply.LMresp));
+	smbbufferputs(b, sizeof(mschapreply.NTresp));
+	smbbufferputl(b, 0);
+	smbbufferputl(b, CAP_UNICODE | CAP_LARGE_FILES);
+	bytecountfixupoffset = smbbufferwriteoffset(b);
+	smbbufferputs(b, 0);
+	if (auth_respond(peerinfo.encryptionkey, peerinfo.encryptionkeylength,
+		nil, 0,
+		&mschapreply, sizeof(mschapreply), auth_getkey,
+		"proto=mschap role=client server=%s", "cher") != sizeof(mschapreply)) {
+		print("auth_respond failed: %r\n");
+		goto fail;
+	}
+	smbbufferputbytes(b, &mschapreply, sizeof(mschapreply));
+	smbbufferputstring(b, &peerinfo, 0, smbglobals.accountname);
+	smbbufferputstring(b, &peerinfo, 0, smbglobals.primarydomain);
+	smbbufferputstring(b, &peerinfo, 0, smbglobals.nativeos);
+	smbbufferputstring(b, &peerinfo, 0, "");
+	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
+	smbbufferalignl2(b, 2);
+	smbbufferoffsetputs(b, andxfixupoffset, smbbufferwriteoffset(b));
+	smbbufferputb(b, 4);
+	smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
+	smbbufferputb(b, 0);
+	smbbufferputs(b, 0);
+	smbbufferputs(b, 0);
+	smbbufferputs(b, 0);
+	bytecountfixupoffset = smbbufferwriteoffset(b);
+	smbbufferputs(b, 0);
+	strcpy(namebuf, "\\\\");
+	strcat(namebuf, to);
+	strcat(namebuf, "\\IPC$");
+	smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
+	smbbufferputstring(b, nil, SMB_STRING_ASCII, "?????");
+	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
+	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	smbbufferreset(b);
+	n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
+	if (n < 0) {
+		smbstringprint(errmsgp, "read error: %r");
+		goto fail;
+	}
+	smbbuffersetreadlen(b, n);
+	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+	if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
+		goto fail;
+	if (!smbsuccess(&rh, errmsgp))
+		goto fail;
+	h.uid = rh.uid;
+	ipctid = rh.tid;
+	/*
+	 * now do another TREE_CONNECT if needed
+	 */
+	if (share) {
+		smbbufferreset(b);
+		h.command = SMB_COM_TREE_CONNECT_ANDX;
+		h.wordcount = 4;
+		h.tid = 0;
+		smbbufferputheader(b, &h, &peerinfo);
+		smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
+		smbbufferputb(b, 0);
+		smbbufferputs(b, 0);
+		smbbufferputs(b, 0);
+		smbbufferputs(b, 0);
+		bytecountfixupoffset = smbbufferwriteoffset(b);
+		smbbufferputs(b, 0);
+		strcpy(namebuf, "\\\\");
+		strcat(namebuf, to);
+		strcat(namebuf, "\\");
+		strcat(namebuf, share);
+		smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
+		smbbufferputstring(b, nil, SMB_STRING_ASCII, "A:");
+		smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
+		nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+		nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
+		smbbufferreset(b);
+		n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
+		if (n < 0) {
+			smbstringprint(errmsgp, "read error: %r");
+			goto fail;
+		}
+		smbbuffersetreadlen(b, n);
+		nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
+		if (!smbbuffergetandcheckheader(b, &rh, h.command, 3, &pdata, &bytecount, errmsgp))
+			goto fail;
+		if (!smbsuccess(&rh, errmsgp))
+			goto fail;
+		sharetid = rh.tid;
+	}
+	else
+		sharetid = -2;
+	c = smbemalloc(sizeof(*c));
+	c->peerinfo = peerinfo;
+	c->ipctid = ipctid;
+	c->sharetid = sharetid;
+	c->b = b;
+	c->protoh = h;
+	c->nbss = nbs;
+	return c;
+fail:
+	smbbufferfree(&b);
+	free(peerinfo.encryptionkey);
+	free(peerinfo.oemdomainname);
+	return nil;
+}
+
+void
+smbclientfree(SmbClient *c)
+{
+	if (c) {
+		free(c->peerinfo.encryptionkey);
+		free(c->peerinfo.oemdomainname);
+		free(c);
+		smbbufferfree(&c->b);
+	}
+}
+
+int
+smbtransactionclientsend(void *magic, SmbBuffer *ob, char **)
+{
+	SmbClient *c = magic;
+smblogprint(-1, "sending:\n");
+smblogdata(-1, smblogprint, smbbufferreadpointer(ob), smbbufferwriteoffset(ob), 256);
+	return nbsswrite(c->nbss, smbbufferreadpointer(ob), smbbufferwriteoffset(ob)) == 0;
+}
+
+int
+smbtransactionclientreceive(void *magic, SmbBuffer *ib, char **)
+{
+	long n; 
+	SmbClient *c = magic;
+	smbbufferreset(ib);
+	n = nbssread(c->nbss, smbbufferwritepointer(ib), smbbufferwritespace(ib));
+	if (n >= 0) {
+		assert(smbbufferputbytes(ib, nil, n));
+		return 1;
+	}
+	return 0;
+}
+

+ 42 - 0
sys/src/cmd/aquarela/smbconv.c

@@ -0,0 +1,42 @@
+#include "headers.h"
+
+ushort
+smbnhgets(uchar *p)
+{
+	return p[0] | (p[1] << 8);
+}
+
+ulong
+smbnhgetl(uchar *p)
+{
+	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+void
+smbhnputs(uchar *p, ushort v)
+{
+	p[0] = v;
+	p[1] = v >> 8;
+}
+
+void
+smbhnputl(uchar *p, ulong v)
+{
+	p[0] = v;
+	p[1] = v >> 8;
+	p[2] = v >> 16;
+	p[3] = v >> 24;
+}
+
+void
+smbhnputv(uchar *p, vlong v)
+{
+	smbhnputl(p, v);
+	smbhnputl(p + 4, (v >> 32) & 0xffffffff);
+}
+
+vlong
+smbnhgetv(uchar *p)
+{
+	return (vlong)smbnhgetl(p) | ((vlong)smbnhgetl(p + 4) << 32);
+}

+ 325 - 0
sys/src/cmd/aquarela/smbdat.h

@@ -0,0 +1,325 @@
+typedef struct SmbSession SmbSession;
+typedef struct SmbTree SmbTree;
+typedef struct SmbService SmbService;
+typedef struct SmbPeerInfo SmbPeerInfo;
+typedef struct SmbTransaction SmbTransaction;
+typedef struct SmbBuffer SmbBuffer;
+typedef struct SmbIdMap SmbIdMap;
+typedef struct SmbSearch SmbSearch;
+typedef struct SmbDirCache SmbDirCache;
+typedef struct SmbFile SmbFile;
+typedef struct SmbSharedFile SmbSharedFile;
+typedef struct SmbCifsSession SmbCifsSession;
+typedef struct SmbServerInfo SmbServerInfo;
+typedef struct SmbRapServerInfo1 SmbRapServerInfo1;
+typedef struct SmbFindFileBothDirectoryInfo SmbFindFileBothDirectoryInfo;
+typedef struct SmbLock SmbLock;
+typedef struct SmbLockList SmbLockList;
+typedef struct SmbSlut SmbSlut;
+
+#pragma incomplete SmbIdMap
+#pragma incomplete SmbBuffer
+#pragma incomplete SmbLockList
+
+typedef int SMBCIFSWRITEFN(SmbCifsSession *cifs, void *buf, long n);
+typedef int SMBCIFSACCEPTFN(SmbCifsSession *cifs, SMBCIFSWRITEFN **fnp);
+typedef void SMBIDMAPAPPLYFN(void *magic, void *p);
+
+struct SmbPeerInfo {
+	ulong capabilities;
+	ushort maxlen;
+	uchar securitymode;
+	ushort maxmpxcount;
+	ushort maxnumbervcs;
+	ulong maxbuffersize;
+	ulong maxrawsize;
+	ulong sessionkey;
+	vlong utc;
+	short tzoff;
+	uchar encryptionkeylength;
+	uchar *encryptionkey;
+	char *oemdomainname;
+};
+
+struct SmbTransaction {
+	struct {
+		char *name;
+		ulong tpcount;
+		uchar *parameters;
+		ulong pcount;
+		ulong tdcount;
+		uchar *data;
+		ulong maxpcount;
+		ulong maxdcount;
+		ulong maxscount;
+		ulong dcount;
+		ushort scount;
+		ushort *setup;
+		ushort flags;
+	} in;
+	struct {
+		ulong tpcount;
+		ulong tdcount;
+		SmbBuffer *parameters;
+		SmbBuffer *data;
+		ushort *setup;
+	} out;
+};
+
+enum {
+	SmbSessionNeedNegotiate,
+	SmbSessionNeedSetup,
+	SmbSessionEstablished,
+};
+
+struct SmbSession {
+	NbSession *nbss;
+	SmbCifsSession *cifss;
+	uchar nextcommand;
+	SmbBuffer *response;
+	SmbPeerInfo peerinfo;
+	Chalstate *cs;
+	struct {
+		char *accountname;	
+		char *primarydomain;
+		char *nativeos;
+		char *nativelanman;
+		ushort maxmpxcount;
+		MSchapreply mschapreply;
+	} client;
+	SmbTransaction transaction;
+	SmbIdMap *fidmap;
+	SmbIdMap *tidmap;
+	SmbIdMap *sidmap;
+	int state;
+	uchar errclass;
+	ushort error;
+	int tzoff;		// as passed to client during negotiation
+	SmbService *serv;
+};
+
+typedef struct SmbHeader {
+	uchar command;
+	union {
+		struct {
+			uchar errclass;
+			ushort error;
+		};
+		ulong status;
+	};
+	uchar flags;
+	ushort flags2;
+	union {
+		struct {
+			ushort pidhigh;
+			uchar securitysignature[8];
+		};
+	};
+	ushort tid;
+	ushort pid;
+	ushort uid;
+	ushort mid;
+	uchar wordcount;
+} SmbHeader;
+
+typedef enum SmbProcessResult {
+	SmbProcessResultOk,
+	SmbProcessResultUnimp,
+	SmbProcessResultFormat,
+	SmbProcessResultMisc,
+	SmbProcessResultError,
+	SmbProcessResultReply,
+	SmbProcessResultDie,
+} SmbProcessResult;
+
+typedef SmbProcessResult SMBPROCESSFN(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *);
+typedef struct SmbOpTableEntry SmbOpTableEntry;
+struct SmbOpTableEntry {
+	char *name;
+	SMBPROCESSFN *process;
+	int debug;
+};
+
+extern SmbOpTableEntry smboptable[256];
+
+typedef struct SmbGlobals SmbGlobals;
+
+extern SmbGlobals smbglobals;
+
+struct SmbServerInfo {
+	char *name;
+	char *nativelanman;
+	uchar vmaj, vmin;
+	ulong stype;
+	char *remark;
+};
+
+struct SmbGlobals {
+	int maxreceive;
+	int unicode;
+	SmbServerInfo serverinfo;
+	char *nativeos;
+	char *primarydomain;
+	NbName nbname;
+	char *accountname;
+	char *mailslotbrowse;
+	char *pipelanman;
+	int l2sectorsize;
+	int l2allocationsize;
+	int convertspace;
+	struct {
+		int fd;
+		int print;
+		int tids;
+		int sids;
+		int fids;
+		int rap2;
+		int find;
+		int query;
+		int sharedfiles;
+		int sessions;
+		int rep;
+		int poolparanoia;
+		int locks;
+	} log;
+};
+
+struct SmbTree {
+	long id;
+	SmbService *serv;
+};
+
+struct SmbService {
+	Ref;
+	char *name;
+	char *type;
+	ushort stype;
+	char *path;
+	char *remark;
+	SmbService *next;
+};
+
+extern SmbService *smbservices;
+
+typedef struct SmbClient SmbClient;
+
+
+typedef struct SmbTransactionMethod {
+	int (*encodeprimary)(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p,
+		SmbBuffer *ob, uchar *wordcount, ushort *bytecount, char **errmsgp);
+	int (*encodesecondary)(SmbTransaction *t, SmbHeader *h, SmbBuffer *ob, char **errmsgp);
+	int (*sendrequest)(void *magic, SmbBuffer *ob, char **errmsgp);
+	int (*receiveintermediate)(void *magic, uchar *wordcountp, ushort *bytecountp, char **errmsgp);
+	int (*receiveresponse)(void *magic, SmbBuffer *ib, char **errmsgp);
+	int (*decoderesponse)(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp);
+	int (*encoderesponse)(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p,
+		SmbBuffer *ob, char **errmsgp);
+	int (*sendresponse)(void *magic, SmbBuffer *ob, char **errmsgp);
+} SmbTransactionMethod;
+
+extern SmbTransactionMethod smbtransactionmethoddgram;
+
+struct SmbSearch {
+	long id;
+	SmbTree *t;
+	SmbDirCache *dc;
+	Reprog *rep;
+	ushort tid;
+};
+
+struct SmbFile {
+	long id;
+	SmbTree *t;		// tree this belongs to
+	int fd;
+	char *name;
+	int p9mode;		// how it was opened
+	int share;			// additional sharing restictions added by this fid
+	int ioallowed;
+	SmbSharedFile *sf;
+};
+
+struct SmbSharedFile {
+	ushort type;
+	ulong dev;
+	vlong path;
+//	char *name;
+	int share;			// current share level
+	int deleteonclose;
+	SmbLockList *locklist;
+};
+
+struct SmbLock {
+	vlong base;
+	vlong limit;
+	SmbSession *s;		// owning session
+	ushort pid;		// owning pid
+};
+
+struct SmbCifsSession {
+	int fd;
+	void *magic;
+};
+
+struct SmbClient {
+	SmbPeerInfo peerinfo;
+	NbSession *nbss;
+	SmbBuffer *b;
+	ushort ipctid;
+	ushort sharetid;
+	SmbHeader protoh;
+};
+
+struct SmbRapServerInfo1 {
+	char name[16];
+	uchar vmaj;
+	uchar vmin;
+	ulong type;
+	char *remark;
+};
+
+struct SmbFindFileBothDirectoryInfo {
+	ulong fileindex;
+	vlong creationtime;
+	vlong lastaccesstime;
+	vlong lastwritetime;
+	vlong changetime;
+	vlong endoffile;
+	vlong allocationsize;
+	ulong extfileattributes;
+	char *filename;
+};
+
+enum {
+	SMB_STRING_UNALIGNED = 1,
+	SMB_STRING_UPCASE = 2,
+	SMB_STRING_UNTERMINATED = 4,
+	SMB_STRING_UNICODE = 8,
+	SMB_STRING_ASCII = 16,
+	SMB_STRING_REVPATH = 32,
+	SMB_STRING_PATH = 64,
+	SMB_STRING_CONVERT_MASK = SMB_STRING_PATH | SMB_STRING_REVPATH | SMB_STRING_UPCASE,
+};
+
+struct SmbDirCache {
+	Dir *buf;
+	long n;
+	long i;
+};
+
+typedef struct SmbTrans2OpTableEntry SmbTrans2OpTableEntry;
+typedef SmbProcessResult SMBTRANS2PROCESSFN(SmbSession *s, SmbHeader *h);
+struct SmbTrans2OpTableEntry {
+	char *name;
+	SMBTRANS2PROCESSFN *process;
+	int debug;
+};
+extern SmbTrans2OpTableEntry smbtrans2optable[];
+extern int smbtrans2optablesize;
+
+struct SmbSlut {
+	char *name;
+	int val;
+};
+
+extern SmbSlut smbopenmodeslut[];
+extern SmbSlut smbsharemodeslut[];

+ 43 - 0
sys/src/cmd/aquarela/smbdircache.c

@@ -0,0 +1,43 @@
+#include "headers.h"
+
+SmbDirCache *
+smbmkdircache(SmbTree *t, char *path)
+{
+	long n;
+	SmbDirCache *c;
+	Dir *buf;
+	int fd;
+	char *fullpath = nil;
+
+	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
+//smblogprintif(1, "smbmkdircache: path %s\n", fullpath);
+	fd = open(fullpath, OREAD);
+	free(fullpath);
+
+	if (fd < 0)
+		return nil;
+	n = dirreadall(fd, &buf);
+	close(fd);
+	if (n < 0) {
+		free(buf);
+		return nil;
+	}
+	c = smbemalloc(sizeof(SmbDirCache));
+	c->buf = buf;
+	c->n = n;
+	c->i = 0;
+	return c;
+}
+
+void
+smbdircachefree(SmbDirCache **cp)
+{
+	SmbDirCache *c;
+	c = *cp;
+	if (c) {
+		free(c->buf);
+		free(c);
+		*cp = nil;
+	}
+}
+

+ 25 - 0
sys/src/cmd/aquarela/smbfile.c

@@ -0,0 +1,25 @@
+#include "headers.h"
+
+static void
+smbfilefree(SmbFile **fp)
+{
+	SmbFile *f;
+	f = *fp;
+	if (f) {
+		smbsharedfileput(f, f->sf, f->share);
+		if (f->fd >= 0)
+			close(f->fd);
+		free(f->name);
+		free(f);
+		*fp = nil;
+	}
+}
+
+void
+smbfileclose(SmbSession *s, SmbFile *f)
+{
+	smblogprintif(smbglobals.log.fids, "smbfileclose: 0x%.4ux/0x%.4ux %s%s\n",
+		f->t->id, f->id, f->t->serv->path, f->name);
+	smbidmapremove(s->fidmap, f);
+	smbfilefree(&f);
+}

+ 256 - 0
sys/src/cmd/aquarela/smbfns.h

@@ -0,0 +1,256 @@
+ushort smbnhgets(uchar *);
+ulong smbnhgetl(uchar *);
+vlong smbnhgetv(uchar *);
+void smbhnputs(uchar *, ushort);
+void smbhnputl(uchar *, ulong);
+void smbhnputv(uchar *, vlong);
+
+SMBPROCESSFN smbnegotiate;
+SMBPROCESSFN smbcomsessionsetupandx;
+SMBPROCESSFN smbcomtreeconnectandx;
+SMBPROCESSFN smbcomtransaction;
+SMBPROCESSFN smbcomcheckdirectory;
+SMBPROCESSFN smbcomtransaction2;
+SMBPROCESSFN smbcomecho;
+SMBPROCESSFN smbcomopenandx;
+SMBPROCESSFN smbcomopen;
+SMBPROCESSFN smbcomclose;
+SMBPROCESSFN smbcomreadandx;
+SMBPROCESSFN smbcomqueryinformation;
+SMBPROCESSFN smbcomfindclose2;
+SMBPROCESSFN smbcomtreedisconnect;
+SMBPROCESSFN smbcomqueryinformation2;
+SMBPROCESSFN smbcomdelete;
+SMBPROCESSFN smbcomflush;
+SMBPROCESSFN smbcomwrite;
+SMBPROCESSFN smbcomsetinformation2;
+SMBPROCESSFN smbcomcreatedirectory;
+SMBPROCESSFN smbcomdeletedirectory;
+SMBPROCESSFN smbcomrename;
+SMBPROCESSFN smbcomlockingandx;
+SMBPROCESSFN smbcomsetinformation;
+SMBPROCESSFN smbcomntcreateandx;
+
+void *smbemalloc(ulong size);
+void *smbemallocz(ulong size, int clear);
+void smberealloc(void **pp, ulong size);
+char *smbestrdup(char *s);
+void smbfree(void **pp);
+
+int smbcheckwordcount(char *name, SmbHeader *h, ushort wordcount);
+int smbcheckwordandbytecount(char *name, SmbHeader *h, ushort wordcount, uchar **bdatap, uchar **edatap);
+int smbsendunicode(SmbPeerInfo *i);
+
+char *smbstringdup(SmbHeader *h, uchar *base, uchar **bdatap, uchar *edata);
+char *smbstrdup(uchar **bdatap, uchar *edata);
+char *smbstrinline(uchar **bdatap, uchar *edata);
+int smbstrlen(char *string);
+int smbstringlen(SmbPeerInfo *i, char *string);
+void smbstringprint(char **p, char *fmt, ...);
+
+int smbucs2len(char *string);
+int smbstringput(SmbPeerInfo *p, ulong flags, uchar *buf, ushort n, ushort maxlen, char *string);
+int smbstrput(ulong flags, uchar *buf, ushort n, ushort maxlen, char *string);
+int smbstrnput(uchar *buf, ushort n, ushort maxlen, char *string, ushort size, int upcase);
+int smbucs2put(ulong flags, uchar *buf, ushort n, ushort maxlen, char *string);
+
+void smbresponseinit(SmbSession *s, ushort maxlen);
+int smbresponsealignl2(SmbSession *s, int l2a);
+ushort smbresponseoffset(SmbSession *s);
+int smbresponseputheader(SmbSession *s, SmbHeader *h, uchar errclass, ushort error);
+int smbresponseputandxheader(SmbSession *s, SmbHeader *h, ushort andxcommand, ulong *andxoffsetfixup);
+int smbresponseputb(SmbSession *s, uchar b);
+int smbresponseputs(SmbSession *s, ushort s);
+int smbresponseputl(SmbSession *s, ulong l);
+int smbresponseoffsetputs(SmbSession *s, ushort offset, ushort s);
+int smbresponseputstring(SmbSession *s, int mustalign, char *string);
+int smbresponseputstr(SmbSession *s, char *string);
+SmbProcessResult smbresponsesend(SmbSession *s);
+int smbresponseputerror(SmbSession *s, SmbHeader *h, uchar errclass, ushort error);
+int smbresponseskip(SmbSession *s, ushort amount);
+ushort smbresponsespace(SmbSession *s);
+void smbresponsereset(SmbSession *s);
+int smbresponsecpy(SmbSession *s, uchar *data, ushort datalen);
+
+void smbtreedisconnect(SmbSession *s, SmbTree *t);
+void smbtreedisconnectbyid(SmbSession *s, ushort id);
+SmbTree *smbtreeconnect(SmbSession *s, SmbService *serv);
+int smbchaincommand(SmbSession *s, SmbHeader *h, ulong andxfixupoffset, uchar cmd, ushort offset, SmbBuffer *b);
+
+SmbService *smbservicefind(SmbSession *s, char *path, char *service, uchar *errclassp, ushort *errorp);
+void smbserviceput(SmbService *serv);
+void smbserviceget(SmbService *serv);
+
+int smbrap2(SmbSession *s);
+
+void smbglobalsguess(int client);
+
+SmbBuffer *smbbuffernew(ulong maxlen);
+void smbbufferfree(SmbBuffer **bp);
+SmbBuffer *smbbufferinit(void *base, void *bdata, ulong blen);
+ulong smbbufferwriteoffset(SmbBuffer *s);
+ulong smbbufferwritemaxoffset(SmbBuffer *s);
+ulong smbbufferreadoffset(SmbBuffer *s);
+void *smbbufferwritepointer(SmbBuffer *s);
+void *smbbufferreadpointer(SmbBuffer *s);
+int smbbufferputheader(SmbBuffer *s, SmbHeader *h, SmbPeerInfo *p);
+int smbbufferputandxheader(SmbBuffer *s, SmbHeader *h, SmbPeerInfo *p, uchar andxcommand, ulong *andxoffsetfixup);
+int smbbufferputb(SmbBuffer *s, uchar b);
+int smbbufferputs(SmbBuffer *s, ushort s);
+int smbbufferputl(SmbBuffer *s, ulong l);
+int smbbufferoffsetputs(SmbBuffer *s, ulong offset, ushort s);
+int smbbufferputstring(SmbBuffer *b, SmbPeerInfo *p, ulong flags, char *string);
+int smbbufferpututstring(SmbBuffer *b, SmbPeerInfo *p, int mustalign, char *string);
+int smbbufferputucs2(SmbBuffer *b, int mustalign, char *string);
+int smbbufferputstr(SmbBuffer *s, char *string);
+int smbbufferputstrn(SmbBuffer *s, char *string, int len, int upcase);
+int smbbufferputerror(SmbBuffer *s, SmbHeader *h, SmbPeerInfo *p, uchar errclass, ushort error);
+int smbbufferskip(SmbBuffer *s, ulong amount);
+ulong smbbufferspace(SmbBuffer *s);
+void smbbufferreset(SmbBuffer *s);
+int smbbufferputbytes(SmbBuffer *s, void *data, ulong datalen);
+int smbbuffergetbytes(SmbBuffer *b, void *buf, ulong len);
+void smbbuffersetreadlen(SmbBuffer *b, ulong len);
+int smbbuffertrimreadlen(SmbBuffer *b, ulong len);
+ulong smbbufferwritespace(SmbBuffer *b);
+int smbbuffergets(SmbBuffer *b, ushort *sp);
+int smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp);
+int smbbuffergetstrinline(SmbBuffer *b, char **sp);
+int smbbuffergetstrn(SmbBuffer *b, ushort size, char **sp);
+int smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp);
+int smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp);
+void *smbbufferpointer(SmbBuffer *b, ulong offset);
+int smbbuffergetb(SmbBuffer *b, uchar *bp);
+int smbbuffergetl(SmbBuffer *b, ulong *lp);
+int smbbuffergetv(SmbBuffer *b, vlong *vp);
+ulong smbbufferreadspace(SmbBuffer *b);
+void smbbufferwritelimit(SmbBuffer *b, ulong limit);
+int smbbufferreadskipto(SmbBuffer *b, ulong offset);
+int smbbufferpushreadlimit(SmbBuffer *b, ulong offset);
+int smbbufferpopreadlimit(SmbBuffer *b);
+int smbbufferalignl2(SmbBuffer *b, int al2);
+int smbbufferwritebackup(SmbBuffer *b, ulong offset);
+int smbbufferreadbackup(SmbBuffer *b, ulong offset);
+int smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset);
+int smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset);
+int smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset);
+int smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset);
+int smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset);
+int smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong val);
+int smbbufferputv(SmbBuffer *b, vlong v);
+int smbbufferputack(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p);
+int smbbufferfill(SmbBuffer *b, uchar c, ulong len);
+int smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp);
+int smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount);
+int smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp);
+
+SmbClient *smbconnect(char *to, char *share, char **errmsgp);
+void smbclientfree(SmbClient *s);
+int smbsuccess(SmbHeader *h, char **errmsgp);
+
+int smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp);
+int smbtransactiondecodeprimary2(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp);
+void smbtransactionfree(SmbTransaction *t);
+int smbtransactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, char **errmsgp);
+int smbtransactionencoderesponse2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, char **errmsgp);
+int smbtransactionencodeprimary(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	uchar *wordcountp, ushort *bytecountp, char **errmsgp);
+int smbtransactionencodeprimary2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	uchar *wordcountp, ushort *bytecountp, char **errmsgp);
+int smbtransactiondecoderesponse(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp);
+int smbtransactiondecoderesponse2(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp);
+int smbtransactionclientsend(void *magic, SmbBuffer *ob, char **errmsgp);
+int smbtransactionclientreceive(void *magic, SmbBuffer *ib, char **errmsgp);
+
+int smbtransactionexecute(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p,
+	SmbBuffer *ob, SmbTransactionMethod *method, void *magic, SmbHeader *rh, char **errmsgp);
+int smbtransactionrespond(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	SmbTransactionMethod *method, void *magic, char **errmsgp);
+
+SmbProcessResult smbtrans2findfirst2(SmbSession *s, SmbHeader *h);
+SmbProcessResult smbtrans2findnext2(SmbSession *s, SmbHeader *h);
+SmbProcessResult smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h);
+SmbProcessResult smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h);
+SmbProcessResult smbtrans2querypathinformation(SmbSession *s, SmbHeader *h);
+SmbProcessResult smbtrans2setfileinformation(SmbSession *s, SmbHeader *h);
+
+SmbIdMap *smbidmapnew(void);
+long smbidmapadd(SmbIdMap *m, void *p);
+void smbidmapremovebyid(SmbIdMap *m, long id);
+void smbidmapremove(SmbIdMap *m, void *thing);
+void smbidmapfree(SmbIdMap **mp, SMBIDMAPAPPLYFN *free, void *magic);
+void smbidmapapply(SmbIdMap *mp, SMBIDMAPAPPLYFN *free, void *magic);
+void *smbidmapfind(SmbIdMap *m, long id);
+void smbidmapremoveif(SmbIdMap *m, int (*f)(void *p, void *arg), void *arg);
+
+void smbsearchfree(SmbSearch **searchp);
+void smbsearchclose(SmbSession *s, SmbSearch *search);
+void smbsearchclosebyid(SmbSession *s, ushort sid);
+
+void smbseterror(SmbSession *s, uchar errclass, ushort error);
+
+void smbplan9time2datetime(ulong time, int tzoff, ushort *datep, ushort *timep);
+ulong smbdatetime2plan9time(ushort date, ushort time, int tzoff);
+vlong smbplan9time2time(ulong time);
+ulong smbplan9time2utime(ulong time, int tzoff);
+ulong smbutime2plan9time(ulong time, int tzoff);
+ulong smbtime2plan9time(vlong);
+void smbpathcanon(char *path);
+void smbpathsplit(char *path, char **dirp, char **namep);
+
+ushort smbplan9mode2dosattr(ulong mode);
+ulong smbdosattr2plan9wstatmode(ulong oldmode, ushort attr);
+ulong smbdosattr2plan9mode(ushort attr);
+
+ulong smbplan9length2size32(vlong size);
+
+void smbfileclose(SmbSession *s, SmbFile *f);
+
+void smbloglock(void);
+void smblogunlock(void);
+int smblogvprint(int cmd, char *fmt, va_list ap);
+int smblogprint(int cmd, char *fmt, ...);
+int smblogprintif(int v, char *fmt, ...);
+void smblogdata(int cmd, int (*print)(int cmd, char *fmt, ...), void *p, long data, long limit);
+
+SmbSharedFile *smbsharedfileget(Dir *d, int p9mode, int *sharep);
+void smbsharedfileput(SmbFile *f, SmbSharedFile *sf, int share);
+int smbsharedfilelock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit);
+int smbsharedfileunlock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit);
+
+vlong smbl2roundupvlong(vlong v, int l2);
+
+int smblistencifs(SMBCIFSACCEPTFN *accept);
+
+int smbnetserverenum2(SmbClient *c, ulong stype, char *domain, int *entriesp, SmbRapServerInfo1 **sip, char **errmsgp);
+
+int smbbuffergetheader(SmbBuffer *b, SmbHeader *h, uchar **parametersp, ushort *bytecountp);
+int smbbuffergetandcheckheader(SmbBuffer *b, SmbHeader *h, uchar command, int response,
+	uchar **pdatap, ushort *bytecountp, char **errmsgp);
+int smbcheckheader(SmbHeader *h, uchar command, int response, char **errmsgp);
+int smbcheckheaderdirection(SmbHeader *h, int response, char **errmsgp);
+
+SmbDirCache *smbmkdircache(SmbTree *t, char *path);
+void smbdircachefree(SmbDirCache **cp);
+
+int smbmatch(char *name, Reprog *rep);
+Reprog *smbmkrep(char *pattern);
+
+int smbclientopen(SmbClient *c, ushort mode, char *name, uchar *errclassp, ushort *errorp, ushort *fid, ushort *attrp,
+ulong *mtimep, ulong *sizep, ushort *accessallowedp, char **errmsgp);
+
+Rune smbruneconvert(Rune r, ulong flags);
+
+int smbslut(SmbSlut *table, char *name);
+char *smbrevslut(SmbSlut *table, int val);
+
+SmbProcessResult smbtruncatefile(SmbSession *s, SmbFile *f, vlong offset);
+
+#ifdef LEAK
+#define smbemallocz(n, z) mallocz(n, z)
+#define smbemalloc(n) malloc(n)
+#define smbestrdup(p) strcpy(malloc(strlen(p) + 1), p)
+#endif
+
+int smbremovefile(SmbTree *t, char *dir, char *name);
+int smbbrowsesendhostannouncement(char *name, ulong periodms, ulong type, char *comment, char **errmsgp);

+ 43 - 0
sys/src/cmd/aquarela/smbglobals.c

@@ -0,0 +1,43 @@
+#include "headers.h"
+
+SmbGlobals smbglobals = {
+	.maxreceive = 0x1ffff,
+	.unicode = 1,
+	.nativeos = "Plan 9 4th edition",
+	.serverinfo = {
+		.nativelanman = "Aquarela",
+		.vmaj = 0,
+		.vmin = 5,
+		.stype = SV_TYPE_SERVER,
+	},
+	.mailslotbrowse = "/MAILSLOT/BROWSE",
+	.pipelanman = "/PIPE/LANMAN",
+	.l2sectorsize = 9,
+	.l2allocationsize = 14,
+	.convertspace = 1,
+	.log = {
+		.fd = -1,
+		.print = 0,
+		.poolparanoia = 1,
+	},
+};
+
+void
+smbglobalsguess(int client)
+{
+	if (smbglobals.serverinfo.name == 0)
+		smbglobals.serverinfo.name = sysname();
+	if (smbglobals.nbname[0] == 0)
+		nbmknamefromstring(smbglobals.nbname, smbglobals.serverinfo.name);
+	if (smbglobals.accountname == nil)
+		smbglobals.accountname = strdup(getuser());
+	if (smbglobals.primarydomain == nil)
+		smbglobals.primarydomain = "PLAN9";
+	if (smbglobals.serverinfo.remark == nil)
+		smbglobals.serverinfo.remark = "This is a default server comment";
+	if (smbglobals.log.fd < 0)
+		if (client)
+			smbglobals.log.fd = create("client.log", OWRITE|OTRUNC, 0666);
+		else
+			smbglobals.log.fd = create("aquarela.log", OWRITE|OTRUNC, 0666);
+}

+ 128 - 0
sys/src/cmd/aquarela/smbidmap.c

@@ -0,0 +1,128 @@
+#include "headers.h"
+
+#define INITIALCHUNKSIZE 10
+
+typedef struct Entry {
+	void *p;
+	long freechain;
+} Entry;
+
+struct SmbIdMap {
+	Entry *array;
+	ulong entries;
+	long freeindex;
+};
+
+SmbIdMap *
+smbidmapnew(void)
+{
+	SmbIdMap *m;
+	m = smbemallocz(sizeof(SmbIdMap), 1);
+	m->freeindex = -1;
+	return m;
+}
+
+void
+smbidmapremovebyid(SmbIdMap *m, long id)
+{
+	if (m == nil)
+		return;
+	assert(id > 0);
+	id--;
+	assert(id >= 0 && id < m->entries);
+	assert(m->array[id].freechain == -2);
+	m->array[id].freechain = m->freeindex;
+	m->freeindex = id;
+}
+
+void
+smbidmapremove(SmbIdMap *m, void *thing)
+{
+	long id;
+	if (m == nil)
+		return;
+	id = *(long *)thing;
+	smbidmapremovebyid(m, id);
+}
+
+void
+smbidmapremoveif(SmbIdMap *m, int (*f)(void *p, void *arg), void *arg)
+{
+	int i;
+	if (m == nil)
+		return;
+	for (i = 0; i < m->entries; i++)
+		if (m->array[i].freechain == -2 && (*f)(m->array[i].p, arg))
+			smbidmapremovebyid(m, i + 1);
+}
+
+static void
+grow(SmbIdMap *m)
+{
+	long x;
+	long oldentries = m->entries;
+	if (m->entries == 0)
+		m->entries = INITIALCHUNKSIZE;
+	else
+		m->entries *= 2;
+	smberealloc(&m->array, sizeof(Entry) * m->entries);
+	for (x = m->entries - 1; x >= oldentries; x--) {
+		m->array[x].freechain = m->freeindex;
+		m->freeindex = x;
+	}
+}
+
+long
+smbidmapadd(SmbIdMap *m, void *p)
+{
+	long i;
+	if (m->freeindex < 0)
+		grow(m);
+	i = m->freeindex;
+	m->freeindex = m->array[i].freechain;
+	m->array[i].freechain = -2;
+	m->array[i].p = p;
+	*(long *)p = i + 1;
+	return i + 1;
+}
+
+void *
+smbidmapfind(SmbIdMap *m, long id)
+{
+	if (m == nil)
+		return nil;
+	if (id <= 0)
+		return nil;
+	id--;
+	if (id < 0 || id > m->entries || m->array[id].freechain != -2)
+		return nil;
+	return m->array[id].p;
+}
+
+void
+smbidmapfree(SmbIdMap **mp, SMBIDMAPAPPLYFN *freefn, void *magic)
+{
+	SmbIdMap *m = *mp;
+	if (m) {
+		long i;
+		if (freefn) {
+			for (i = 0; i < m->entries; i++)
+				if (m->array[i].freechain == -2)
+					(*freefn)(magic, m->array[i].p);
+		}
+		free(m->array);
+		free(m);
+		*mp = nil;
+	}
+}
+
+void
+smbidmapapply(SmbIdMap *m, SMBIDMAPAPPLYFN *applyfn, void *magic)
+{
+	if (m) {
+		long i;
+		for (i = 0; i < m->entries; i++)
+			if (m->array[i].freechain == -2)
+				(*applyfn)(magic, m->array[i].p);
+	}
+}

+ 155 - 0
sys/src/cmd/aquarela/smblisten.c

@@ -0,0 +1,155 @@
+#include "headers.h"
+
+static struct {
+	int thread;
+	QLock;
+	char adir[NETPATHLEN];
+	int acfd;
+	char ldir[NETPATHLEN];
+	int lcfd;
+	SMBCIFSACCEPTFN *accept;
+} tcp = { -1 };
+
+typedef struct Session Session;
+
+enum { Connected, Dead };
+
+struct Session {
+	SmbCifsSession;
+	int thread;
+	Session *next;
+	int state;
+	SMBCIFSWRITEFN *write;
+};
+
+static struct {
+	QLock;
+	Session *head;
+} sessions;
+
+typedef struct Listen Listen;
+
+static void
+deletesession(Session *s)
+{
+	Session **sp;
+	close(s->fd);
+	qlock(&sessions);
+	for (sp = &sessions.head; *sp && *sp != s; sp = &(*sp)->next)
+		;
+	if (*sp)
+		*sp = s->next;
+	qunlock(&sessions);
+	free(s);
+}
+
+static void
+tcpreader(void *a)
+{
+	Session *s = a;
+	uchar *buf;
+	int buflen = smbglobals.maxreceive + 4;
+	buf = nbemalloc(buflen);
+	for (;;) {
+		int n;
+		uchar flags;
+		ushort length;
+
+		n = readn(s->fd, buf, 4);
+		if (n != 4) {
+		die:
+			free(buf);
+			if (s->state == Connected)
+				(*s->write)(s, nil, -1);
+			deletesession(s);
+			return;
+		}
+		flags = buf[1];
+		length = nhgets(buf + 2) | ((flags & 1) << 16);
+		if (length > buflen - 4) {
+			print("nbss: too much data (%ud)\n", length);
+			goto die;
+		}
+		n = readn(s->fd, buf + 4, length);
+		if (n != length)
+			goto die;
+		if (s->state == Connected) {
+			if ((*s->write)(s, buf + 4, length) != 0) {
+				s->state = Dead;
+				goto die;
+			}
+		}
+	}
+}
+
+static Session *
+createsession(int fd)
+{
+	Session *s;
+	s = smbemalloc(sizeof(Session));
+	s->fd = fd;
+	s->state = Connected;
+	qlock(&sessions);
+	if (!(*tcp.accept)(s, &s->write)) {
+		qunlock(&sessions);
+		free(s);
+		return nil;
+	}
+	s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
+	if (s->thread < 0) {
+		qunlock(&sessions);
+		(*s->write)(s, nil, -1);
+		free(s);
+		return nil;
+	}
+	s->next = sessions.head;
+	sessions.head = s;
+	qunlock(&sessions);
+	return s;
+}
+
+static void
+tcplistener(void *)
+{
+	for (;;) {
+		int dfd;
+		char ldir[NETPATHLEN];
+		int lcfd;
+//print("cifstcplistener: listening\n");
+		lcfd = listen(tcp.adir, ldir);
+//print("cifstcplistener: contact\n");
+		if (lcfd < 0) {
+		die:
+			qlock(&tcp);
+			close(tcp.acfd);
+			tcp.thread = -1;
+			qunlock(&tcp);
+			return;
+		}
+		dfd = accept(lcfd, ldir);
+		close(lcfd);
+		if (dfd < 0)
+			goto die;
+		if (createsession(dfd) == nil)
+			close(dfd);
+	}
+}
+
+int
+smblistencifs(SMBCIFSACCEPTFN *accept)
+{
+	qlock(&tcp);
+	if (tcp.thread < 0) {
+		tcp.acfd = announce("tcp!*!cifs", tcp.adir);
+		if (tcp.acfd < 0) {
+			print("smblistentcp: can't announce: %r\n");
+			qunlock(&tcp);
+			return -1;
+		}
+		tcp.thread = proccreate(tcplistener, nil, 16384);
+	}
+	tcp.accept = accept;
+	qunlock(&tcp);
+	return 0;
+}
+	

+ 107 - 0
sys/src/cmd/aquarela/smblog.c

@@ -0,0 +1,107 @@
+#include "headers.h"
+
+static QLock logreflock, logprintlock;
+static int locked;
+
+void
+smbloglock(void)
+{
+	qlock(&logreflock);
+	if (locked++ == 0)
+		qlock(&logprintlock);
+	qunlock(&logreflock);
+}
+
+void
+smblogunlock(void)
+{
+	qlock(&logreflock);
+	if (locked && --locked == 0)
+		qunlock(&logprintlock);
+	qunlock(&logreflock);
+}
+
+static int
+smbloglockedvprint(char *fmt, va_list ap)
+{
+	if (smbglobals.log.fd >= 0)
+		vfprint(smbglobals.log.fd, fmt, ap);
+	if (smbglobals.log.print)
+		vfprint(2, fmt, ap);
+	return 0;
+}
+
+int
+smblogvprint(int cmd, char *fmt, va_list ap)
+{
+	if (cmd < 0 || smboptable[cmd].debug) {
+		smbloglock();
+		smbloglockedvprint(fmt, ap);
+		smblogunlock();
+	}
+	return 0;
+}
+
+int
+smblogprint(int cmd, char *fmt, ...)
+{
+	if (cmd < 0 || smboptable[cmd].debug) {
+		va_list ap;
+		va_start(ap, fmt);
+		smblogvprint(cmd, fmt, ap);
+		va_end(ap);
+	}
+	return 0;
+}
+
+int
+smblogprintif(int v, char *fmt, ...)
+{
+	if (v) {
+		va_list ap;
+		va_start(ap, fmt);
+		smbloglock();
+		smbloglockedvprint(fmt, ap);
+		smblogunlock();
+		va_end(ap);
+	}
+	return 0;
+}
+
+void
+smblogdata(int cmd, int (*print)(int cmd, char *fmt, ...), void *ap, long n, long limit)
+{
+	uchar *p = ap;
+	long i;
+	long saven;
+	i = 0;
+	saven = n;
+	if (saven > limit)
+		n = limit;
+	while (i < n) {
+		int l = n - i < 16 ? n - i : 16;
+		int b;
+		(*print)(cmd, "0x%.4lux  ", i);
+		for (b = 0; b < l; b += 2) {
+			(*print)(cmd, " %.2ux", p[i + b]);
+			if (b < l - 1)
+				(*print)(cmd, "%.2ux", p[i + b + 1]);
+			else
+				(*print)(cmd, "  ");
+		}
+		while (b < 16) {
+			(*print)(cmd, "     ");
+			b += 2;
+		}
+		(*print)(cmd, "        ");
+		for (b = 0; b < l; b++)
+			if (p[i + b] >= ' ' && p[i + b] <= '~')
+				(*print)(cmd, "%c", p[i + b]);
+			else
+				(*print)(cmd, ".");
+		(*print)(cmd, "\n");
+		i += l;
+	}
+	if (saven > limit)
+		(*print)(cmd, "0x%.4ux   ...\n0x%.4ux\n", limit, saven);
+}

+ 89 - 0
sys/src/cmd/aquarela/smbnegotiate.c

@@ -0,0 +1,89 @@
+#include "headers.h"
+
+SmbProcessResult
+smbnegotiate(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
+{
+	ushort index;
+	int i;
+	uchar bufferformat;
+
+	if (!smbcheckwordcount("negotiate", h, 0))
+		return SmbProcessResultFormat;
+	if (s->state != SmbSessionNeedNegotiate) {
+		/* this acts as a complete session reset */
+		smblogprint(-1, "smbnegotiate: called when already negotiated\n");
+		return SmbProcessResultUnimp;
+	}
+	i = 0;
+	index = 0xffff;
+	while (smbbuffergetb(b, &bufferformat)) {
+		char *s;
+		if (bufferformat != 0x02) {
+			smblogprint(-1, "smbnegotiate: unrecognised buffer format 0x%.2ux\n", bufferformat);
+			return SmbProcessResultFormat;
+		}
+		if (!smbbuffergetstr(b, 0, &s)) {
+			smblogprint(-1, "smbnegotiate: no null found\n");
+			return SmbProcessResultFormat;
+		}
+		smblogprint(h->command, "smbnegotiate: '%s'\n", s);
+		if (index == 0xffff && strcmp(s, "NT LM 0.12") == 0)
+			index = i;
+		i++;
+		free(s);
+	}
+	if (index != 0xffff) {
+		Tm *tm;
+		ulong capabilities;
+		ulong bytecountfixupoffset;
+
+		h->wordcount = 17;
+		if (!smbbufferputheader(s->response, h, nil)
+			|| !smbbufferputs(s->response, index)
+			|| !smbbufferputb(s->response, 3)			/* user security, encrypted */
+			|| !smbbufferputs(s->response, 1)			/* max mux */
+			|| !smbbufferputs(s->response, 1)			/* max vc */
+			|| !smbbufferputl(s->response, smbglobals.maxreceive)		/* max buffer size */
+			|| !smbbufferputl(s->response, 0x10000)		/* max raw */
+			|| !smbbufferputl(s->response, threadid()))	/* session key */
+			goto die;
+		/* <= Win2k insist upon this being set to ensure that they observe the prototol (!) */
+		capabilities = CAP_NT_SMBS;
+		if (smbglobals.unicode)
+			capabilities |= CAP_UNICODE;
+		tm = localtime(time(nil));
+		s->tzoff = tm->tzoff;
+		if (!smbbufferputl(s->response, capabilities)
+			|| !smbbufferputv(s->response, nsec() / 100 + (vlong)10000000 * 11644473600LL)
+			|| !smbbufferputs(s->response, -s->tzoff / 60)
+			|| !smbbufferputb(s->response, 8))	/* crypt len */
+			goto die;
+		bytecountfixupoffset = smbbufferwriteoffset(s->response);
+		if (!smbbufferputs(s->response, 0))
+			goto die;
+		s->cs = auth_challenge("proto=mschap role=server");
+		if (s->cs == nil) {
+			smblogprint(h->command, "smbnegotiate: couldn't get mschap challenge\n");
+			return SmbProcessResultMisc;
+		}
+		if (s->cs->nchal != 8) {
+			smblogprint(h->command, "smbnegotiate: nchal %d\n", s->cs->nchal);
+			return SmbProcessResultMisc;
+		}
+		if (!smbbufferputbytes(s->response, s->cs->chal, s->cs->nchal)
+			|| !smbbufferputstring(s->response, nil, SMB_STRING_UNICODE, smbglobals.primarydomain)
+			|| !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
+			goto die;
+	}
+	else {
+		h->wordcount = 1;
+		if (!smbbufferputheader(s->response, h, nil)
+			|| !smbbufferputs(s->response, index)
+			|| !smbbufferputs(s->response, 0))
+			goto die;
+	}
+	s->state = SmbSessionNeedSetup;
+	return SmbProcessResultReply;
+die:
+	return SmbProcessResultDie;
+}

+ 98 - 0
sys/src/cmd/aquarela/smboptable.c

@@ -0,0 +1,98 @@
+#include "headers.h"
+
+SmbOpTableEntry smboptable[256] = {
+[SMB_COM_CREATE_DIRECTORY] { "SMB_COM_CREATE_DIRECTORY", smbcomcreatedirectory },
+[SMB_COM_DELETE_DIRECTORY] { "SMB_COM_DELETE_DIRECTORY", smbcomdeletedirectory },
+[SMB_COM_OPEN] { "SMB_COM_OPEN", smbcomopen },
+[SMB_COM_CREATE] { "SMB_COM_CREATE", nil },
+[SMB_COM_CLOSE] { "SMB_COM_CLOSE", smbcomclose },
+[SMB_COM_FLUSH] { "SMB_COM_FLUSH", smbcomflush },
+[SMB_COM_DELETE] { "SMB_COM_DELETE", smbcomdelete },
+[SMB_COM_RENAME] { "SMB_COM_RENAME", smbcomrename },
+[SMB_COM_QUERY_INFORMATION] { "SMB_COM_QUERY_INFORMATION", smbcomqueryinformation },
+[SMB_COM_SET_INFORMATION] { "SMB_COM_SET_INFORMATION", smbcomsetinformation },
+[SMB_COM_READ] { "SMB_COM_READ", nil },
+[SMB_COM_WRITE] { "SMB_COM_WRITE", smbcomwrite },
+[SMB_COM_LOCK_BYTE_RANGE] { "SMB_COM_LOCK_BYTE_RANGE", nil },
+[SMB_COM_UNLOCK_BYTE_RANGE] { "SMB_COM_UNLOCK_BYTE_RANGE", nil },
+[SMB_COM_CREATE_TEMPORARY] { "SMB_COM_CREATE_TEMPORARY", nil },
+[SMB_COM_CREATE_NEW] { "SMB_COM_CREATE_NEW", nil },
+[SMB_COM_CHECK_DIRECTORY] { "SMB_COM_CHECK_DIRECTORY", smbcomcheckdirectory },
+[SMB_COM_PROCESS_EXIT] { "SMB_COM_PROCESS_EXIT", nil },
+[SMB_COM_SEEK] { "SMB_COM_SEEK", nil },
+[SMB_COM_LOCK_AND_READ] { "SMB_COM_LOCK_AND_READ", nil },
+[SMB_COM_WRITE_AND_UNLOCK] { "SMB_COM_WRITE_AND_UNLOCK", nil },
+[SMB_COM_READ_RAW] { "SMB_COM_READ_RAW", nil },
+[SMB_COM_READ_MPX] { "SMB_COM_READ_MPX", nil },
+[SMB_COM_READ_MPX_SECONDARY] { "SMB_COM_READ_MPX_SECONDARY", nil },
+[SMB_COM_WRITE_RAW] { "SMB_COM_WRITE_RAW", nil },
+[SMB_COM_WRITE_MPX] { "SMB_COM_WRITE_MPX", nil },
+[SMB_COM_WRITE_MPX_SECONDARY] { "SMB_COM_WRITE_MPX_SECONDARY", nil },
+[SMB_COM_WRITE_COMPLETE] { "SMB_COM_WRITE_COMPLETE", nil },
+[SMB_COM_QUERY_SERVER] { "SMB_COM_QUERY_SERVER", nil },
+[SMB_COM_SET_INFORMATION2] { "SMB_COM_SET_INFORMATION2", smbcomsetinformation2 },
+[SMB_COM_QUERY_INFORMATION2] { "SMB_COM_QUERY_INFORMATION2", smbcomqueryinformation2 },
+[SMB_COM_LOCKING_ANDX] { "SMB_COM_LOCKING_ANDX", smbcomlockingandx },
+[SMB_COM_TRANSACTION] { "SMB_COM_TRANSACTION", smbcomtransaction },
+[SMB_COM_TRANSACTION_SECONDARY] { "SMB_COM_TRANSACTION_SECONDARY", nil },
+[SMB_COM_IOCTL] { "SMB_COM_IOCTL", nil },
+[SMB_COM_IOCTL_SECONDARY] { "SMB_COM_IOCTL_SECONDARY", nil },
+[SMB_COM_COPY] { "SMB_COM_COPY", nil },
+[SMB_COM_MOVE] { "SMB_COM_MOVE", nil },
+[SMB_COM_ECHO] { "SMB_COM_ECHO", smbcomecho },
+[SMB_COM_WRITE_AND_CLOSE] { "SMB_COM_WRITE_AND_CLOSE", nil },
+[SMB_COM_OPEN_ANDX] { "SMB_COM_OPEN_ANDX", smbcomopenandx },
+[SMB_COM_READ_ANDX] { "SMB_COM_READ_ANDX", smbcomreadandx },
+[SMB_COM_WRITE_ANDX] { "SMB_COM_WRITE_ANDX", nil },
+[SMB_COM_NEW_FILE_SIZE] { "SMB_COM_NEW_FILE_SIZE", nil },
+[SMB_COM_CLOSE_AND_TREE_DISC] { "SMB_COM_CLOSE_AND_TREE_DISC", nil },
+[SMB_COM_TRANSACTION2] { "SMB_COM_TRANSACTION2", smbcomtransaction2 },
+[SMB_COM_TRANSACTION2_SECONDARY] { "SMB_COM_TRANSACTION2_SECONDARY", nil },
+[SMB_COM_FIND_CLOSE2] { "SMB_COM_FIND_CLOSE2", smbcomfindclose2 },
+[SMB_COM_FIND_NOTIFY_CLOSE] { "SMB_COM_FIND_NOTIFY_CLOSE", nil },
+[SMB_COM_TREE_CONNECT] { "SMB_COM_TREE_CONNECT", nil },
+[SMB_COM_TREE_DISCONNECT] { "SMB_COM_TREE_DISCONNECT", smbcomtreedisconnect },
+[SMB_COM_NEGOTIATE] { "SMB_COM_NEGOTIATE", smbnegotiate },
+[SMB_COM_SESSION_SETUP_ANDX] { "SMB_COM_SESSION_SETUP_ANDX", smbcomsessionsetupandx },
+[SMB_COM_LOGOFF_ANDX] { "SMB_COM_LOGOFF_ANDX", nil },
+[SMB_COM_TREE_CONNECT_ANDX] { "SMB_COM_TREE_CONNECT_ANDX", smbcomtreeconnectandx },
+[SMB_COM_QUERY_INFORMATION_DISK] { "SMB_COM_QUERY_INFORMATION_DISK", nil },
+[SMB_COM_SEARCH] { "SMB_COM_SEARCH", nil },
+[SMB_COM_FIND] { "SMB_COM_FIND", nil },
+[SMB_COM_FIND_UNIQUE] { "SMB_COM_FIND_UNIQUE", nil },
+[SMB_COM_FIND_CLOSE] { "SMB_COM_FIND_CLOSE", nil },
+[SMB_COM_NT_TRANSACT] { "SMB_COM_NT_TRANSACT", nil },
+[SMB_COM_NT_TRANSACT_SECONDARY] { "SMB_COM_NT_TRANSACT_SECONDARY", nil },
+[SMB_COM_NT_CREATE_ANDX] { "SMB_COM_NT_CREATE_ANDX", smbcomntcreateandx },
+[SMB_COM_NT_CANCEL] { "SMB_COM_NT_CANCEL", nil },
+[SMB_COM_NT_RENAME] { "SMB_COM_NT_RENAME", nil },
+[SMB_COM_OPEN_PRINT_FILE] { "SMB_COM_OPEN_PRINT_FILE", nil },
+[SMB_COM_WRITE_PRINT_FILE] { "SMB_COM_WRITE_PRINT_FILE", nil },
+[SMB_COM_CLOSE_PRINT_FILE] { "SMB_COM_CLOSE_PRINT_FILE", nil },
+[SMB_COM_GET_PRINT_QUEUE] { "SMB_COM_GET_PRINT_QUEUE", nil },
+[SMB_COM_READ_BULK] { "SMB_COM_READ_BULK", nil },
+[SMB_COM_WRITE_BULK] { "SMB_COM_WRITE_BULK", nil },
+[SMB_COM_NO_ANDX_COMMAND] { "SMB_COM_NO_ANDX_COMMAND", nil },
+};
+
+SmbTrans2OpTableEntry
+smbtrans2optable[] = {
+[SMB_TRANS2_OPEN] { "SMB_TRANS2_OPEN", nil },
+[SMB_TRANS2_FIND_FIRST2] { "SMB_TRANS2_FIND_FIRST2", smbtrans2findfirst2 },
+[SMB_TRANS2_FIND_NEXT2] { "SMB_TRANS2_FIND_NEXT2", smbtrans2findnext2 },
+[SMB_TRANS2_QUERY_FS_INFORMATION] { "SMB_TRANS2_QUERY_FS_INFORMATION", smbtrans2queryfsinformation },
+[SMB_TRANS2_SET_FS_INFORMATION] { "SMB_TRANS2_SET_FS_INFORMATION", nil },
+[SMB_TRANS2_QUERY_PATH_INFORMATION] { "SMB_TRANS2_QUERY_PATH_INFORMATION", smbtrans2querypathinformation },
+[SMB_TRANS2_SET_PATH_INFORMATION] { "SMB_TRANS2_SET_PATH_INFORMATION", nil },
+[SMB_TRANS2_QUERY_FILE_INFORMATION] { "SMB_TRANS2_QUERY_FILE_INFORMATION", smbtrans2queryfileinformation },
+[SMB_TRANS2_SET_FILE_INFORMATION] { "SMB_TRANS2_SET_FILE_INFORMATION", smbtrans2setfileinformation },
+[SMB_TRANS2_FSCTL] { "SMB_TRANS2_FSCTL", nil },
+[SMB_TRANS2_IOCTL2] { "SMB_TRANS2_IOCTL2", nil },
+[SMB_TRANS2_FIND_NOTIFY_FIRST] { "SMB_TRANS2_FIND_NOTIFY_FIRST", nil },
+[SMB_TRANS2_FIND_NOTIFY_NEXT] { "SMB_TRANS2_FIND_NOTIFY_NEXT", nil },
+[SMB_TRANS2_CREATE_DIRECTORY] { "SMB_TRANS2_CREATE_DIRECTORY", nil },
+[SMB_TRANS2_SESSION_SETUP] { "SMB_TRANS2_SESSION_SETUP", nil },
+[SMB_TRANS2_GET_DFS_REFERRAL] { "SMB_TRANS2_GET_DFS_REFERRAL", nil },
+[SMB_TRANS2_REPORT_DFS_INCONSISTENCY] { "SMB_TRANS2_REPORT_DFS_INCONSISTENCY", nil },
+};
+int smbtrans2optablesize = nelem(smbtrans2optable);

+ 22 - 0
sys/src/cmd/aquarela/smbpath.c

@@ -0,0 +1,22 @@
+#include "headers.h"
+
+void
+smbpathsplit(char *path, char **dirp, char **namep)
+{
+	char *dir;
+	char *p = strrchr(path, '/');
+	if (p == nil) {
+		*dirp = smbestrdup("/");
+		*namep = smbestrdup(path);
+		return;
+	}
+	if (p == path)
+		dir = smbestrdup("/");
+	else {
+		dir = smbemalloc(p - path + 1);
+		memcpy(dir, path, p - path);
+		dir[p - path] = 0;
+	}
+	*dirp = dir;
+	*namep = smbestrdup(p + 1);
+}

+ 467 - 0
sys/src/cmd/aquarela/smbrap2.c

@@ -0,0 +1,467 @@
+#include "headers.h"
+
+typedef struct RapTableEntry RapTableEntry;
+
+struct RapTableEntry {
+	char *name;
+	SmbProcessResult (*procedure)(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata);
+};
+
+typedef int INFOSIZEFN(ushort level, void *data);
+typedef int INFOPUTFN(SmbBuffer *b, ushort level, void *data);
+typedef int INFOPUTSTRINGSFN(SmbBuffer *b, ushort level, int instance, void *data);
+typedef void *INFOENUMERATEFN(void *magic, int i);
+
+typedef struct InfoMethod {
+	INFOSIZEFN *size;
+	INFOPUTFN *put;
+	INFOPUTSTRINGSFN *putstrings;
+	INFOENUMERATEFN *enumerate;
+} InfoMethod;
+
+static int
+serverinfosize(ushort level, void *data)
+{
+	SmbServerInfo *si = data;
+	switch (level) {
+	case 0:
+		return 16;
+	case 1:
+		return 26 + smbstrlen(si->remark);
+	default:
+		return 0;
+	}
+}
+
+static int
+serverinfoput(SmbBuffer *b, ushort level, void *data)
+{
+	SmbServerInfo *si = data;
+	if (!smbbufferputstrn(b, si->name, 16, 1))
+		return 0;
+	if (level > 0) {
+		if (!smbbufferputb(b, si->vmaj)
+			|| !smbbufferputb(b, si->vmin)
+			|| !smbbufferputl(b, si->stype)
+			|| !smbbufferputl(b, 0))
+			return 0;
+	}
+	if (level > 1)
+		return 0;
+	return 1;
+}
+
+static int
+serverinfoputstrings(SmbBuffer *b, ushort level, int instance, void *data)
+{
+	SmbServerInfo *si = data;
+	if (level == 1) {
+		if (!smbbufferfixupabsolutel(b, instance * 26 + 22)
+			|| !smbbufferputstring(b, nil, SMB_STRING_ASCII, si->remark))
+			return 0;
+	}
+	return 1;
+}
+
+static void *
+serverinfoenumerate(void *magic, int i)
+{
+	if (magic) {
+		SmbServerInfo **si = magic;
+		return si[i];
+	}
+	if (i == 0)
+		return &smbglobals.serverinfo;
+	return nil;
+}
+
+InfoMethod serverinfo = {
+	serverinfosize,
+	serverinfoput,
+	serverinfoputstrings,
+	serverinfoenumerate,
+};
+
+static int
+shareinfosize(ushort level, void *data)
+{
+	SmbService *serv = data;
+	switch (level) {
+	case 0:
+		return 13;
+	case 1:
+		return 20 + smbstrlen(serv->remark);
+	case 2:
+		return 40 + smbstrlen(serv->remark) + smbstrlen(serv->path);
+	default:
+		return 0;
+	}
+}
+
+static int
+shareinfoput(SmbBuffer *b, ushort level, void *data)
+{
+	SmbService *serv = data;
+	if (!smbbufferputstrn(b, serv->name, 13, 0))
+		return 0;
+	if (level > 0) {
+		if (!smbbufferputb(b, 0)
+			|| !smbbufferputs(b, serv->stype)
+			|| !smbbufferputl(b, 0))
+			return 0;
+	}
+	if (level > 1) {
+		if (!smbbufferputs(b, 7)
+			|| !smbbufferputs(b, -1)
+			|| !smbbufferputs(b, serv->ref)
+			|| !smbbufferputl(b, 0)
+			|| !smbbufferfill(b, 0, 10))
+			return 0;
+	}
+	if (level > 2)
+		return 0;
+	return 1;
+}
+
+static int
+shareinfoputstrings(SmbBuffer *b, ushort level, int instance, void *data)
+{
+	SmbService *serv = data;
+	switch (level) {
+	case 0:
+		break;
+	case 1:
+		if (!smbbufferfixupabsolutel(b, instance * 20 + 16)
+			|| !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark))
+			return 0;
+		break;
+	case 2:
+		if (!smbbufferfixupabsolutel(b, instance * 40 + 16)
+			|| !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark)
+			|| !smbbufferfixupabsolutel(b, instance * 40 + 26)
+			|| !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->path))
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+	return 1;
+}
+
+static void *
+shareinfoenumerate(void *, int i)
+{
+	SmbService *serv;
+	for (serv = smbservices; i-- > 0 && serv; serv = serv->next)
+		;
+	return serv;
+}
+
+static InfoMethod shareinfo = {
+	shareinfosize,
+	shareinfoput,
+	shareinfoputstrings,
+	shareinfoenumerate,
+};
+
+static SmbProcessResult
+thingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m, ushort level, void *magic)
+{
+	int sentthings, totalthings;
+	int i;
+	int totalbytes;
+
+	sentthings = 0;
+	totalbytes = 0;
+	for (i = 0; ; i++) {
+		int len;
+		void *thing = (*m->enumerate)(magic, i);
+		if (thing == nil)
+			break;
+		len = (*m->size)(level, thing);
+		if (totalbytes + len <= smbbufferspace(outdata)) {
+			assert((*m->put)(outdata, level, thing));
+			sentthings++;
+		}
+		totalbytes += len;
+	}
+	totalthings = i;
+	for (i = 0; i < sentthings; i++) {
+		void *thing = (*m->enumerate)(magic, i);
+		assert(thing);
+		assert((*m->putstrings)(outdata, level, i, thing));
+	}
+	if (!smbbufferputs(outparam, sentthings < totalthings ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
+		|| !smbbufferputs(outparam, 0)
+		|| !smbbufferputs(outparam, totalthings)
+		|| !smbbufferputs(outparam, sentthings))
+		return SmbProcessResultFormat;
+	return SmbProcessResultReply;
+}
+
+static SmbProcessResult
+onethingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m, ushort level, void *thing)
+{
+	int moredata;
+	int totalbytes = (*m->size)(level, thing);
+	if (totalbytes <= smbbufferspace(outdata)) {
+		assert((*m->put)(outdata, level, thing));
+		assert((*m->putstrings)(outdata, level, 0, thing));
+		moredata = 0;
+	}
+	else
+		moredata = 1;
+	if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
+		|| !smbbufferputs(outparam, 0)
+		|| !smbbufferputs(outparam, totalbytes))
+		return SmbProcessResultFormat;
+	return SmbProcessResultReply;
+}
+
+static SmbProcessResult
+netshareenum(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
+{
+	ushort level;
+
+	/* WrLeh */
+	/* ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail */
+
+	if (!smbbuffergets(inparam, &level))
+		return SmbProcessResultFormat;
+	
+	smblogprintif(smbglobals.log.rap2, "netshareenum(%lud, %lud)\n",
+		level, smbbufferwritespace(outdata));
+
+	if (level != 1)
+		return SmbProcessResultFormat;
+
+	return thingfill(outparam, outdata, &shareinfo, level, nil);
+}
+
+static SmbProcessResult
+netserverenum2(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
+{
+	ushort level, rbl;
+	char *domain;
+	ulong servertype;
+	SmbProcessResult pr;
+	SmbServerInfo *si[3];
+	SmbServerInfo domainsi;
+	int entries;
+
+	/* WrLehDz
+	 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail,
+	 * ulong fServerType, char *pszDomain
+	*/
+
+	if (!smbbuffergets(inparam, &level)
+		|| !smbbuffergets(inparam, &rbl)
+		|| !smbbuffergetl(inparam, &servertype)
+		|| !smbbuffergetstr(inparam, 0, &domain)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	
+	smblogprintif(smbglobals.log.rap2, "netserverenum2(%lud, %lud, 0x%.8lux, %s)\n",
+		level, smbbufferwritespace(outdata), servertype, domain);
+
+	if (level > 1)
+		goto fmtfail;
+
+	if (servertype == 0xffffffff)
+		servertype &= ~(SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY);
+
+	if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0 && (servertype & SV_TYPE_DOMAIN_ENUM) == 0) 
+		servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
+
+	entries = 0;
+
+	if ((servertype & SV_TYPE_SERVER) != 0
+		&& (domain[0] == 0 || cistrcmp(domain, smbglobals.primarydomain) == 0)) {
+		si[entries++] = &smbglobals.serverinfo;
+	}
+
+	if ((servertype & SV_TYPE_DOMAIN_ENUM) != 0) {
+		/* there's only one that I know about */
+		memset(&domainsi, 0, sizeof(domainsi));
+		domainsi.name = smbglobals.primarydomain;
+		domainsi.stype = SV_TYPE_DOMAIN_ENUM;
+		si[entries++] = &domainsi;
+	}
+	si[entries] = 0;
+
+	pr = thingfill(outparam, outdata, &serverinfo, level, si);
+			
+done:
+	free(domain);
+	return pr;
+}
+
+static SmbProcessResult
+netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
+{
+	char *netname;
+	ushort level;
+	SmbProcessResult pr;
+	SmbService *serv;
+
+	/*
+	 * zWrLh
+	 * char *pszNetName, ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
+	*/
+
+	if (!smbbuffergetstrinline(inparam, &netname)
+		|| !smbbuffergets(inparam, &level)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	
+	smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lud, %lud)\n",
+		netname, level, smbbufferwritespace(outdata));
+
+	if (level > 2)
+		goto fmtfail;
+
+	for (serv = smbservices; serv; serv = serv->next)
+		if (cistrcmp(serv->name, netname) == 0)
+			break;
+
+	if (serv == nil) {
+		smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname);
+		pr = SmbProcessResultUnimp;
+		goto done;
+	}
+
+	pr = onethingfill(outparam, outdata, &shareinfo, level, serv);
+
+done:
+	return pr;
+}
+
+static SmbProcessResult
+netservergetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
+{
+	ushort level;
+	SmbProcessResult pr;
+
+	/* WrLh
+	 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
+	*/
+
+	if (!smbbuffergets(inparam, &level)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	
+	smblogprintif(smbglobals.log.rap2, "netservergetinfo(%lud, %lud)\n",
+		level, smbbufferwritespace(outdata));
+
+	if (level > 1)
+		goto fmtfail;
+
+	pr = onethingfill(outparam, outdata, &shareinfo, level, &smbglobals.serverinfo);
+			
+done:
+	return pr;
+}
+
+static SmbProcessResult
+netwkstagetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
+{
+	ushort level;
+	ushort usefulbytes;
+	SmbProcessResult pr;
+	int moredata;
+
+	/* WrLh
+	 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
+	*/
+
+	if (!smbbuffergets(inparam, &level)) {
+	fmtfail:
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	
+	smblogprintif(smbglobals.log.rap2, "netwkstagetinfo(%lud, %lud)\n",
+		level, smbbufferwritespace(outdata));
+
+	if (level != 10)
+		goto fmtfail;
+
+	usefulbytes = 22 + smbstrlen(smbglobals.serverinfo.name) + smbstrlen(getuser())
+		+ 3 * smbstrlen(smbglobals.primarydomain);
+
+	moredata = usefulbytes > smbbufferwritespace(outdata);
+
+	assert(smbbufferputl(outdata, 0));
+	assert(smbbufferputl(outdata, 0));
+	assert(smbbufferputl(outdata, 0));
+	assert(smbbufferputb(outdata, smbglobals.serverinfo.vmaj));
+	assert(smbbufferputb(outdata, smbglobals.serverinfo.vmin));
+	assert(smbbufferputl(outdata, 0));
+	assert(smbbufferputl(outdata, 0));
+	assert(smbbufferfixupabsolutel(outdata, 0));
+	assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.serverinfo.name));
+	assert(smbbufferfixupabsolutel(outdata, 4));
+	assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, getuser()));
+	assert(smbbufferfixupabsolutel(outdata, 8));
+	assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
+	assert(smbbufferfixupabsolutel(outdata, 14));
+	assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
+	assert(smbbufferfixupabsolutel(outdata, 18));
+	assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
+
+	if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
+		|| !smbbufferputs(outparam, 0)
+		|| !smbbufferputs(outparam, usefulbytes)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	
+	pr = SmbProcessResultReply;
+			
+done:
+	return pr;
+}
+
+static RapTableEntry raptable[] = {
+[RapNetShareGetInfo] { "NetShareGetInfo", netsharegetinfo },
+[RapNetShareEnum] { "NetShareEnum", netshareenum },
+[RapNetServerGetInfo] {"NetServerGetInfo", netservergetinfo },
+[RapNetWkstaGetInfo] { "NetWkstaGetInfo", netwkstagetinfo },
+[RapNetServerEnum2] { "NetServerEnum2", netserverenum2 },
+};
+
+SmbProcessResult
+smbrap2(SmbSession *s)
+{
+	char *pstring;
+	char *dstring;
+	ushort pno;
+	RapTableEntry *e;
+	SmbProcessResult pr;
+	SmbBuffer *inparam;
+
+	inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(inparam, &pno)
+		|| !smbbuffergetstrinline(inparam, &pstring)
+		|| !smbbuffergetstrinline(inparam, &dstring)) {
+		smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n");
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	if (pno > nelem(raptable) || raptable[pno].name == nil) {
+		smblogprint(-1, "smbrap2: unsupported procedure %ud\n", pno);
+		pr = SmbProcessResultUnimp;
+		goto done;
+	}
+	e = raptable + pno;
+	pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data);
+done:
+	smbbufferfree(&inparam);
+	return pr;
+}

+ 100 - 0
sys/src/cmd/aquarela/smbrap2client.c

@@ -0,0 +1,100 @@
+#include "headers.h"
+
+static SmbTransactionMethod smbtransactionmethodrap = {
+	.encodeprimary = smbtransactionencodeprimary,
+	.sendrequest = smbtransactionclientsend,
+	.receiveresponse = smbtransactionclientreceive,
+	.decoderesponse = smbtransactiondecoderesponse,
+};
+
+int
+smbclientrap(SmbClient *c, SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata, char **errmsgp)
+{
+	SmbTransaction transaction;
+	SmbHeader h;
+	memset(&transaction, 0, sizeof(transaction));
+	transaction.in.name = smbglobals.pipelanman;
+	transaction.in.parameters = smbbufferreadpointer(inparam);
+	transaction.in.tpcount = smbbufferreadspace(inparam);
+	transaction.in.maxpcount = smbbufferwritespace(outparam);
+	transaction.in.maxdcount = smbbufferwritespace(outdata);
+	transaction.out.parameters = outparam;
+	transaction.out.data = outdata;
+	h = c->protoh;
+	h.tid = c->ipctid;
+	h.mid = 0;
+	return smbtransactionexecute(&transaction, &h, &c->peerinfo, c->b, &smbtransactionmethodrap, c, nil, errmsgp);
+}
+
+int
+smbnetserverenum2(SmbClient *c, ulong stype, char *domain, int *entriesp, SmbRapServerInfo1 **sip, char **errmsgp)
+{
+	int rv;
+	ushort ec, entries, total, converter;
+	SmbRapServerInfo1 *si = nil;
+	SmbBuffer *ipb = smbbuffernew(512);
+	SmbBuffer *odb = smbbuffernew(65535);
+	SmbBuffer *opb = smbbuffernew(8);
+	smbbufferputs(ipb, 104);
+	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "WrLehDz");
+	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "B16BBDz");
+	smbbufferputs(ipb, 1);
+	smbbufferputs(ipb, smbbufferwritespace(odb));
+	smbbufferputl(ipb, stype);
+	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, domain);
+	rv = !smbclientrap(c, ipb, opb, odb, errmsgp);
+	smbbufferfree(&ipb);
+	if (rv == 0) {
+		char *remark, *eremark;
+		int remarkspace;
+		int i;
+		if (!smbbuffergets(opb, &ec)
+			|| !smbbuffergets(opb, &converter)
+			|| !smbbuffergets(opb, &entries)
+			|| !smbbuffergets(opb, &total)) {
+			smbstringprint(errmsgp, "smbnetserverenum2: not enough return parameters");
+			rv = -1;
+			goto done;
+		}
+		if (ec != 0) {
+			rv = ec;
+			goto done;
+		}
+		if (smbbufferreadspace(odb) < entries * 26) {
+			smbstringprint(errmsgp, "smbnetserverenum2: not enough return data");
+			rv = -1;
+			goto done;
+		}
+		remarkspace = smbbufferreadspace(odb) - entries * 26;
+		si = smbemalloc(entries * sizeof(SmbRapServerInfo1) + remarkspace);
+		remark = (char *)&si[entries];
+		eremark = remark + remarkspace;
+		for (i = 0; i < entries; i++) {
+			ulong offset;
+			int remarklen;
+			assert(smbbuffergetbytes(odb, si[i].name, 16));
+			assert(smbbuffergetb(odb, &si[i].vmaj));
+			assert(smbbuffergetb(odb, &si[i].vmin));
+			assert(smbbuffergetl(odb, &si[i].type));
+			assert(smbbuffergetl(odb, &offset));
+			offset -= converter;
+			if (!smbbufferoffsetcopystr(odb, offset, remark, eremark - remark, &remarklen)) {
+				smbstringprint(errmsgp, "smbnetserverenum2: invalid string offset");
+				rv = -1;
+				goto done;
+			}
+			si[i].remark = remark;
+			remark += remarklen;
+		}
+		*sip = si;
+		si = nil;
+		*entriesp = entries;
+	}
+	else
+		rv = -1;	
+done:
+	free(si);
+	smbbufferfree(&opb);
+	smbbufferfree(&odb);
+	return rv;
+}

+ 67 - 0
sys/src/cmd/aquarela/smbrep.c

@@ -0,0 +1,67 @@
+#include "headers.h"
+
+int
+smbmatch(char *name, Reprog *rep)
+{
+	Resub sub;
+	sub.sp = nil;
+	sub.ep = nil;
+	if (regexec(rep, name, &sub, 1) && sub.sp == name && *sub.ep == 0)
+		return 1;
+	return 0;
+}
+
+Reprog *
+smbmkrep(char *pattern)
+{
+	Reprog *r;
+	int l;
+	char *tmp, *p, *q, *t;
+	l = strlen(pattern);
+	tmp = smbemalloc(l * 5 + 1);
+	t = tmp;
+	p = pattern;
+	while (*p) {
+		if (*p == '*') {
+			if (p[1] == '.') {
+				strcpy(t, "[^.]*");
+				t += 5;
+				p++;
+			}
+			else {
+				*t++ = '.';
+				*t++ = '*';
+				p++;
+			}
+		}
+		else if (*p == '?') {
+			for (q = p + 1; *q && *q == '?'; q++)
+				;
+			if (*q == 0 || *q == '.') {
+				/* at most n copies */
+				strcpy(t, "[^.]?");
+				t += 5;
+				p++;
+			}
+			else {
+				/* exactly n copies */
+				strcpy(t, "[^.]");
+				t += 4;
+				p++;
+			}
+		}
+		else if (strchr(".+{}()|\\^$", *p) != 0) {
+			/* regexp meta */
+			*t++ = '\\';
+			*t++ = *p++;
+		}
+		else
+			*t++ = *p++;
+	}
+	*t = 0;
+	smblogprintif(smbglobals.log.rep, "%s => %s\n", pattern, tmp);
+	r = regcomp(tmp);
+	free(tmp);
+	return r;
+}
+

+ 135 - 0
sys/src/cmd/aquarela/smbresponse.c

@@ -0,0 +1,135 @@
+#include "headers.h"
+
+void
+smbresponsereset(SmbSession *s)
+{
+	smbbufferreset(s->response);
+}
+
+void
+smbresponseinit(SmbSession *s, ushort maxlen)
+{
+	smbbufferfree(&s->response);
+	s->response = smbbuffernew(maxlen);
+}
+
+int
+smbresponsealignl2(SmbSession *s, int l2a)
+{
+	return smbbufferalignl2(s->response, l2a);
+}
+
+int
+smbresponseputheader(SmbSession *s, SmbHeader *h, uchar errclass, ushort error)
+{
+	h->errclass = errclass;
+	h->error = error;
+	return smbbufferputheader(s->response, h, &s->peerinfo);
+}
+
+int
+smbresponseputb(SmbSession *s, uchar b)
+{
+	return smbbufferputb(s->response, b);
+}
+
+ushort
+smbresponsespace(SmbSession *sess)
+{
+	return smbbufferwritespace(sess->response);
+}
+
+int
+smbresponseskip(SmbSession *sess, ushort amount)
+{
+	return smbbufferputbytes(sess->response, nil, amount);
+}
+
+int
+smbresponseoffsetputs(SmbSession *sess, ushort offset, ushort s)
+{
+	return smbbufferoffsetputs(sess->response, offset, s);
+}
+
+int
+smbresponseputs(SmbSession *sess, ushort s)
+{
+	return smbbufferputs(sess->response, s);
+}
+
+int
+smbresponseputl(SmbSession *s, ulong l)
+{
+	return smbbufferputl(s->response, l);
+}
+
+int
+smbresponsecpy(SmbSession *s, uchar *data, ushort datalen)
+{
+	return smbbufferputbytes(s->response, data, datalen);
+}
+
+int
+smbresponseputstring(SmbSession *s, int mustalign, char *string)
+{
+	return smbbufferputstring(s->response, &s->peerinfo, mustalign ? 0 : SMB_STRING_UNALIGNED, string);
+}
+
+int
+smbresponseputstr(SmbSession *s, char *string)
+{
+	return smbbufferputstring(s->response, nil, SMB_STRING_ASCII, string);
+}
+
+ushort
+smbresponseoffset(SmbSession *s)
+{
+	return smbbufferwriteoffset(s->response);
+}
+
+SmbProcessResult
+smbresponsesend(SmbSession *s)
+{
+	uchar cmd;
+	SmbProcessResult pr;
+
+	assert(smbbufferoffsetgetb(s->response, 4, &cmd));
+smbloglock();
+smblogprint(cmd, "sending:\n");
+smblogdata(cmd, smblogprint, smbbufferreadpointer(s->response), smbbufferreadspace(s->response), 256);
+smblogunlock();
+	if (s->nbss) {
+		NbScatterGather a[2];
+		a[0].p = smbbufferreadpointer(s->response);
+		a[0].l = smbbufferreadspace(s->response);
+		a[1].p = nil;
+		nbssgatherwrite(s->nbss, a);
+		pr = SmbProcessResultOk;
+	}
+	else if (s->cifss) {
+		ulong l = smbbufferreadspace(s->response);
+		uchar nl[4];
+		hnputl(nl, l);
+		write(s->cifss->fd, nl, 4);
+		write(s->cifss->fd, smbbufferreadpointer(s->response), l);
+		pr = SmbProcessResultOk;
+	}
+	else
+		pr = SmbProcessResultDie;
+	smbbufferreset(s->response);
+	return pr;
+}
+
+int
+smbresponseputandxheader(SmbSession *s, SmbHeader *h, ushort andxcommand, ulong *andxoffsetfixupp)
+{
+	return smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, andxoffsetfixupp);
+}
+
+int
+smbresponseputerror(SmbSession *s, SmbHeader *h, uchar errclass, ushort error)
+{
+	h->wordcount = 0;
+	return smbresponseputheader(s, h, errclass, error)
+		&& smbresponseputs(s, 0);
+}

+ 115 - 0
sys/src/cmd/aquarela/smbservice.c

@@ -0,0 +1,115 @@
+#include "headers.h"
+
+static SmbService local = {
+	.name = "local",
+	.type = "A:",
+	.stype = STYPE_DISKTREE,
+	.remark = "The standard namespace",
+	.path = "/n/local",
+};
+
+static SmbService ipc = {
+	.name = "IPC$",
+	.type = "IPC",
+	.stype = STYPE_IPC,
+	.remark = "The aquarela IPC service",
+	.path = nil,
+	.next = &local,
+};
+
+SmbService *smbservices = &ipc;
+
+static int
+run9fs(char *arg)
+{
+	int rv;
+	Waitmsg *w;
+
+	rv = fork();
+	if (rv < 0)
+		return -1;
+	if (rv == 0) {
+		char *argv[3];
+		argv[0] = "/rc/bin/9fs";
+		argv[1] = arg;
+		argv[2] = 0;
+		exec(argv[0], argv);
+		exits("failed to exec 9fs");
+	}
+	for (;;) {
+		w = wait();
+		if (w == nil)
+			return -1;
+		if (w->pid == rv)
+			break;
+		free(w);
+	}
+	if (w->msg[0]) {
+		smblogprint(SMB_COM_TREE_CONNECT_ANDX, "smbservicefind: %s\n", w->msg);
+		free(w);
+		return -1;
+	}
+	free(w);
+	smblogprint(SMB_COM_TREE_CONNECT_ANDX, "smbservicefind: 9fs %s executed successfully\n", arg);
+	return 0;
+}
+
+SmbService *
+smbservicefind(SmbSession *s, char *uncpath, char *servicetype, uchar *errclassp, ushort *errorp)
+{
+	char *p, *q;
+	if (uncpath[0] == '/' && uncpath[1] == '/') {
+		/* check that the server name matches mine */
+		p = uncpath + 2;
+		q = strchr(p, '/');
+		if (q == nil)
+			goto bad;
+		*q++ = 0;
+//		if (cistrcmp(p, smbglobals.serverinfo.name) != 0)
+//			goto bad;
+	}
+	else
+		q = uncpath + 1;
+	if (strcmp(servicetype, "?????") == 0 && strcmp(q, "IPC$") == 0)
+		return &ipc;
+	if ((strcmp(servicetype, "?????") == 0 || strcmp(servicetype, "A:") == 0)) {
+		SmbService *serv;
+		if (cistrcmp(q, local.name) == 0)
+			return &local;
+		/* try the session specific list */
+		for (serv = s->serv; serv; serv = serv->next)
+			if (cistrcmp(q, serv->name) == 0)
+				return serv;
+		/* exec "9fs q" in case it invents /n/q */
+		for (p = q; *p; p++)
+			if (*p >= 'A' && *p <= 'Z')
+				*p = tolower(*p);
+		if (run9fs(q) >= 0) {
+			serv = smbemallocz(sizeof(*serv), 1);
+			serv->name = smbestrdup(q);
+			serv->type = smbestrdup("A:");
+			serv->stype = STYPE_DISKTREE;
+			smbstringprint(&serv->remark, "9fs %s", q);
+			smbstringprint(&serv->path, "/n/%s", q);
+			serv->next = s->serv;
+			s->serv = serv;
+			return serv;
+		}
+	}
+bad:
+	*errclassp = ERRDOS;
+	*errorp = ERRbadpath;
+	return nil;
+}
+
+void
+smbserviceget(SmbService *serv)
+{
+	incref(serv);
+}
+
+void
+smbserviceput(SmbService *serv)
+{
+	decref(serv);
+}

+ 271 - 0
sys/src/cmd/aquarela/smbsharedfile.c

@@ -0,0 +1,271 @@
+#include "headers.h"
+
+typedef struct SmbSharedFileEntry SmbSharedFileEntry;
+struct SmbSharedFileEntry {
+	SmbSharedFile;
+	Ref;
+	SmbSharedFileEntry *next;
+};
+
+static struct {
+	QLock;
+	SmbSharedFileEntry *list;
+} sharedfiletable;
+
+typedef struct SmbLockListEntry SmbLockListEntry;
+
+struct SmbLockListEntry {
+	SmbLock;
+	SmbLockListEntry *next;
+};
+
+struct SmbLockList {
+	SmbLockListEntry *head;
+};
+
+static int
+lockconflict(SmbLock *l1, SmbLock *l2)
+{
+	return l1->base < l2->limit && l2->base < l1->limit;
+}
+
+static int
+lockorder(SmbLock *l1, SmbLock *l2)
+{
+	if (l1->base < l2->base)
+		return -1;
+	if (l1->base > l2->base)
+		return 1;
+	if (l1->limit > l2->limit)
+		return -1;
+	if (l1->limit < l2->limit)
+		return 1;
+	return 0;
+}
+
+static void
+locklistfree(SmbLockList **llp)
+{
+	SmbLockList *ll = *llp;
+	if (ll) {
+		while (ll->head) {
+			SmbLockListEntry *next = ll->head->next;
+			free(ll->head);
+			ll->head = next;
+		}
+		free(ll);
+		*llp = nil;
+	}
+}
+
+int
+smbsharedfilelock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit)
+{
+	SmbLockListEntry smblock;
+	SmbLockListEntry *l, *nl, **lp;
+	smblock.s = s;
+	smblock.pid = pid;
+	smblock.base = base;
+	smblock.limit = limit;
+	if (sf->locklist) {
+		for (l = sf->locklist->head; l; l = l->next)
+			if (lockconflict(l, &smblock)) {
+				smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) failed because conflicts with [%lld, %lld)\n",
+					base, limit, l->base, l->limit);
+				return 0;
+			}
+	}
+	if (sf->locklist == nil)
+		sf->locklist = smbemallocz(sizeof(SmbLockList), 1);
+	for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next)
+		if (lockorder(&smblock, l) <= 0)
+			break;
+	smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) succeeded\n", base, limit);
+	nl = smbemalloc(sizeof(*nl));
+	*nl = smblock;
+	nl->next = *lp;
+	*lp = nl;
+//{
+//	smblogprintif(smbglobals.log.locks,"smbsharedfilelock: list\n");
+//	for (l = sf->locklist->head; l; l = l->next)
+//		smblogprintif(smbglobals.log.locks, "smbsharedfilelock: [%lld, %lld)\n", l->base, l->limit);
+//}
+	return 1;
+}
+
+int
+smbsharedfileunlock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit)
+{
+	SmbLockListEntry smblock;
+	SmbLockListEntry *l, **lp;
+	smblock.s = s;
+	smblock.pid = pid;
+	smblock.base = base;
+	smblock.limit = limit;
+	if (sf->locklist == nil)
+		goto failed;
+	for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next) {
+		if (l->s != s || l->pid != pid)
+			continue;
+		switch (lockorder(&smblock, l)) {
+		case 0:
+			*lp = l->next;
+			free(l);
+			smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) succeeded\n", base, limit);
+			return 1;
+		case -1:
+			goto failed;
+		}
+	}
+failed:
+	smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) failed\n", base, limit);
+	return 0;
+}
+
+static int
+p9denied(int p9mode, int share)
+{
+//smblogprint(-1, "p9denied(%d, %d)\n", p9mode, share);
+	if (share == SMB_OPEN_MODE_SHARE_EXCLUSIVE)
+		return 1;
+	switch (p9mode & 3) {
+	case OREAD:
+	case OEXEC:
+		if (share == SMB_OPEN_MODE_SHARE_DENY_READOREXEC)
+			return 1;
+		break;
+	case OWRITE:
+		if (share == SMB_OPEN_MODE_SHARE_DENY_WRITE)
+			return 1;
+		break;
+	case ORDWR:
+		if (share != SMB_OPEN_MODE_SHARE_DENY_NONE)
+			return 1;
+		break;
+	}
+	return 0;
+}
+
+static void
+sharesplit(int share, int *denyread, int *denywrite)
+{
+	switch (share) {
+	case SMB_OPEN_MODE_SHARE_EXCLUSIVE:
+		*denyread = 1;
+		*denywrite = 1;
+		break;
+	case SMB_OPEN_MODE_SHARE_DENY_READOREXEC:
+		*denyread = 1;
+		*denywrite = 0;
+		break;
+	case SMB_OPEN_MODE_SHARE_DENY_WRITE:
+		*denywrite = 0;
+		*denywrite = 1;
+		break;
+	default:
+		*denyread = 0;
+		*denywrite = 0;
+	}
+}
+
+static int
+sharemake(int denyread, int denywrite)
+{
+	if (denyread)
+		if (denywrite)
+			return SMB_OPEN_MODE_SHARE_EXCLUSIVE;
+		else
+			return SMB_OPEN_MODE_SHARE_DENY_READOREXEC;
+	else if (denywrite)
+		return SMB_OPEN_MODE_SHARE_DENY_WRITE;
+	else
+		return SMB_OPEN_MODE_SHARE_DENY_NONE;
+}
+
+static ushort
+sharesubtract(int share1, int share2)
+{
+	int dr1, dw1;
+	int dr2, dw2;
+	sharesplit(share1, &dr1, &dw1);
+	sharesplit(share2, &dr2, &dw2);
+	if (dw2)
+		dw1 = 0;
+	if (dr2)
+		dr1 = 0;
+	return sharemake(dr1, dw1);
+}
+
+static int
+shareadd(int share1, int share2)
+{
+	int dr1, dw1;
+	int dr2, dw2;
+	sharesplit(share1, &dr1, &dw1);
+	sharesplit(share2, &dr2, &dw2);
+	if (dw2)
+		dw1 = 1;
+	if (dr2)
+		dr1 = 1;
+	return sharemake(dr1, dw1);
+}
+
+SmbSharedFile *
+smbsharedfileget(Dir *d, int p9mode, int *sharep)
+{
+	SmbSharedFileEntry *sfe;
+	qlock(&sharedfiletable);
+	for (sfe = sharedfiletable.list; sfe; sfe = sfe->next) {
+		if (sfe->type == d->type && sfe->dev == d->dev && sfe->path == d->qid.path) {
+			if (p9denied(p9mode, sfe->share)) {
+				qunlock(&sharedfiletable);
+				return nil;
+			}
+			*sharep = sharesubtract(*sharep, sfe->share);
+			sfe->share = shareadd(sfe->share, *sharep);
+			sfe->ref++;
+			goto done;
+		}
+	}
+	sfe = smbemallocz(sizeof(SmbSharedFileEntry), 1);
+	sfe->type = d->type;
+	sfe->dev = d->dev;
+	sfe->path = d->qid.path;
+//	sfe->name = smbestrdup(name);
+	sfe->ref = 1;
+	sfe->share = *sharep;
+	sfe->next = sharedfiletable.list;
+	sharedfiletable.list = sfe;
+done:
+	smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileget: ref %d share %d\n",
+		sfe->ref, sfe->share);
+	qunlock(&sharedfiletable);
+	return sfe;
+}
+
+void
+smbsharedfileput(SmbFile *f, SmbSharedFile *sf, int share)
+{
+	SmbSharedFileEntry *sfe, **sfep;
+	qlock(&sharedfiletable);
+	for (sfep = &sharedfiletable.list; (sfe = *sfep) != nil; sfep = &sfe->next) {
+		if (sfe == sf) {
+			sfe->ref--;
+			if (sfe->ref == 0) {
+				*sfep = sfe->next;
+				if (sfe->deleteonclose && f)
+					smbremovefile(f->t, nil, f->name);
+				smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileput: removed\n");
+				locklistfree(&sfe->locklist);
+				free(sfe);
+			}
+			else {
+				sfe->share = sharesubtract(sfe->share, share);
+				smblogprintif(smbglobals.log.sharedfiles,
+					"smbsharedfileput: ref %d share %d\n", sfe->ref, sfe->share);
+			}
+			break;
+		}
+	}
+	qunlock(&sharedfiletable);
+}

+ 201 - 0
sys/src/cmd/aquarela/smbstring.c

@@ -0,0 +1,201 @@
+#include "headers.h"
+
+Rune
+smbruneconvert(Rune r, ulong flags)
+{
+	if (r >= 'a' && r <= 'z' && (flags & SMB_STRING_UPCASE))
+		r = toupper(r);
+	else if (r == '/' && (flags & SMB_STRING_REVPATH))
+		r = '\\';
+	else if (r == '\\' && (flags & SMB_STRING_PATH))
+		r = '/';
+	else if (r == 0xa0 && (flags & SMB_STRING_REVPATH) && smbglobals.convertspace)
+		r = ' ';
+	else if (r == ' ' && (flags & SMB_STRING_PATH) && smbglobals.convertspace)
+		r = 0xa0;
+	return r;
+}
+
+int
+smbucs2len(char *string)
+{
+	return (string ? utflen(string) : 0) * 2 + 2;
+}
+
+int
+smbstrlen(char *string)
+{
+	return (string ? strlen(string) : 0) + 1;
+}
+
+int
+smbstringlen(SmbPeerInfo *i, char *string)
+{
+	if (smbglobals.unicode && (i == nil || (i->capabilities & CAP_UNICODE) != 0))
+		return smbucs2len(string);
+	return  smbstrlen(string);
+}
+
+char *
+smbstrinline(uchar **bdatap, uchar *edata)
+{
+	char *p;
+	uchar *np;
+	np = memchr(*bdatap, 0, edata - *bdatap);
+	if (np == nil)
+		return nil;
+	p = (char *)*bdatap;
+	*bdatap = np + 1;
+	return p;
+}
+
+char *
+smbstrdup(uchar **bdatap, uchar *edata)
+{
+	char *p;
+	uchar *np;
+	np = memchr(*bdatap, 0, edata - *bdatap);
+	if (np == nil)
+		return nil;
+	p = smbestrdup((char *)(*bdatap));
+	*bdatap = np + 1;
+	return p;
+}
+
+char *
+smbstringdup(SmbHeader *h, uchar *base, uchar **bdatap, uchar *edata)
+{
+	char *p;
+	if (h && h->flags2 & SMB_FLAGS2_UNICODE) {
+		uchar *bdata = *bdatap;
+		uchar *savebdata;
+		Rune r;
+		int l;
+		char *q;
+
+		l = 0;
+		if ((bdata - base) & 1)
+			bdata++;
+		savebdata = bdata;
+		do {
+			if (bdata + 2 > edata)
+				return nil;
+			r = smbnhgets(bdata); bdata += 2;
+			l += runelen(r);
+		} while (r != 0);
+		p = smbemalloc(l);
+		bdata = savebdata;
+		q = p;
+		do {
+			r = smbnhgets(bdata); bdata += 2;
+			q += runetochar(q, &r);
+		} while (r != 0);
+		*bdatap = bdata;
+		return p;
+	}
+	return smbstrdup(bdatap, edata);
+}
+
+int
+smbstrnput(uchar *buf, ushort n, ushort maxlen, char *string, ushort size, int upcase)
+{
+	uchar *p = buf + n;
+	int l;
+	l = strlen(string);
+	if (l + 1 > size)
+		l = size - 1;
+	if (n + l + 1 > maxlen)
+		return 0;
+	if (upcase) {
+		int x;
+		for (x = 0; x < l; x++)
+			p[x] = toupper(string[x]);
+	}
+	else
+		memcpy(p, string, l);
+	
+	p += l;
+	while (l++ < size)
+		*p++ = 0;
+	return size;
+}
+
+int
+smbstrput(ulong flags, uchar *buf, ushort n, ushort maxlen, char *string)
+{
+	uchar *p = buf + n;
+	int l;
+	l = string ? strlen(string) : 0;
+	if (n + l + ((flags & SMB_STRING_UNTERMINATED) == 0 ? 1 : 0) > maxlen)
+		return 0;
+	memcpy(p, string, l);
+	if (flags & (SMB_STRING_UPCASE | SMB_STRING_PATH | SMB_STRING_REVPATH)) {
+		uchar *q;
+		for (q = p; q < p + l; q++)
+			if (*q >= 'a' && *q <= 'z' && (flags & SMB_STRING_UPCASE))
+				*q = toupper(*q);
+			else if (*q == '/' && (flags & SMB_STRING_REVPATH))
+				*q = '\\';
+			else if (*q == '\\' && (flags & SMB_STRING_PATH))
+				*q = '/';
+	}
+	p += l;
+	if ((flags & SMB_STRING_UNTERMINATED) == 0)
+		*p++ = 0;
+	return p - (buf + n);
+}
+
+int
+smbucs2put(ulong flags, uchar *buf, ushort n, ushort maxlen, char *string)
+{
+	uchar *p = buf + n;
+	int l;
+	int align;
+	align = (flags & SMB_STRING_UNALIGNED) == 0 && (n & 1) != 0;
+	l = string ? utflen(string) * 2 : 0;
+	if (n + l + ((flags & SMB_STRING_UNTERMINATED) ? 0 : 2) + align > maxlen)
+		return 0;
+	if (align)
+		*p++ = 0;
+	while (string && *string) {
+		Rune r;
+		int i;
+		i = chartorune(&r, string);
+		if (flags & SMB_STRING_CONVERT_MASK)
+			r = smbruneconvert(r, flags);
+		smbhnputs(p, r);
+		p += 2;
+		string += i;
+	}
+	if ((flags & SMB_STRING_UNTERMINATED) == 0) {
+		smbhnputs(p, 0);
+		p += 2;
+	}
+	assert(p <= buf + maxlen);
+	return p - (buf + n);
+}
+
+int
+smbstringput(SmbPeerInfo *p, ulong flags, uchar *buf, ushort n, ushort maxlen, char *string)
+{
+	if (flags & SMB_STRING_UNICODE)
+		return smbucs2put(flags, buf, n, maxlen, string);
+	if (flags & SMB_STRING_ASCII)
+		return smbstrput(flags, buf, n, maxlen, string);
+	if (p && (p->capabilities & CAP_UNICODE) != 0)
+		return smbucs2put(flags, buf, n, maxlen, string);
+	return smbstrput(flags, buf, n, maxlen, string);
+}
+
+void
+smbstringprint(char **p, char *fmt, ...)
+{
+	va_list arg;
+	if (*p) {
+		free(*p);
+		*p = nil;
+	}
+	va_start(arg, fmt);
+	*p = vsmprint(fmt, arg);
+	va_end(arg);
+}

+ 63 - 0
sys/src/cmd/aquarela/smbtime.c

@@ -0,0 +1,63 @@
+#include "headers.h"
+
+void
+smbplan9time2datetime(ulong time, int tzoff, ushort *datep, ushort *timep)
+{
+	Tm *tm;
+	if (tzoff < 0)
+		time -= (ulong)-tzoff;
+	else
+		time += tzoff;
+	tm = gmtime(time);
+	*datep = (tm->mday) | ((tm->mon + 1) << 5) | ((tm->year - 80) << 9);
+	*timep = (tm->sec >> 1) | (tm->min << 5) | (tm->hour << 11);
+}
+
+ulong
+smbdatetime2plan9time(ushort date, ushort time, int tzoff)
+{
+	Tm tm;
+	strcpy(tm.zone, "GMT");
+	tm.mday = date & 0x1f;
+	tm.mon = ((date >> 5) & 0xf) - 1;
+	tm.year = (date >> 9) + 80;
+	tm.yday = 0;
+	tm.sec = (time & 0x1f) << 1;
+	tm.min = (time >> 5) & 0x3f;
+	tm.hour = time >> 11;
+	smblogprint(-1, "smbdatetime2plan9time: converting %d/%d/%d %d:%d:%d\n",
+		tm.year + 1900, tm.mon + 1, tm.mday, tm.hour, tm.min, tm.sec);
+	return tm2sec(&tm) - tzoff;
+}
+
+vlong
+smbplan9time2time(ulong time)
+{
+	return ((vlong)time + 11644473600LL) * 10000000;
+}
+
+ulong
+smbtime2plan9time(vlong nttime)
+{
+	return (nttime / 10000000 - 11644473600LL);
+}
+
+ulong
+smbplan9time2utime(ulong time, int tzoff)
+{
+	if (tzoff < 0)
+		time -= (ulong)-tzoff;
+	else
+		time += tzoff;
+	return time;
+}
+
+ulong
+smbutime2plan9time(ulong utime, int tzoff)
+{
+	if (tzoff < 0)
+		utime += (ulong)-tzoff;
+	else
+		utime -= tzoff;
+	return utime;
+}

+ 108 - 0
sys/src/cmd/aquarela/smbtrans2client.c

@@ -0,0 +1,108 @@
+#include "headers.h"
+
+static SmbTransactionMethod method = {
+	.encodeprimary = smbtransactionencodeprimary2,
+	.sendrequest = smbtransactionclientsend,
+	.receiveresponse = smbtransactionclientreceive,
+	.decoderesponse = smbtransactiondecoderesponse2,
+};
+
+int
+smbclienttrans2(SmbClient *c, uchar scount, ushort *setup, SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata, SmbHeader *rh, char **errmsgp)
+{
+	SmbTransaction transaction;
+	SmbHeader h;
+	memset(&transaction, 0, sizeof(transaction));
+	transaction.in.scount = scount;
+	transaction.in.setup = setup;
+	transaction.in.parameters = smbbufferreadpointer(inparam);
+	transaction.in.tpcount = smbbufferreadspace(inparam);
+	transaction.in.maxpcount = smbbufferwritespace(outparam);
+	transaction.in.maxdcount = smbbufferwritespace(outdata);
+	transaction.out.parameters = outparam;
+	transaction.out.data = outdata;
+	h = c->protoh;
+	h.tid = c->sharetid;
+	h.mid = 0;
+	return smbtransactionexecute(&transaction, &h, &c->peerinfo, c->b, &method, c, rh, errmsgp);
+}
+
+int
+smbclienttrans2findfirst2(SmbClient *c, ushort searchcount, char *filename,
+	ushort *sidp, ushort *searchcountp, ushort *endofsearchp,SmbFindFileBothDirectoryInfo *ip, char **errmsgp)
+{
+	int rv;
+	ushort setup;
+	SmbBuffer *inparam;
+	SmbBuffer *outparam;
+	SmbBuffer *outdata;
+	SmbHeader rh;
+	setup = SMB_TRANS2_FIND_FIRST2;
+	inparam = smbbuffernew(512);
+	smbbufferputs(inparam, 0x16);
+	smbbufferputs(inparam, searchcount);
+	smbbufferputs(inparam, 7);
+	smbbufferputs(inparam, SMB_FIND_FILE_BOTH_DIRECTORY_INFO);
+	smbbufferputl(inparam, 0);
+	smbbufferputstring(inparam, &c->peerinfo, 0, filename);
+	outparam = smbbuffernew(10);
+	outdata = smbbuffernew(65535);
+	rv = smbclienttrans2(c, 1, &setup, inparam, outparam, outdata, &rh, errmsgp);
+	smbbufferfree(&inparam);
+	if (rv) {
+		ushort eaerroroffset, lastnameoffset;
+		ulong nextentry;
+		int i;
+
+		if (!smbbuffergets(outparam, sidp)
+			|| !smbbuffergets(outparam, searchcountp)
+			|| !smbbuffergets(outparam, endofsearchp)
+			|| !smbbuffergets(outparam, &eaerroroffset)
+			|| !smbbuffergets(outparam, &lastnameoffset)) {
+			smbstringprint(errmsgp, "smbclienttrans2findfirst2: not enough parameters returned");
+			rv = 0;
+			goto done;
+		}
+		nextentry = 0;
+smblogprint(-1, "returned data:\n");
+smblogdata(-1, smblogprint, smbbufferreadpointer(outdata), smbbufferreadspace(outdata), 256);
+		for (i = 0; i < *searchcountp; i++) {
+			SmbFindFileBothDirectoryInfo *info = ip + i;
+			ulong neo, filenamelength, easize;
+			uchar shortnamelength;
+			if (i && !smbbufferreadskipto(outdata, nextentry)) {
+			underflow:
+				smbstringprint(errmsgp, "smbclientrans2findfirst2: not enough data returned");
+				rv = 0;
+				goto done;
+			}
+			if (!smbbuffergetl(outdata, &neo))
+				goto underflow;
+			nextentry = smbbufferreadoffset(outdata) + neo - 4;
+print("neo 0x%.8lux\n", neo);
+			if (!smbbuffergetl(outdata, &info->fileindex)
+				|| !smbbuffergetv(outdata, &info->creationtime)
+				|| !smbbuffergetv(outdata, &info->lastaccesstime)
+				|| !smbbuffergetv(outdata, &info->lastwritetime)
+				|| !smbbuffergetv(outdata, &info->changetime)
+				|| !smbbuffergetv(outdata, &info->endoffile)
+				|| !smbbuffergetv(outdata, &info->allocationsize))
+				goto underflow;
+print("got here\n");
+			if (!smbbuffergetl(outdata, &info->extfileattributes)
+				|| !smbbuffergetl(outdata, &filenamelength)
+				|| !smbbuffergetl(outdata, &easize)
+				|| !smbbuffergetb(outdata, &shortnamelength)
+				|| !smbbuffergetbytes(outdata, nil, 1)
+				|| !smbbuffergetbytes(outdata, nil, 24)
+				|| !smbbuffergetstring(outdata, &rh, SMB_STRING_REVPATH, &info->filename))
+				goto underflow;
+print("got here as well\n");
+		}
+	}
+done:
+	smbbufferfree(&outparam);
+	smbbufferfree(&outdata);
+	return rv;
+}
+

+ 333 - 0
sys/src/cmd/aquarela/smbtrans2find.c

@@ -0,0 +1,333 @@
+#include "headers.h"
+#include <pool.h>
+
+void
+smbsearchfree(SmbSearch **searchp)
+{
+	SmbSearch *search = *searchp;
+	if (search) {
+		smbdircachefree(&search->dc);
+		free(search->rep);
+		free(search);
+		*searchp = nil;
+	}
+}
+
+void
+smbsearchclose(SmbSession *s, SmbSearch *search)
+{
+	if (search) {
+		smblogprintif(smbglobals.log.sids, "smbsearchclose: tid 0x%.4ux sid 0x%.4ux\n", search->t->id, search->id);
+		smbidmapremove(s->sidmap, search);
+		smbsearchfree(&search);
+	}
+}
+
+void
+smbsearchclosebyid(SmbSession *s, ushort sid)
+{
+	smbsearchclose(s,  smbidmapfind(s->sidmap, sid));
+}
+
+SmbSearch *
+smbsearchnew(SmbSession *s, SmbDirCache *dc, Reprog *r, SmbTree *t)
+{
+	SmbSearch *search;
+	if (s->sidmap == nil)
+		s->sidmap = smbidmapnew();
+	search = smbemalloc(sizeof(SmbSearch));
+	smbidmapadd(s->sidmap, search);
+	search->dc = dc;
+	search->rep = r;
+	search->t = t;
+	smblogprintif(smbglobals.log.sids, "smbsearchnew: 0x%.4ux\n", search->id);
+	return search;
+}
+
+static int
+standardflatten(SmbSession *s, SmbBuffer *b, Dir *d, ulong *nameoffsetp)
+{
+	ushort mdate, mtime;
+	ushort adate, atime;
+	ushort fnlfixupoffset;
+
+	smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
+	smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
+	if (!smbbufferputs(b, mdate)
+		|| !smbbufferputs(b, mtime)
+		|| !smbbufferputs(b, adate)
+		|| !smbbufferputs(b, atime)
+		|| !smbbufferputs(b, mdate)
+		|| !smbbufferputs(b, mtime)
+		|| !smbbufferputl(b, d->length)
+		|| !smbbufferputl(b, 512)			// ha
+		|| !smbbufferputs(b, (d->qid.type & QTDIR) ? 0x10 : 0))
+		return 0;
+	fnlfixupoffset = smbbufferwriteoffset(b);
+	if (!smbbufferputs(b, 0))
+		return 0;
+	*nameoffsetp = smbbufferwriteoffset(b);
+	if (!smbbufferputstring(b, &s->peerinfo, 0, d->name))
+		return 0;
+	return smbbufferfixuprelatives(b, fnlfixupoffset);
+}
+
+static int
+findbothflatten(SmbBuffer *b, SmbPeerInfo *p, Dir *d, ulong resumekey, ulong *nameoffsetp)
+{
+	vlong mtime, atime;
+	ulong fixup;
+
+	fixup = smbbufferwriteoffset(b);
+	mtime = smbplan9time2time(d->mtime);
+	atime = smbplan9time2time(d->atime);
+poolcheck(mainmem);
+	if (!smbbufferputl(b, 0)
+		|| !smbbufferputl(b, resumekey)
+		|| !smbbufferputv(b, mtime)
+		|| !smbbufferputv(b, atime)
+		|| !smbbufferputv(b, mtime)
+		|| !smbbufferputv(b, mtime)
+		|| !smbbufferputv(b, d->length)
+		|| !smbbufferputv(b, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))			// ha
+		|| !smbbufferputl(b, (d->qid.type & QTDIR) ? 0x10 : 0x80)
+		|| !smbbufferputl(b, smbstringlen(p, d->name))
+		|| !smbbufferputl(b, 0)
+		|| !smbbufferputb(b, 0)
+		|| !smbbufferputb(b, 0)
+		|| !smbbufferfill(b, 0, 24))
+		return 0;
+poolcheck(mainmem);
+	*nameoffsetp = smbbufferwriteoffset(b);
+	if (!smbbufferputstring(b, p, 0, d->name) || !smbbufferalignl2(b, 2))
+		return 0;
+poolcheck(mainmem);
+	return smbbufferfixuprelativeinclusivel(b, fixup);
+}
+
+static void
+populate(SmbSession *s, SmbDirCache *dc, Reprog *r, ushort informationlevel, ushort flags, ushort scount,
+	ushort *ep, ulong *nameoffsetp)
+{
+	ushort e;
+	ulong nameoffset;
+	e = 0;
+	nameoffset = 0;
+	while (dc->i < dc->n && e < scount) {
+		ulong backup;
+		int rv;
+		
+		if (!smbmatch(dc->buf[dc->i].name, r)) {
+			dc->i++;
+			continue;
+		}
+		rv = 0;
+		backup = smbbufferwriteoffset(s->transaction.out.data);
+		switch (informationlevel) {
+		case SMB_INFO_STANDARD:
+			if (flags & SMB_FIND_RETURN_RESUME_KEYS) {
+				if (!smbbufferputl(s->transaction.out.data, dc->i)) {
+					rv = 0;
+					break;
+				}
+			}
+			rv = standardflatten(s, s->transaction.out.data, dc->buf + dc->i, &nameoffset);
+			break;
+		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+			rv = findbothflatten(s->transaction.out.data, &s->peerinfo, dc->buf + dc->i, dc->i, &nameoffset);
+			break;
+		}
+		if (rv == 0) {
+			smbbufferwritebackup(s->transaction.out.data, backup);
+			break;
+		}
+		dc->i++;
+		e++;
+	}
+	*ep = e;
+	*nameoffsetp = nameoffset;
+}
+
+SmbProcessResult
+smbtrans2findfirst2(SmbSession *s, SmbHeader *h)
+{
+	SmbBuffer *b;
+	char *pattern = nil;
+	char *dir = nil;
+	char *name = nil;
+	ushort searchattributes, searchcount, flags, informationlevel;
+	ulong searchstoragetype;
+	SmbDirCache *dc = nil;
+	ushort e;
+	ulong nameoffset;
+	ushort eos;
+	SmbSearch *search;
+	SmbProcessResult pr;
+	Reprog *r = nil;
+	SmbTree *t;
+	int debug;
+
+	debug = smboptable[h->command].debug
+		|| smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug
+		|| smbglobals.log.find;
+poolcheck(mainmem);
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &searchattributes)
+		|| !smbbuffergets(b, &searchcount)
+		|| !smbbuffergets(b, &flags)
+		|| !smbbuffergets(b, &informationlevel)
+		|| !smbbuffergetl(b, &searchstoragetype)
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	smbloglock();
+	smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes);
+	smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount);
+	smblogprintif(debug, "flags: 0x%.4ux\n", flags);
+	smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel);
+	smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype);
+	smblogprintif(debug, "pattern: %s\n", pattern);
+	smblogunlock();
+	smbpathsplit(pattern, &dir, &name);
+	if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
+		smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel);
+		smbseterror(s, ERRDOS, ERRunknownlevel);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	dc = smbmkdircache(t, dir);
+	if (dc == nil) {
+		smbseterror(s, ERRDOS, ERRnoaccess);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+poolcheck(mainmem);
+	r = smbmkrep(name);
+	populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset);
+poolcheck(mainmem);
+	eos = dc->i >= dc->n;
+	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
+		smbdircachefree(&dc);
+poolcheck(mainmem);
+	if (dc) {
+		/* create a search handle */
+		search = smbsearchnew(s, dc, r, t);
+		r = nil;
+		dc = nil;
+	}
+	else
+		search = nil;
+	smbbufferputs(s->transaction.out.parameters, search ? search->id : 0);
+	smbbufferputs(s->transaction.out.parameters, e);
+	smbbufferputs(s->transaction.out.parameters, eos);
+	smbbufferputs(s->transaction.out.parameters, 0);
+	smbbufferputs(s->transaction.out.parameters, nameoffset);
+	pr = SmbProcessResultReply;
+done:
+	smbbufferfree(&b);
+	free(pattern);
+	free(dir);
+	free(name);
+	smbdircachefree(&dc);
+	free(r);
+	return pr;
+}
+
+SmbProcessResult
+smbtrans2findnext2(SmbSession *s, SmbHeader *h)
+{
+	SmbBuffer *b;
+	int debug;
+	ushort sid, scount, infolevel;
+	ulong resumekey;
+	ushort flags;
+	char *filename = nil;
+	SmbProcessResult pr;
+	ushort e;
+	ulong nameoffset;
+	ushort eos;
+	SmbTree *t;
+	SmbSearch *search;
+
+	debug = smboptable[h->command].debug
+		|| smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug
+		|| smbglobals.log.find;
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &sid)
+		|| !smbbuffergets(b, &scount)
+		|| !smbbuffergets(b, &infolevel)
+		|| !smbbuffergetl(b, &resumekey)
+		|| !smbbuffergets(b, &flags)
+		|| !smbbuffergetstring(b, h, 0, &filename)) {
+		pr = SmbProcessResultFormat;
+		goto done;
+	}
+	smblogprintif(debug,
+		"smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n",
+		sid, scount, infolevel, resumekey, flags, filename);
+
+	if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
+		smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel);
+		smbseterror(s, ERRDOS, ERRunknownlevel);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	search = smbidmapfind(s->sidmap, sid);
+	if (search == nil) {
+		smbseterror(s, ERRDOS, ERRnofiles);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	if (search->t != t) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	if ((flags & (1 << 3)) == 0) {
+		long i;
+		if (filename == nil) {
+			smbseterror(s, ERRDOS, ERRnofiles);
+			pr = SmbProcessResultError;
+			goto done;
+		}
+		for (i = 0; i < search->dc->n; i++)
+			if (strcmp(search->dc->buf[i].name, filename) == 0) {
+				search->dc->i = i + 1;
+				break;
+			}
+	}
+
+	populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset);
+	
+	eos = search->dc->i >= search->dc->n;
+	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
+		smbsearchclose(s, search);
+	smbbufferputs(s->transaction.out.parameters, e);
+	smbbufferputs(s->transaction.out.parameters, eos);
+	smbbufferputs(s->transaction.out.parameters, 0);
+	smbbufferputs(s->transaction.out.parameters, nameoffset);
+	pr = SmbProcessResultReply;
+done:
+	smbbufferfree(&b);
+	free(filename);
+	return pr;
+}

+ 235 - 0
sys/src/cmd/aquarela/smbtrans2query.c

@@ -0,0 +1,235 @@
+#include "headers.h"
+
+static SmbProcessResult
+query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
+{
+	vlong ntatime, ntmtime;
+	ushort dosmode;
+	ulong fnlfixupoffset;
+	vlong allocsize;
+
+	if (d == nil) {
+		smbseterror(s, ERRDOS, ERRbadfile);
+		return SmbProcessResultError;
+	}
+
+	switch (infolevel) {
+	case SMB_QUERY_FILE_BASIC_INFO:
+		ntatime = smbplan9time2time(d->atime);
+		ntmtime = smbplan9time2time(d->mtime);
+		dosmode = smbplan9mode2dosattr(d->mode);
+		if (!smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputv(s->transaction.out.data, ntatime)
+			|| !smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputl(s->transaction.out.data, dosmode))
+//			|| !smbbufferputl(s->transaction.out.data, 0))
+			return SmbProcessResultMisc;
+		break;
+	case SMB_QUERY_FILE_ALL_INFO:
+		ntatime = smbplan9time2time(d->atime);
+		ntmtime = smbplan9time2time(d->mtime);
+		dosmode = smbplan9mode2dosattr(d->mode);
+		allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
+		if (!smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputv(s->transaction.out.data, ntatime)
+			|| !smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputv(s->transaction.out.data, ntmtime)
+			|| !smbbufferputs(s->transaction.out.data, dosmode)
+			|| !smbbufferputbytes(s->transaction.out.data, nil, 6)
+			|| !smbbufferputv(s->transaction.out.data, allocsize)
+			|| !smbbufferputv(s->transaction.out.data, d->length)
+			|| !smbbufferputl(s->transaction.out.data, 0)		// hard links - ha
+			|| !smbbufferputb(s->transaction.out.data, 0)		// TODO delete pending
+			|| !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
+			|| !smbbufferputv(s->transaction.out.data, d->qid.path)
+			|| !smbbufferputl(s->transaction.out.data, 0)		// EA size
+			|| !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
+			|| !smbbufferputv(s->transaction.out.data, cbo)
+			|| !smbbufferputs(s->transaction.out.data, dosmode)
+			|| !smbbufferputl(s->transaction.out.data, 0))	// alignment
+			return SmbProcessResultMisc;
+		fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
+		if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
+			|| !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
+			return SmbProcessResultMisc;
+		break;
+	case SMB_QUERY_FILE_STANDARD_INFO:
+		if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
+			|| !smbbufferputv(s->transaction.out.data, d->length)
+			|| !smbbufferputl(s->transaction.out.data, 1)
+			|| !smbbufferputb(s->transaction.out.data, 0)
+			|| !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
+			return SmbProcessResultMisc;
+		break;
+	case SMB_QUERY_FILE_EA_INFO:
+		if (!smbbufferputl(s->transaction.out.data, 0))
+			return SmbProcessResultMisc;
+		break;
+	case SMB_QUERY_FILE_STREAM_INFO:
+		/* don't do it, never will */
+		goto unknownlevel;
+	default:
+		smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
+	unknownlevel:
+		smbseterror(s, ERRDOS, ERRunknownlevel);
+		return SmbProcessResultError;
+	}
+	return SmbProcessResultReply;
+}
+
+SmbProcessResult
+smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
+{
+	SmbTree *t;
+	SmbBuffer *b = nil;
+	SmbProcessResult pr;
+	ushort infolevel;
+	Dir *d;
+	char *path = nil;
+	char *fullpath;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
+		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	smblogprintif(smbglobals.log.query, "infolevel 0x%.4ux\n", infolevel);
+	smblogprintif(smbglobals.log.query, "path %s\n", path);
+	fullpath = nil;
+	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
+	smblogprintif(smbglobals.log.query, "fullpath %s\n", fullpath);
+	d = dirstat(fullpath);
+	pr = query(s, "path", path, infolevel, 0, d);
+	free(d);
+	free(fullpath);
+done:
+	free(path);
+	smbbufferfree(&b);
+	return pr;
+}
+
+SmbProcessResult
+smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
+{
+	SmbTree *t;
+	SmbFile *f;
+	SmbBuffer *b = nil;
+	SmbProcessResult pr;
+	ushort fid;
+	ushort infolevel;
+	Dir *d;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	smblogprintif(smbglobals.log.query, "fid 0x%.4ux\n", fid);
+	smblogprintif(smbglobals.log.query, "infolevel 0x%.4ux\n", infolevel);
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	d = dirfstat(f->fd);
+	pr = query(s, "file", f->name, infolevel, seek(f->fd, 0, 1), d);
+	free(d);
+done:
+	smbbufferfree(&b);
+	return pr;
+}
+
+SmbProcessResult
+smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
+{
+	SmbTree *t;
+	ushort infolevel;
+	SmbBuffer *b;
+	SmbProcessResult pr;
+	ulong fixup;
+	ulong vnbase;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &infolevel)) {
+	misc:
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+	pr = SmbProcessResultReply;
+	switch (infolevel) {
+	case SMB_INFO_ALLOCATION:
+		if (!smbbufferputl(s->transaction.out.data, 0)
+			|| !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
+			|| !smbbufferputl(s->transaction.out.data, 0xffffffff)
+			|| !smbbufferputl(s->transaction.out.data, 0xffffffff)
+			|| !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
+			goto misc;
+		break;
+	case SMB_INFO_VOLUME:
+		if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
+			|| !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
+			goto misc;
+		break;
+	case SMB_QUERY_FS_VOLUME_INFO:
+		if (!smbbufferputv(s->transaction.out.data, 0)
+			|| !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
+			goto misc;
+		fixup = smbbufferwriteoffset(s->transaction.out.data);
+		if (!smbbufferputl(s->transaction.out.data, 0)
+			|| !smbbufferputs(s->transaction.out.data, 0))
+			goto misc;
+		vnbase = smbbufferwriteoffset(s->transaction.out.data);
+		if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
+			|| !smbbufferfixupl(s->transaction.out.data, fixup,
+				smbbufferwriteoffset(s->transaction.out.data) - vnbase))
+			goto misc;
+		break;
+	case SMB_QUERY_FS_SIZE_INFO:
+		if (!smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
+			|| !smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
+			|| !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
+			|| !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
+			goto misc;
+		break;
+	case SMB_QUERY_FS_ATTRIBUTE_INFO:
+//print("doing attribute info\n");
+		if (!smbbufferputl(s->transaction.out.data, 3)
+			|| !smbbufferputl(s->transaction.out.data, 255))
+			goto misc;
+		fixup = smbbufferwriteoffset(s->transaction.out.data);
+		if (!smbbufferputl(s->transaction.out.data, 0)
+			|| !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
+			|| !smbbufferfixuprelativel(s->transaction.out.data, fixup))
+			goto misc;
+//print("done attribute info\n");
+		break;
+	default:
+		smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
+		smbseterror(s, ERRDOS, ERRunknownlevel);
+		pr = SmbProcessResultError;
+	}
+done:
+	smbbufferfree(&b);
+	return pr;
+}

+ 100 - 0
sys/src/cmd/aquarela/smbtrans2set.c

@@ -0,0 +1,100 @@
+#include "headers.h"
+
+SmbProcessResult
+smbtrans2setfileinformation(SmbSession *s, SmbHeader *h)
+{
+	SmbTree *t;
+	ushort infolevel;
+	SmbBuffer *b;
+	SmbProcessResult pr;
+	ushort fid;
+	SmbFile *f;
+	vlong newsize;
+	uvlong atime, mtime;
+	ulong attr;
+	ulong mode;
+
+	t = smbidmapfind(s->tidmap, h->tid);
+	if (t == nil) {
+		smbseterror(s, ERRSRV, ERRinvtid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
+	if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
+	misc:
+		pr = SmbProcessResultMisc;
+		goto done;
+	}
+
+	f = smbidmapfind(s->fidmap, fid);
+	if (f == nil) {
+		smbseterror(s, ERRDOS, ERRbadfid);
+		pr = SmbProcessResultError;
+		goto done;
+	}
+
+	switch (infolevel) {
+	case SMB_SET_FILE_ALLOCATION_INFO:
+	case SMB_SET_FILE_END_OF_FILE_INFO:
+		if (s->transaction.in.tdcount < 8)
+			goto misc;
+		newsize = smbnhgetv(s->transaction.in.data);
+		pr = smbtruncatefile(s, f, newsize);
+		if (pr == SmbProcessResultReply && !smbbufferputs(s->transaction.out.parameters, 0))
+			goto misc;
+		break;
+
+	case SMB_SET_FILE_BASIC_INFO:
+		if (s->transaction.in.tdcount < 4 * 8 + 4)
+			goto misc;
+		atime = smbnhgetv(s->transaction.in.data + 8);
+		mtime = smbnhgetv(s->transaction.in.data + 24);
+		attr = smbnhgetv(s->transaction.in.data + 32);
+		if (attr) {
+			Dir *od = dirfstat(f->fd);
+			if (od == nil)
+				goto noaccess;
+			mode = smbdosattr2plan9wstatmode(od->mode, attr);
+			free(od);
+		}
+		else
+			mode = 0xffffffff;
+		if (atime || mtime || mode != 0xffffffff) {
+			Dir d;
+			memset(&d, 0xff, sizeof(d));
+			d.name = d.uid = d.gid = d.muid = nil;
+			if (atime)
+				d.atime = smbtime2plan9time(atime);
+			if (mtime)
+				d.mtime = smbtime2plan9time(mtime);
+			d.mode = mode;
+			if (dirfwstat(f->fd, &d) < 0) {
+			noaccess:
+				smbseterror(s, ERRDOS, ERRnoaccess);
+				pr = SmbProcessResultError;
+				goto done;
+			}
+		}
+		if (!smbbufferputs(s->transaction.out.parameters, 0))
+			goto misc;
+		pr = SmbProcessResultReply;
+		break;
+
+	case SMB_SET_FILE_DISPOSITION_INFO:
+		if (s->transaction.in.tdcount < 1)
+			goto misc;
+		f->sf->deleteonclose = *s->transaction.in.data;
+		pr = SmbProcessResultReply;
+		break;
+
+	default:
+		smblogprint(-1, "smbtrans2setfileinformation: infolevel 0x%.4ux not implemented\n", infolevel);
+		smbseterror(s, ERRDOS, ERRunknownlevel);
+		pr = SmbProcessResultError;
+		break;
+	}
+done:
+	smbbufferfree(&b);
+	return pr;
+}

+ 507 - 0
sys/src/cmd/aquarela/smbtransaction.c

@@ -0,0 +1,507 @@
+#include "headers.h"
+
+typedef struct Args Args;
+
+struct Args {
+	ulong pcount;
+	ulong poffset;
+	ulong pdisplacement;
+	ulong dcount;
+	ulong doffset;
+	ulong ddisplacement;
+	uchar scount;
+};
+
+int
+_smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, int hasname, char **errmsgp)
+{
+	ushort poffset, doffset;
+
+	if (h->wordcount < 14) {
+		smbstringprint(errmsgp, "word count less than 14");
+		return -1;
+	}
+	t->in.scount = pdata[13 * 2];
+	if (h->wordcount != 14 + t->in.scount) {
+		smbstringprint(errmsgp, "smbcomtransaction: word count invalid\n");
+		return -1;
+	}
+	t->in.tpcount = smbnhgets(pdata); pdata += 2;
+	t->in.tdcount = smbnhgets(pdata); pdata += 2;
+	t->in.maxpcount = smbnhgets(pdata); pdata += 2;
+	t->in.maxdcount = smbnhgets(pdata); pdata += 2;
+	t->in.maxscount = *pdata++;
+	pdata++;
+	t->in.flags = smbnhgets(pdata); pdata += 2;
+	pdata += 4; /* timeout */
+	pdata += 2;
+	t->in.pcount = smbnhgets(pdata); pdata += 2;
+	poffset = smbnhgets(pdata); pdata += 2;
+	t->in.dcount = smbnhgets(pdata); pdata += 2;
+	doffset = smbnhgets(pdata); pdata += 2;
+	pdata++; /* scount */
+	pdata++; /* reserved */
+	smbfree(&t->in.setup);
+	if (t->in.scount) {
+		int x;
+		t->in.setup = smbemalloc(t->in.scount * sizeof(ushort));
+		for (x = 0; x < t->in.scount; x++) {
+			t->in.setup[x] = smbnhgets(pdata);
+			pdata += 2;
+		}
+	}
+	smbfree(&t->in.name);
+	if (hasname && !smbbuffergetstring(b, h, SMB_STRING_PATH, &t->in.name)) {
+		smbstringprint(errmsgp, "not enough bdata for name");
+		return -1;
+	}
+	if (poffset + t->in.pcount > smbbufferwriteoffset(b)) {
+		smbstringprint(errmsgp, "not enough bdata for parameters");
+		return -1;
+	}
+	if (t->in.pcount > t->in.tpcount) {
+		smbstringprint(errmsgp, "too many parameters");
+		return -1;
+	}
+	smbfree(&t->in.parameters);
+	t->in.parameters = smbemalloc(t->in.tpcount);
+	memcpy(t->in.parameters, smbbufferpointer(b, poffset), t->in.pcount);
+	if (doffset + t->in.dcount > smbbufferwriteoffset(b)) {
+		smbstringprint(errmsgp, "not enough bdata for data");
+		return -1;
+	}
+	if (t->in.dcount > t->in.tdcount) {
+		smbstringprint(errmsgp, "too much data");
+		return -1;
+	}
+	smbfree(&t->in.data);
+	t->in.data = smbemalloc(t->in.tdcount);
+	memcpy(t->in.data, smbbufferpointer(b, doffset), t->in.dcount);
+	if (t->in.dcount < t->in.tdcount || t->in.pcount < t->in.tpcount)
+		return 0;
+	return 1;
+}
+
+int
+decoderesponse(SmbTransaction *t, Args *a, SmbBuffer *b, char **errmsgp)
+{
+	if (t->out.tpcount > smbbufferwritemaxoffset(t->out.parameters)) {
+		smbstringprint(errmsgp, "decoderesponse: too many parameters for buffer");
+		return 0;
+	}
+	if (t->out.tdcount > smbbufferwritemaxoffset(t->out.data)) {
+		smbstringprint(errmsgp, "decoderesponse: too much data for buffer");
+		return 0;
+	}
+	if (a->pdisplacement + a->pcount > t->out.tpcount) {
+		smbstringprint(errmsgp, "decoderesponse: more parameters than tpcount");
+		return 0;
+	}
+	if (a->pdisplacement != smbbufferwriteoffset(t->out.parameters)) {
+		smbstringprint(errmsgp, "decoderesponse: parameter displacement inconsistent");
+		return 0;
+	}
+	if (a->ddisplacement + a->dcount > t->out.tdcount) {
+		smbstringprint(errmsgp, "decoderesponse: more data than tdcount");
+		return 0;
+	}
+	if (a->ddisplacement != smbbufferwriteoffset(t->out.data)) {
+		smbstringprint(errmsgp, "decoderesponse: data displacement inconsistent");
+		return 0;
+	}
+	assert(a->scount == 0);
+	if (a->pcount) {
+		if (!smbbufferreadskipto(b, a->poffset)) {
+			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid parameter offset");
+			return 0;
+		}
+		if (!smbbuffercopy(t->out.parameters, b, a->pcount)) {
+			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for parameters");
+			return 0;
+		}
+	}
+	if (a->dcount) {
+		if (!smbbufferreadskipto(b, a->doffset)) {
+			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid data offset");
+			return 0;
+		}
+		if (!smbbuffercopy(t->out.data, b, a->dcount)) {
+			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for data");
+			return 0;
+		}
+	}
+	return 1;
+}
+
+int
+smbtransactiondecoderesponse(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp)
+{
+	Args a;
+
+	if (h->command != SMB_COM_TRANSACTION) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse: not an SMB_COM_TRANSACTION");
+		return 0;
+	}
+	if (h->wordcount < 10) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse: word count less than 10");
+		return -1;
+	}
+	t->out.tpcount = smbnhgets(pdata); pdata += 2;
+	t->out.tdcount = smbnhgets(pdata); pdata += 2;
+	pdata += 2;
+	a.pcount = smbnhgets(pdata); pdata += 2;
+	a.poffset =  smbnhgets(pdata); pdata += 2;
+	a.pdisplacement = smbnhgets(pdata); pdata += 2;
+	a.dcount = smbnhgets(pdata); pdata += 2;
+	a.doffset =  smbnhgets(pdata); pdata += 2;
+	a.ddisplacement = smbnhgets(pdata); pdata += 2;
+	a.scount = *pdata;
+	if (a.scount != h->wordcount - 10) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse: scount inconsistent");
+		return 0;
+	}
+	return decoderesponse(t, &a, b, errmsgp);
+}
+
+int
+smbtransactiondecoderesponse2(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp)
+{
+	Args a;
+
+	if (h->command != SMB_COM_TRANSACTION2) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: not an SMB_COM_TRANSACTION2");
+		return 0;
+	}
+	if (h->wordcount < 10) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: word count less than 10");
+		return -1;
+	}
+	t->out.tpcount = smbnhgets(pdata); pdata += 2;
+	t->out.tdcount = smbnhgets(pdata); pdata += 2;
+	pdata += 2;
+	a.pcount = smbnhgets(pdata); pdata += 2;
+	a.poffset =  smbnhgets(pdata); pdata += 2;
+	a.pdisplacement = smbnhgets(pdata); pdata += 2;
+	a.dcount = smbnhgets(pdata); pdata += 2;
+	a.doffset =  smbnhgets(pdata); pdata += 2;
+	a.ddisplacement = smbnhgets(pdata); pdata += 2;
+	a.scount = *pdata;
+	if (a.scount != h->wordcount - 10) {
+		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: scount inconsistent");
+		return 0;
+	}
+	return decoderesponse(t, &a, b, errmsgp);
+}
+
+int
+smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp)
+{
+	return _smbtransactiondecodeprimary(t, h, pdata, b, 1, errmsgp);
+}
+
+int
+smbtransactiondecodeprimary2(SmbTransaction *t, SmbHeader *h, uchar *pdata, SmbBuffer *b, char **errmsgp)
+{
+	return _smbtransactiondecodeprimary(t, h, pdata, b, 0, errmsgp);
+}
+
+void
+smbtransactionfree(SmbTransaction *t)
+{
+	free(t->in.parameters);
+	free(t->in.data);
+	free(t->in.setup);
+	free(t->in.name);
+	smbbufferfree(&t->out.parameters);
+	smbbufferfree(&t->out.data);
+}
+
+static int
+_transactionencodeprimary(SmbTransaction *t, uchar cmd, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	uchar *wordcountp, ushort *bytecountp, char **errmsgp)
+{
+	SmbHeader mh;
+	ulong countsfixupoffset, bytecountfixupoffset;
+	int x;
+	mh = *h;
+	*wordcountp = mh.wordcount = 14 + t->in.scount;
+	mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
+	mh.command = cmd;
+	if (!smbbufferputheader(ob, &mh, p)) {
+	toosmall:
+		smbstringprint(errmsgp, "output buffer too small");
+		return 0;
+	}
+	if (t->in.tpcount > 65535 || t->in.tdcount > 65535 || t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
+		smbstringprint(errmsgp, "counts too big");
+		return 0;
+	}
+	if (!smbbufferputs(ob, t->in.tpcount)
+		|| !smbbufferputs(ob, t->in.tdcount)
+		|| !smbbufferputs(ob, t->in.maxpcount)
+		|| !smbbufferputs(ob, t->in.maxdcount)
+		|| !smbbufferputb(ob, t->in.maxscount)
+		|| !smbbufferputb(ob, 0)
+		|| !smbbufferputs(ob, t->in.flags)
+		|| !smbbufferputl(ob, 0)
+		|| !smbbufferputs(ob, 0))
+		goto toosmall;
+	countsfixupoffset = smbbufferwriteoffset(ob);
+	if (!smbbufferputs(ob, 0)
+		|| !smbbufferputs(ob, 0)
+		|| !smbbufferputs(ob, 0)
+		|| !smbbufferputs(ob, 0))
+		goto toosmall;
+	if (!smbbufferputb(ob, t->in.scount)
+		|| !smbbufferputb(ob, 0))
+		goto toosmall;
+	for (x = 0; x < t->in.scount; x++)
+		if (!smbbufferputs(ob, t->in.setup[x]))
+			goto toosmall;
+	bytecountfixupoffset = smbbufferwriteoffset(ob);
+	if (!smbbufferputs(ob, 0))
+		goto toosmall;
+	smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
+	if (!smbbufferputstring(ob, p, SMB_STRING_UPCASE, t->in.name))
+		goto toosmall;
+	if (t->in.pcount < t->in.tpcount) {
+		ulong align = smbbufferwriteoffset(ob) & 1;
+		ulong pthistime;
+		pthistime = smbbufferwritespace(ob) - align;
+		if (pthistime > t->in.tpcount - t->in.pcount)
+			pthistime = t->in.tpcount - t->in.pcount;
+		if (pthistime > 65535)
+			pthistime = 65535;
+		if (smbbufferwriteoffset(ob) > 65535)
+			pthistime = 0;
+		if (pthistime) {
+			assert(smbbufferalignl2(ob, 0));
+			assert(smbbufferoffsetputs(ob, countsfixupoffset, pthistime));
+			assert(smbbufferoffsetputs(ob, countsfixupoffset + 2, smbbufferwriteoffset(ob)));
+			assert(smbbufferputbytes(ob, t->in.parameters + t->in.pcount, pthistime));
+		}
+		t->in.pcount += pthistime;
+	}
+	if (t->in.dcount < t->in.tdcount) {
+		ulong align = smbbufferwriteoffset(ob) & 1;
+		ulong dthistime;
+		dthistime = smbbufferwritespace(ob) - align;
+		if (dthistime > t->in.tdcount - t->in.dcount)
+			dthistime = t->in.tdcount - t->in.dcount;
+		if (dthistime > 65535)
+			dthistime = 65535;
+		if (smbbufferwriteoffset(ob) > 65535)
+			dthistime = 0;
+		if (dthistime) {
+			assert(smbbufferalignl2(ob, 0));
+			assert(smbbufferoffsetputs(ob, countsfixupoffset + 4, dthistime));
+			assert(smbbufferoffsetputs(ob, countsfixupoffset + 6, smbbufferwriteoffset(ob)));
+			assert(smbbufferputbytes(ob, t->in.data + t->in.dcount, dthistime));
+		}
+		t->in.dcount += dthistime;
+	}
+	*bytecountp = smbbufferwriteoffset(ob) - bytecountfixupoffset - 2;
+	assert(smbbufferoffsetputs(ob, bytecountfixupoffset, *bytecountp));
+	return 1;
+}
+
+int
+smbtransactionencodeprimary(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	uchar *wordcountp, ushort *bytecountp, char **errmsgp)
+{
+	return _transactionencodeprimary(t, SMB_COM_TRANSACTION, h, p,ob, wordcountp, bytecountp, errmsgp);
+};
+
+int
+smbtransactionencodeprimary2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
+	uchar *wordcountp, ushort *bytecountp, char **errmsgp)
+{
+	return _transactionencodeprimary(t, SMB_COM_TRANSACTION2, h, p,ob, wordcountp, bytecountp, errmsgp);
+};
+
+int
+_transactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, uchar cmd,
+	char **errmsgp)
+{
+	SmbHeader mh;
+	ulong countsfixupoffset, bytecountfixupoffset;
+	int palign, dalign;
+	ulong pbytecount, dbytecount;
+	ulong poffset, doffset;
+
+	if (t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
+		smbstringprint(errmsgp, "counts too big");
+		return 0;
+	}
+	mh = *h;
+	mh.wordcount = 10;
+	mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
+	mh.command = cmd;
+	mh.errclass = SUCCESS;
+	mh.error = SUCCESS;
+	if (!smbbufferputheader(ob, &mh, p)
+		|| !smbbufferputs(ob, smbbufferwriteoffset(t->out.parameters))
+		|| !smbbufferputs(ob, smbbufferwriteoffset(t->out.data))
+		|| !smbbufferputs(ob, 0)) {
+	toosmall:
+		smbstringprint(errmsgp, "output buffer too small");
+		goto toosmall;
+	}
+	countsfixupoffset = smbbufferwriteoffset(ob);
+	if (!smbbufferputbytes(ob, nil, 6 * sizeof(ushort))
+		|| !smbbufferputb(ob, 0)	// scount == 0
+		|| !smbbufferputb(ob, 0))	// reserved2
+		goto toosmall;
+	/* now the byte count */
+	bytecountfixupoffset = smbbufferwriteoffset(ob);
+	if (!smbbufferputs(ob, 0))
+		goto toosmall;
+	smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
+	palign = bytecountfixupoffset & 1;
+	if (palign && !smbbufferputb(ob, 0))
+		goto toosmall;
+	pbytecount = smbbufferreadspace(t->out.parameters);
+	if (pbytecount > smbbufferwritespace(ob))
+		pbytecount = smbbufferwritespace(ob);
+	poffset = smbbufferwriteoffset(ob);
+	if (poffset > 65535)
+		goto toosmall;
+	if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.parameters), pbytecount))
+		goto toosmall;
+	dalign = smbbufferwritespace(ob) > 0 && (smbbufferwriteoffset(ob) & 1) != 0;
+	if (dalign && !smbbufferputb(ob, 0))
+		goto toosmall;
+	dbytecount = smbbufferreadspace(t->out.data);
+	if (dbytecount > smbbufferwritespace(ob))
+		dbytecount = smbbufferwritespace(ob);
+	doffset = smbbufferwriteoffset(ob);
+	if (doffset > 65535)
+		goto toosmall;
+	if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.data), dbytecount))
+		goto toosmall;
+	if (!smbbufferoffsetputs(ob, bytecountfixupoffset, palign + pbytecount + dalign + dbytecount)
+		|| !smbbufferoffsetputs(ob, countsfixupoffset, pbytecount)
+		|| !smbbufferoffsetputs(ob, countsfixupoffset + 2, poffset)
+		|| !smbbufferoffsetputs(ob, countsfixupoffset + 4, smbbufferreadoffset(t->out.parameters))
+		|| !smbbufferoffsetputs(ob, countsfixupoffset + 6, dbytecount)
+		|| !smbbufferoffsetputs(ob, countsfixupoffset + 8, doffset)
+		|| !smbbufferoffsetputs(ob, countsfixupoffset + 10, smbbufferreadoffset(t->out.data)))
+		goto toosmall;
+	assert(smbbufferoffsetputs(ob, bytecountfixupoffset, smbbufferwriteoffset(ob) - bytecountfixupoffset - 2));
+	smbbuffergetbytes(t->out.parameters, nil, pbytecount);
+	smbbuffergetbytes(t->out.data, nil, dbytecount);
+	return 1;
+}
+
+int
+smbtransactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, char **errmsgp)
+{
+	return _transactionencoderesponse(t, h, p, ob, SMB_COM_TRANSACTION, errmsgp);
+}
+
+int
+smbtransactionencoderesponse2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, char **errmsgp)
+{
+	return _transactionencoderesponse(t, h, p, ob, SMB_COM_TRANSACTION2, errmsgp);
+}
+
+int
+smbtransactionrespond(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, SmbTransactionMethod *method, void *magic, char **errmsgp)
+{
+	/* generate one or more responses */
+	while (smbbufferreadspace(t->out.parameters) || smbbufferreadspace(t->out.data)) {
+		assert(method->encoderesponse);
+		if (!(*method->encoderesponse)(t, h, p, ob, errmsgp))
+			return 0;
+		assert(method->sendresponse);
+		if (!(*method->sendresponse)(magic, ob, errmsgp))
+			return 0;
+	}
+	return 1;
+}
+
+int
+smbtransactionnbdgramsend(void *magic, SmbBuffer *ob, char **errmsgp)
+{
+	NbDgramSendParameters *p = magic;
+//print("sending to %B\n", p->to);
+//nbdumpdata(smbbufferreadpointer(ob), smbbufferreadspace(ob));
+	if (!nbdgramsend(p, smbbufferreadpointer(ob), smbbufferreadspace(ob))) {
+		smbstringprint(errmsgp, "dgram send failed");
+		return 0;
+	}
+	return 1;
+}
+
+SmbTransactionMethod smbtransactionmethoddgram = {
+	.encodeprimary = smbtransactionencodeprimary,
+	.sendrequest = smbtransactionnbdgramsend,
+	.encoderesponse = smbtransactionencoderesponse,
+};
+
+int
+smbtransactionexecute(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *iob, SmbTransactionMethod *method, void *magic, SmbHeader *rhp, char **errmsgp)
+{
+	uchar sentwordcount;
+	ushort sentbytecount;
+	SmbHeader rh;
+	smbbufferreset(iob);
+	if (!(*method->encodeprimary)(t, h, p, iob, &sentwordcount, &sentbytecount, errmsgp))
+		return 0;
+//	smblogprint(-1, "sent...\n");
+//	smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
+	if (!(*method->sendrequest)(magic, iob, errmsgp))
+		return 0;
+	if (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount) {
+		uchar wordcount;
+		ushort bytecount;
+		/* secondary needed */
+		if (method->encodesecondary == nil || method->receiveintermediate == nil) {
+			smbstringprint(errmsgp, "buffer too small and secondaries not allowed");
+			return 0;
+		}
+		if (!(*method->receiveintermediate)(magic, &wordcount, &bytecount, errmsgp))
+			return 0;
+		if (sentwordcount != wordcount || sentbytecount != bytecount) {
+			smbstringprint(errmsgp, "server intermediate reply counts differ");
+			return 0;
+		}
+		do {
+			if (!(*method->encodesecondary)(t, h, iob, errmsgp))
+				return 0;
+			if (!(*method->sendrequest)(magic, iob, errmsgp))
+				return 0;
+		} while (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount);
+	}
+	if (method->receiveresponse == nil || method->decoderesponse == nil)
+		return 1;
+	do {
+		uchar *pdata;
+		ushort bytecount;
+
+		if (!(*method->receiveresponse)(magic, iob, errmsgp))
+			return 0;
+		if (!smbbuffergetheader(iob, &rh, &pdata, &bytecount)) {
+			smbstringprint(errmsgp, "smbtransactionexecute: invalid response header");
+			return 0;
+		}
+		if (!smbcheckheaderdirection(&rh, 1, errmsgp))
+			return 0;
+		if (rh.errclass != SUCCESS) {
+			smbstringprint(errmsgp, "smbtransactionexecute: remote error %d/%d", rh.errclass, rh.error);
+			return 0;
+		}
+		if (!smbbuffertrimreadlen(iob, bytecount)) {
+			smbstringprint(errmsgp, "smbtransactionexecute: invalid bytecount");
+			return 0;
+		}
+//		smblogprint(-1, "received...\n");
+//		smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
+		if (!(*method->decoderesponse)(t, &rh, pdata, iob, errmsgp))
+			return 0;
+	} while (smbbufferwriteoffset(t->out.parameters) < t->out.tpcount || smbbufferwriteoffset(t->out.data) < t->out.tdcount);
+	if (rhp)
+		*rhp = rh;
+	return 1;
+}
+

+ 73 - 0
sys/src/cmd/aquarela/smbtree.c

@@ -0,0 +1,73 @@
+#include "headers.h"
+
+typedef struct DisconnectData {
+	SmbSession *s;
+	SmbTree *t;
+} DisconnectData;
+
+static void
+smbtreefree(SmbTree **tp)
+{
+	SmbTree *t = *tp;
+	if (t) {
+		smbserviceput(t->serv);
+		free(t);
+		*tp = nil;
+	}
+}
+
+static void
+closesearch(void *magic, void *a)
+{
+	SmbSearch *search = a;
+	DisconnectData *d = magic;
+	if (search->t == d->t)
+		smbsearchclose(d->s, search);
+}
+
+static void
+closefile(void *magic, void *a)
+{
+	SmbFile *f = a;
+	DisconnectData *d = magic;
+	if (f->t == d->t)
+		smbfileclose(d->s, f);
+}
+
+void
+smbtreedisconnect(SmbSession *s, SmbTree *t)
+{
+	if (t) {
+		DisconnectData data;
+		smblogprintif(smbglobals.log.tids, "smbtreedisconnect: 0x%.4ux\n", t->id);
+		data.s = s;
+		data.t = t;
+		smbserviceput(t->serv);
+		smbidmapapply(s->sidmap, closesearch, &data);
+		smbidmapapply(s->fidmap, closefile, &data);
+		smbidmapremove(s->tidmap, t);
+		smbtreefree(&t);
+	}
+}
+
+void
+smbtreedisconnectbyid(SmbSession *s, ushort id)
+{
+	smbtreedisconnect(s, smbidmapfind(s->tidmap, id));
+}
+
+SmbTree *
+smbtreeconnect(SmbSession *s, SmbService *serv)
+{
+	SmbTree *t;
+
+	if (s->tidmap == nil)
+		s->tidmap = smbidmapnew();
+
+	t = smbemallocz(sizeof(*t), 1);
+	smbidmapadd(s->tidmap, t);
+	t->serv = serv;
+	smbserviceget(serv);
+	smblogprintif(smbglobals.log.tids, "smbtreeconnect: 0x%.4ux\n", t->id);
+	return t;
+}

+ 56 - 0
sys/src/cmd/aquarela/testconnect.c

@@ -0,0 +1,56 @@
+#include "headers.h"
+
+void
+threadmain(int argc, char *argv[])
+{
+	SmbClient *c;
+	char *errmsg;
+	if (argc != 2 && argc != 3) {
+		print("usage: testconnect to [share]\n");
+		exits("args");
+	}
+	smbglobalsguess(1);
+	errmsg = nil;
+	c = smbconnect(argv[1], argc == 3 ? argv[2] : nil, &errmsg);
+	if (c) {
+		int i, rv;
+		int entries;
+		SmbRapServerInfo1 *si = nil;
+		SmbFindFileBothDirectoryInfo ip[10];
+		char *errmsg;
+		ushort sid, searchcount, endofsearch;
+		errmsg = nil;
+		rv = smbnetserverenum2(c, SV_TYPE_SERVER, "PLAN9", &entries, &si, &errmsg);
+		if (rv < 0)
+			print("error: %s\n", errmsg);
+		else if (rv > 0)
+			print("error code %d\n", rv);
+		else
+			for (i = 0; i < entries; i++)
+				print("%s: %d.%d 0x%.8lux %s\n", si[i].name, si[i].vmaj, si[i].vmin, si[i].type, si[i].remark);
+		free(si);
+		if (rv == 0) {
+			rv = smbnetserverenum2(c, SV_TYPE_DOMAIN_ENUM, nil, &entries, &si, &errmsg);
+			if (rv < 0)
+				print("error: %s\n", errmsg);
+			else if (rv > 0)
+				print("error code %d\n", rv);
+			else
+				for (i = 0; i < entries; i++)
+					print("%s: %d.%d 0x%.8lux %s\n", si[i].name, si[i].vmaj, si[i].vmin, si[i].type, si[i].remark);
+			free(si);
+		}
+		rv = smbclienttrans2findfirst2(c, nelem(ip), "\\LICENSE",
+			&sid, &searchcount, &endofsearch, ip, &errmsg);
+		if (rv) {
+			print("sid 0x%.4ux\n", sid);
+			print("searchcount 0x%.4ux\n", searchcount);
+			print("endofsearch 0x%.4ux\n", endofsearch);
+		}
+		else
+			print("search failed %s\n", errmsg);
+		smbclientfree(c);
+	}
+	else
+		print("failed to connect: %s\n", errmsg);
+}

+ 114 - 0
sys/src/cmd/aquarela/testnbdgram.c

@@ -0,0 +1,114 @@
+#include "headers.h"
+
+static int
+deliver(void *, NbDgram *s)
+{
+	SmbHeader h;
+	uchar *pdata;
+	ushort bytecount;
+	SmbBuffer *b;
+	char *errmsg;
+	SmbTransaction transaction;
+	int rv;
+//	int x;
+	char *comment, *servername;
+	unsigned char opcode, updatecount, versionminor, versionmajor;
+	ulong periodicity, signature, type;
+
+	errmsg = nil;
+	comment = nil;
+	servername = nil;
+//	nbdumpdata(s->datagram.data, s->datagram.length);
+	b = smbbufferinit(s->datagram.data, s->datagram.data, s->datagram.length);
+	if (!smbbuffergetandcheckheader(b, &h, SMB_COM_TRANSACTION, 0, &pdata, &bytecount, &errmsg)) {
+		print("ignored: %s\n", errmsg);
+		goto done;
+	}
+	memset(&transaction, 0, sizeof(transaction));
+	rv = smbtransactiondecodeprimary(&transaction, &h, pdata, b, &errmsg);
+	if (rv < 0) {
+		print("transaction decode fail: %s\n", errmsg);
+		goto done;
+	}
+	if (rv == 0) {
+		print("transaction too big\n");
+		goto done;
+	}
+/*
+	print("name: %s\n", transaction.in.name);
+	print("setup:");
+	for (x = 0; x < transaction.in.scount; x++)
+		print(" 0x%.4ux", transaction.in.setup[x]);
+	print("\n");
+	print("parameters:\n");
+	nbdumpdata(transaction.in.parameters, transaction.in.tpcount);
+	print("data:\n");
+	nbdumpdata(transaction.in.data, transaction.in.tdcount);
+*/
+	if (strcmp(transaction.in.name, "\\MAILSLOT\\BROWSE") != 0) {
+		print("not a supported mailslot\n");
+		goto done;
+	}
+	
+	if (!smbbuffergetb(b, &opcode)) {
+		print("not enough data for opcode\n");
+		goto done;
+	}
+
+	if (opcode != 1) {
+		print("not a supported mailslot opcode %d\n", opcode);
+		goto done;
+	}
+	
+	if (!smbbuffergetb(b, &updatecount)
+		|| !smbbuffergetl(b, &periodicity)
+		|| !smbbuffergetstrn(b, 16, &servername)
+		|| !smbbuffergetb(b, &versionmajor)
+		|| !smbbuffergetb(b, &versionminor)
+		|| !smbbuffergetl(b, &type)
+		|| !smbbuffergetl(b, &signature)
+		|| !smbbuffergetstr(b, &comment)) {
+		print("mailslot parse failed\n");
+		goto done;
+	}
+/*
+ * not advisable to check this! Netgear printservers send 0x55aa
+	if ((signature & 0xffff0000) != 0xaa550000) {
+		print("wrong signature\n");
+		goto done;
+	}
+*/
+	print("%s: period %ludms version %d.%d type 0x%.8lux browserversion %d.%d comment %s\n",
+		servername, periodicity, versionmajor, versionminor, type, (signature >> 8) & 0xff, signature & 0xff, comment);
+done:
+	free(errmsg);
+	free(comment);
+	free(servername);
+	smbtransactionfree(&transaction);
+	smbbufferfree(&b);
+	return 1;
+}
+
+void
+threadmain(int, char **)
+{
+	char *e;
+	NbDgramSendParameters p;
+	nbinit();
+	smbglobalsguess(1);
+	nbmknamefromstringandtype(p.to, smbglobals.primarydomain, 0x1d);
+	e = nbdgramlisten(p.to, deliver, nil);
+	if (e) {
+		print("listen failed: %s\n", e);
+		threadexitsall("net");
+	}
+	p.type = NbDgramDirectUnique;
+	for (;;) {
+		if (!smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 3 * 60 * 1000,
+			SV_TYPE_SERVER,
+			"Testing testing", &e)) {
+			print("hostannounce failed: %s\n", e);
+		}
+		sleep(60 * 1000);
+	}
+}

+ 23 - 0
sys/src/cmd/aquarela/testtime.c

@@ -0,0 +1,23 @@
+#include "headers.h"
+
+void
+threadmain(int argc, char **argv)
+{
+	ulong now, now2;
+	vlong nttime;
+	if (argc > 1) {
+		nttime = strtoull(argv[1], 0, 0);
+		now2 = smbtime2plan9time(nttime);
+		print("%ld %s", now2, ctime(now2));
+	}
+	else {
+		now = 1032615845;
+		nttime = smbplan9time2time(now);
+		print("0x%.llux\n", nttime);
+		now2 = smbtime2plan9time(nttime);
+		print("now %ld %s", now, ctime(now));
+		print("now2 %ld %s", now2, ctime(now2));
+	}
+}
+
+

+ 330 - 0
sys/src/cmd/tcs/html.c

@@ -0,0 +1,330 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "hdr.h"
+#include "conv.h"
+
+typedef struct Hchar Hchar;
+struct Hchar
+{
+	char *s;
+	Rune r;
+};
+
+/* &lt;, &gt;, &quot;, &amp; intentionally omitted */
+
+static Hchar byname[] =
+{
+	{"AElig", 198},
+	{"Aacute", 193},
+	{"Acirc", 194},
+	{"Agrave", 192},
+	{"Aring", 197},
+	{"Atilde", 195},
+	{"Auml", 196},
+	{"Ccedil", 199},
+	{"ETH", 208},
+	{"Eacute", 201},
+	{"Ecirc", 202},
+	{"Egrave", 200},
+	{"Euml", 203},
+	{"Iacute", 205},
+	{"Icirc", 206},
+	{"Igrave", 204},
+	{"Iuml", 207},
+	{"Ntilde", 209},
+	{"Oacute", 211},
+	{"Ocirc", 212},
+	{"Ograve", 210},
+	{"Oslash", 216},
+	{"Otilde", 213},
+	{"Ouml", 214},
+	{"THORN", 222},
+	{"Uacute", 218},
+	{"Ucirc", 219},
+	{"Ugrave", 217},
+	{"Uuml", 220},
+	{"Yacute", 221},
+	{"aacute", 225},
+	{"acirc", 226},
+	{"acute", 180},
+	{"aelig", 230},
+	{"agrave", 224},
+	{"alpha", 945},
+	{"aring", 229},
+	{"atilde", 227},
+	{"auml", 228},
+	{"beta", 946},
+	{"brvbar", 166},
+	{"ccedil", 231},
+	{"cdots", 8943},
+	{"cedil", 184},
+	{"cent", 162},
+	{"chi", 967},
+	{"copy", 169},
+	{"curren", 164},
+	{"ddots", 8945},
+	{"deg", 176},
+	{"delta", 948},
+	{"divide", 247},
+	{"eacute", 233},
+	{"ecirc", 234},
+	{"egrave", 232},
+	{"emdash", 8212},	/* non-standard but commonly used */
+	{"emsp", 8195},
+	{"endash", 8211},	/* non-standard but commonly used */
+	{"ensp", 8194},
+	{"epsilon", 949},
+	{"eta", 951},
+	{"eth", 240},
+	{"euml", 235},
+	{"frac12", 189},
+	{"frac14", 188},
+	{"frac34", 190},
+	{"gamma", 947},
+	{"iacute", 237},
+	{"icirc", 238},
+	{"iexcl", 161},
+	{"igrave", 236},
+	{"iota", 953},
+	{"iquest", 191},
+	{"iuml", 239},
+	{"kappa", 954},
+	{"lambda", 955},
+	{"laquo", 171},
+	{"ldquo", 8220},
+	{"ldots", 8230},
+	{"lsquo", 8216},
+	{"macr", 175},
+	{"mdash", 8212},
+	{"micro", 181},
+	{"middot", 183},
+	{"mu", 956},
+	{"nbsp", 160},
+	{"ndash", 8211},
+	{"not", 172},
+	{"ntilde", 241},
+	{"nu", 957},
+	{"oacute", 243},
+	{"ocirc", 244},
+	{"ograve", 242},
+	{"omega", 969},
+	{"omicron", 959},
+	{"ordf", 170},
+	{"ordm", 186},
+	{"oslash", 248},
+	{"otilde", 245},
+	{"ouml", 246},
+	{"para", 182},
+	{"phi", 966},
+	{"pi", 960},
+	{"plusmn", 177},
+	{"pound", 163},
+	{"psi", 968},
+	{"quad", 8193},
+	{"raquo", 187},
+	{"rdquo", 8221},
+	{"reg", 174},
+	{"rho", 961},
+	{"rsquo", 8217},
+	{"sect", 167},
+	{"shy", 173},
+	{"sigma", 963},
+	{"sp", 8194},
+	{"sup1", 185},
+	{"sup2", 178},
+	{"sup3", 179},
+	{"szlig", 223},
+	{"tau", 964},
+	{"theta", 952},
+	{"thinsp", 8201},
+	{"thorn", 254},
+	{"times", 215},
+	{"trade", 8482},
+	{"uacute", 250},
+	{"ucirc", 251},
+	{"ugrave", 249},
+	{"uml", 168},
+	{"upsilon", 965},
+	{"uuml", 252},
+	{"varepsilon", 8712},
+	{"varphi", 981},
+	{"varpi", 982},
+	{"varrho", 1009},
+	{"vdots", 8942},
+	{"vsigma", 962},
+	{"vtheta", 977},
+	{"xi", 958},
+	{"yacute", 253},
+	{"yen", 165},
+	{"yuml", 255},
+	{"zeta", 950}
+};
+
+static Hchar byrune[nelem(byname)];
+
+static int
+hnamecmp(const void *va, const void *vb)
+{
+	Hchar *a, *b;
+	
+	a = (Hchar*)va;
+	b = (Hchar*)vb;
+	return strcmp(a->s, b->s);
+}
+
+static int
+hrunecmp(const void *va, const void *vb)
+{
+	Hchar *a, *b;
+	
+	a = (Hchar*)va;
+	b = (Hchar*)vb;
+	return a->r - b->r;
+}
+
+static void
+html_init(void)
+{
+	static int init;
+	
+	if(init)
+		return;
+	init = 1;
+	memmove(byrune, byname, sizeof byrune);
+	qsort(byname, nelem(byname), sizeof byname[0], hnamecmp);
+	qsort(byrune, nelem(byrune), sizeof byrune[0], hrunecmp);
+}
+
+static Rune
+findbyname(char *s)
+{
+	Hchar *h;
+	int n, m, x;
+	
+	h = byname;
+	n = nelem(byname);
+	while(n > 0){
+		m = n/2;
+		x = strcmp(h[m].s, s);
+		if(x == 0)
+			return h[m].r;
+		if(x < 0){
+			h += m+1;
+			n -= m+1;
+		}else
+			n = m;
+	}
+	return Runeerror;
+}
+
+static char*
+findbyrune(Rune r)
+{
+	Hchar *h;
+	int n, m;
+
+	h = byrune;
+	n = nelem(byrune);
+	while(n > 0){
+		m = n/2;
+		if(h[m].r == r)
+			return h[m].s;
+		if(h[m].r < r){
+			h += m+1;
+			n -= m+1;
+		}else
+			n = m;
+	}
+	return nil;
+}
+
+void
+html_in(int fd, long *x, struct convert *out)
+{
+	char buf[100], *p;
+	Biobuf b;
+	Rune rbuf[N];
+	Rune *r, *er;
+	int c, i;
+	
+	USED(x);
+	
+	html_init();
+	r = rbuf;
+	er = rbuf+N;
+	Binit(&b, fd, OREAD);
+	while((c = Bgetrune(&b)) != Beof){
+		if(r >= er){
+			OUT(out, rbuf, r-rbuf);
+			r = rbuf;
+		}
+		if(c == '&'){
+			buf[0] = c;
+			for(i=1; i<nelem(buf)-1;){
+				c = Bgetc(&b);
+				if(c == Beof)
+					break;
+				buf[i++] = c;
+				if(strchr("; \t\r\n", c))
+					break;
+			}
+			buf[i] = 0;
+			if(buf[i-1] == ';'){
+				buf[i-1] = 0;
+				if((c = findbyname(buf+1)) != Runeerror){
+					*r++ = c;
+					continue;
+				}
+				buf[i-1] = ';';
+				if(buf[1] == '#'){
+					if(buf[2] == 'x')
+						c = strtol(buf+3, &p, 16);
+					else
+						c = strtol(buf+2, &p, 10);
+					if(*p != ';' || c >= NRUNE || c < 0)
+						goto bad;
+					*r++ = c;
+					continue;
+				}
+			}
+		bad:
+			for(p=buf; p<buf+i; ){
+				p += chartorune(r++, p);
+				if(r >= er){
+					OUT(out, rbuf, r-rbuf);
+					r = rbuf;
+				}
+			}
+			continue;
+		}
+		*r++ = c;
+	}
+	if(r > rbuf)
+		OUT(out, rbuf, r-rbuf);
+}
+
+/*
+ * use biobuf because can use more than UTFmax bytes per rune
+ */
+void
+html_out(Rune *r, int n, long *x)
+{
+	char *s;
+	Biobuf b;
+	Rune *er;
+	
+	html_init();
+	Binit(&b, 1, OWRITE);
+	er = r+n;
+	for(; r<er; r++){
+		if(*r < Runeself)
+			Bputrune(&b, *r);
+		else if((s = findbyrune(*r)) != nil)
+			Bprint(&b, "&%s;", s);
+		else
+			Bprint(&b, "&#x%04x;", *r);
+	}
+	Bflush(&b);
+}
+

BIN
sys/src/cmd/unix/drawterm/9ball.ico


+ 1 - 0
sys/src/cmd/unix/drawterm/9ball.rc

@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "9ball.ico"

+ 245 - 0
sys/src/cmd/unix/drawterm/LICENSE

@@ -0,0 +1,245 @@
+Copyright (c) 2005 Lucent Technologies
+Portions Copyright (c) 2005 Russ Cox, MIT
+
+The Plan 9 software is provided under the terms of the
+Lucent Public License, Version 1.02, reproduced below.
+
+===================================================================
+
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+     Program, and
+  b. in the case of each Contributor,
+
+     i. changes to the Program, and
+    ii. additions to the Program;
+
+    where such changes and/or additions to the Program were added to the
+    Program by such Contributor itself or anyone acting on such
+    Contributor's behalf, and the Contributor explicitly consents, in
+    accordance with Section 3C, to characterization of the changes and/or
+    additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free copyright
+    license to reproduce, prepare derivative works of, publicly display,
+    publicly perform, distribute and sublicense the Contribution of such
+    Contributor, if any, and such derivative works, in source code and
+    object code form.
+    
+ b. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free patent
+    license under Licensed Patents to make, use, sell, offer to sell,
+    import and otherwise transfer the Contribution of such Contributor, if
+    any, in source code and object code form. The patent license granted
+    by a Contributor shall also apply to the combination of the
+    Contribution of that Contributor and the Program if, at the time the
+    Contribution is added by the Contributor, such addition of the
+    Contribution causes such combination to be covered by the Licensed
+    Patents. The patent license granted by a Contributor shall not apply
+    to (i) any other combinations which include the Contribution, nor to
+    (ii) Contributions of other Contributors. No hardware per se is
+    licensed hereunder.
+    
+ c. Recipient understands that although each Contributor grants the
+    licenses to its Contributions set forth herein, no assurances are
+    provided by any Contributor that the Program does not infringe the
+    patent or other intellectual property rights of any other entity. Each
+    Contributor disclaims any liability to Recipient for claims brought by
+    any other entity based on infringement of intellectual property rights
+    or otherwise. As a condition to exercising the rights and licenses
+    granted hereunder, each Recipient hereby assumes sole responsibility
+    to secure any other intellectual property rights needed, if any. For
+    example, if a third party patent license is required to allow
+    Recipient to distribute the Program, it is Recipient's responsibility
+    to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+    copyright rights in its Contribution, if any, to grant the copyright
+    license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+    form, a copy of this Agreement or Distributor's own license agreement
+    is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+    license agreement:
+
+      i. effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii. effectively excludes on behalf of all Contributors all liability
+         for damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits; and
+    iii. states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+   location in the Program:
+
+   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+   Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+

+ 1 - 0
sys/src/cmd/unix/drawterm/Make.config

@@ -0,0 +1 @@
+include $(ROOT)/Make.$(CONF)

+ 21 - 0
sys/src/cmd/unix/drawterm/Make.unix

@@ -0,0 +1,21 @@
+# Unix
+#PTHREAD=	# for Mac
+PTHREAD=-pthread
+AR=ar
+AS=as
+RANLIB=ranlib
+X11=/usr/X11R6
+CC=gcc
+CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2
+O=o
+OS=posix
+GUI=x11
+LDADD=-L$(X11)/lib -lX11 -ggdb
+LDFLAGS=$(PTHREAD)
+TARG=drawterm
+
+all: default
+
+libmachdep.a:
+	arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \
+	(cd posix-$$arch &&  make)

+ 42 - 0
sys/src/cmd/unix/drawterm/Make.win32

@@ -0,0 +1,42 @@
+# Windows via mingw32
+# MING=mingw32- is necessary if you're cross-compiling
+# on another platform.  Otherwise the binaries are just
+# named gcc, etc.
+
+MING=i586-mingw32msvc-
+#MING=
+AR=$(MING)ar
+CC=$(MING)gcc
+AS=$(MING)as
+RANLIB=$(MING)ranlib
+WINDRES=$(MING)windres
+CFLAGS=-Wall -Wno-missing-braces -I$(ROOT)/include -I$(ROOT) -I$(ROOT)/kern -c -D_X86_ -DIS_32 -DWINDOWS -O2
+O=o
+FS=fs-win32
+IP=win32
+OS=win32
+GUI=win32
+LDFLAGS=-mwindows
+LDADD=-lkernel32 -ladvapi32 -lgdi32 -lmpr -lwsock32 -lmsvcrt -lmingw32
+TARG=drawterm.exe
+XOFILES=9ball.$O
+
+# Windows via MSVC
+#AR=???
+#CC=cl
+#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -Iinclude -DWINDOWS
+#O=obj
+#FS=fs-win32
+#IP=win32
+#OS=win32
+#GUI=win32
+
+all: default
+
+# for root
+libmachdep.a:
+	(cd win32-386; make)
+
+9ball.$O: 9ball.rc 9ball.ico
+	$(WINDRES) -i 9ball.rc -o 9ball.o
+

+ 71 - 0
sys/src/cmd/unix/drawterm/Makefile

@@ -0,0 +1,71 @@
+ROOT=.
+
+include Make.config
+
+OFILES=\
+	main.$O\
+	cpu.$O\
+	readcons.$O\
+	secstore.$O\
+	latin1.$O\
+	$(OS)-factotum.$O\
+	$(XOFILES)\
+
+LIBS1=\
+	kern/libkern.a\
+	exportfs/libexportfs.a\
+	libauth/libauth.a\
+	libauthsrv/libauthsrv.a\
+	libsec/libsec.a\
+	libmp/libmp.a\
+	libmemdraw/libmemdraw.a\
+	libmemlayer/libmemlayer.a\
+	libdraw/libdraw.a\
+	gui-$(GUI)/libgui.a\
+	libc/libc.a\
+
+# stupid gcc
+LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a
+
+default: $(TARG)
+$(TARG): $(OFILES) $(LIBS)
+	$(CC) $(LDFLAGS) -o $(TARG) $(OFILES) $(LIBS) $(LDADD)
+
+%.$O: %.c
+	$(CC) $(CFLAGS) $*.c
+
+clean:
+	rm -f *.o */*.o */*.a *.a drawterm drawterm.exe
+
+kern/libkern.a:
+	(cd kern; $(MAKE))
+
+exportfs/libexportfs.a:
+	(cd exportfs; $(MAKE))
+
+libauth/libauth.a:
+	(cd libauth; $(MAKE))
+	
+libauthsrv/libauthsrv.a:
+	(cd libauthsrv; $(MAKE))
+
+libmp/libmp.a:
+	(cd libmp; $(MAKE))
+
+libsec/libsec.a:
+	(cd libsec; $(MAKE))
+
+libmemdraw/libmemdraw.a:
+	(cd libmemdraw; $(MAKE))
+
+libmemlayer/libmemlayer.a:
+	(cd libmemlayer; $(MAKE))
+
+libdraw/libdraw.a:
+	(cd libdraw; $(MAKE))
+
+libc/libc.a:
+	(cd libc; $(MAKE))
+
+gui-$(GUI)/libgui.a:
+	(cd gui-$(GUI); $(MAKE))

+ 36 - 8
sys/src/cmd/unix/drawterm/README

@@ -1,9 +1,37 @@
-This is drawterm, enough of a Plan 9 kernel to provide
-an environment under which ``cpu'' can run, so that you
-can access Plan 9 from Windows and various flavors
-of Unix.  See the manual page for more information.
-
-This drawterm still uses the old (third edition) 9P, aka 9P1.
-A 9P2000 version of drawterm and many other tools is in 
-progress.  See ../README for details.
+INSTALLATION
+--------------
+To build on Unix, run CONF=unix make.
+
+To build on Windows, you need Mingw.  See http://www.mingw.org.
+Edit Make.config to uncomment the Windows section
+and comment out the rest.  Then run CONF=windows make.
+
+(You can download nmake from 
+http://support.microsoft.com/default.aspx?scid=kb;en-us;Q132084
+Rename it to make.exe and put it in your path somewhere.
+)
+
+I haven't tested the Windows build on Windows itself.
+I cross-compile using mingw32 on Linux.
+
+
+BINARIES
+---------
+See http://swtch.com/drawterm/
+
+SOURCE
+------
+Use CVS: cvs -d :pserver:anoncvs@cvs.pdos.csail.mit.edu:/cvs co drawterm
+On the web at http://cvs.pdos.csail.mit.edu/cvs/drawterm
+In the Plan 9 distribution: /sys/src/cmd/unix/drawterm
+
+TO DO:
+------
+
+- Should import latest /dev/draw to allow resize of window
+
+- Should copy 9term code and make console window a real
+	9term window instead.
+
+- Should implement /dev/label.
 
 

+ 0 - 2
sys/src/cmd/unix/drawterm/README.MACOSX

@@ -1,2 +0,0 @@
-To build binaries for Mac OSX, use mkfile-FreeBSD-power
-

+ 0 - 17
sys/src/cmd/unix/drawterm/_asrdfile.c

@@ -1,17 +0,0 @@
-#include "lib9.h"
-#include "auth.h"
-#include "authlocal.h"
-
-int
-_asrdfile(char *file, char *buf, int len)
-{
-	int n, fd;
-
-	memset(buf, 0, len);
-	fd = open(file, OREAD);
-	if(fd < 0)
-		return -1;
-	n = read(fd, buf, len-1);
-	close(fd);
-	return n;
-}

+ 0 - 37
sys/src/cmd/unix/drawterm/_asrdresp.c

@@ -1,37 +0,0 @@
-#include "lib9.h"
-#include "auth.h"
-#include "authlocal.h"
-
-static char *pbmsg = "AS protocol botch";
-
-int
-_asrdresp(int fd, char *buf, int len)
-{
-	char error[ERRLEN];
-
-	if(read(fd, buf, 1) != 1){
-		werrstr(pbmsg);
-		return -1;
-	}
-
-	switch(buf[0]){
-	case AuthOK:
-		if(_asreadn(fd, buf, len) < 0){
-			werrstr(pbmsg);
-			return -1;
-		}
-		break;
-	case AuthErr:
-		if(_asreadn(fd, error, ERRLEN) < 0){
-			werrstr(pbmsg);
-			return -1;
-		}
-		error[ERRLEN-1] = 0;
-		werrstr(error);
-		return -1;
-	default:
-		werrstr(pbmsg);
-		return -1;
-	}
-	return 0;
-}

+ 0 - 15
sys/src/cmd/unix/drawterm/_asreadn.c

@@ -1,15 +0,0 @@
-#include "lib9.h"
-#include "authlocal.h"
-
-int
-_asreadn(int fd, char *buf, int len)
-{
-	int m, n;
-
-	for(n = 0; n < len; n += m){
-		m = read(fd, buf+n, len-n);
-		if(m <= 0)
-			return -1;
-	}
-	return n;
-}

+ 20 - 0
sys/src/cmd/unix/drawterm/args.h

@@ -0,0 +1,20 @@
+extern char *argv0;
+#define	ARGBEGIN	for((argv0? 0: (argv0=*argv)),argv++,argc--;\
+			    argv[0] && argv[0][0]=='-' && argv[0][1];\
+			    argc--, argv++) {\
+				char *_args, *_argt;\
+				Rune _argc;\
+				_args = &argv[0][1];\
+				if(_args[0]=='-' && _args[1]==0){\
+					argc--; argv++; break;\
+				}\
+				_argc = 0;\
+				while(*_args && (_args += chartorune(&_argc, _args)))\
+				switch(_argc)
+#define	ARGEND		SET(_argt);USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc);
+#define	ARGF()		(_argt=_args, _args="",\
+				(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
+#define	ARGC()		_argc
+
+#define	EARGF(x)		(_argt=_args, _args="",\
+				(*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0)))

+ 0 - 3
sys/src/cmd/unix/drawterm/argv0.c

@@ -1,3 +0,0 @@
-#include "lib9.h"
-
-char *argv0;

+ 0 - 60
sys/src/cmd/unix/drawterm/asm-Solaris-386.s

@@ -1,60 +0,0 @@
-	.section	.bss
-	.align	4
-.L4_.bss:
-	.align	4
-Solaris_Asm_IntP: / Offset 0
-	.type	Solaris_Asm_IntP,@object
-	.size	Solaris_Asm_IntP,4
-	.set	.,.+4
-Solaris_Asm_VoidP: / Offset 4
-	.type	Solaris_Asm_VoidP,@object
-	.size	Solaris_Asm_VoidP,4
-	.set	.,.+4
-	.section	.data
-	.align	4
-.L2_.data:
-	.align	4
-.L01:	.string	"canlock corrupted 0x%lux\n\000"
-	.set	.,.+0x2
-	.section	.text
-	.align	4
-.L1_.text:
-
-/====================
-/ canlock
-/--------------------
-	.align	4
-	.align	4
-	.globl	canlock
-canlock:
-	pushl	%ebp
-	movl	%esp,%ebp
-	pushl	%esi
-	movl	8(%ebp),%eax
-	movl	%eax,Solaris_Asm_IntP
-	movl	$1, %ecx
-	xchg	(%eax), %ecx
-	andl	%ecx,%ecx
-	jne	.L1
-	movl	$1,%esi
-	jmp	.L2
-	.align	4
-.L3:
-	subl	%esi,%esi
-	jmp	.L2
-	.align	4
-.L1:
-	cmpl	$1,%ecx
-	je	.L3
-	pushl	%ecx
-	pushl	$.L01
-	call	print
-	addl	$8,%esp
-.L2:
-	movl	%esi,%eax
-	popl	%esi
-	leave	
-	ret	
-	.type	canlock,@function
-	.size	canlock,.-canlock
-

+ 0 - 21
sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s

@@ -1,21 +0,0 @@
-	.section	".text", #alloc, #execinstr
-	.align		8
-	.skip		16
-	.global canlock
-	.type	canlock,2
-canlock:
-	or	%g0,1,%o1
-	swap	[%o0],%o1	! o0 points to lock; key is first word
-	cmp	%o1,1
-	bne	.gotit
-	nop
-	retl			! key was 1
-	or	%g0,0,%o0
-.gotit:
-	retl			! key was not 1
-	or	%g0,1,%o0
-
-	.size	canlock,(.-canlock)
-
-
- 

+ 0 - 70
sys/src/cmd/unix/drawterm/atexit.c

@@ -1,70 +0,0 @@
-#include "lib9.h"
-#include "sys.h"
-
-#define	NEXIT	33
-
-static void	(*onex[NEXIT])(void);
-static Lock	atlock;
-
-int
-atexit(void (*f)(void))
-{
-	int i;
-
-	lock(&atlock);
-	for(i=0; i<NEXIT; i++) {
-		if(onex[i] == 0) {
-			onex[i] = f;
-			unlock(&atlock);
-			return 1;
-		}
-	}
-	unlock(&atlock);
-	return 0;
-}
-
-void
-atexitdont(void (*f)(void))
-{
-	int i;
-
-	lock(&atlock);
-	for(i=0; i<NEXIT; i++)
-		if(onex[i] == f)
-			onex[i] = 0;
-	unlock(&atlock);
-}
-
-void
-exits(char *s)
-{
-	int i;
-	void (*f)(void);
-
-	for(i = NEXIT-1; i >= 0; i--) {
-		lock(&atlock);
-		f = onex[i];
-		onex[i] = 0;
-		unlock(&atlock);
-
-		if(f)
-			(*f)();
-	}
-	_exits(s);
-}
-
-void
-fatal(char *fmt, ...)
-{
-	char buf[512];
-	va_list va;
-
-	va_start(va, fmt);
-	doprint(buf, buf+sizeof(buf), fmt, va);
-	va_end(va);
-
-	iprint("%s: %s\n", argv0, buf);
-abort();
-	_exits(buf);
-}
-

Some files were not shown because too many files changed in this diff