Browse Source

Plan 9 from Bell Labs 2005-09-14

David du Colombier 18 years ago
parent
commit
b0620829d9

+ 18 - 18
dist/replica/_plan9.db

@@ -7765,7 +7765,7 @@ sys/src/9/alphapc/initcode - 664 sys sys 1039753419 779
 sys/src/9/alphapc/io.h - 664 sys sys 1087657423 4540
 sys/src/9/alphapc/kbd.c - 664 sys sys 1015012785 8676
 sys/src/9/alphapc/l.s - 664 sys sys 1067722580 9124
-sys/src/9/alphapc/main.c - 664 sys sys 1039753420 13626
+sys/src/9/alphapc/main.c - 664 sys sys 1126586256 13624
 sys/src/9/alphapc/mem.h - 664 sys sys 1077408326 3131
 sys/src/9/alphapc/memmove.s - 664 sys sys 1015012786 2936
 sys/src/9/alphapc/memset.s - 664 sys sys 1015012786 844
@@ -7801,7 +7801,7 @@ sys/src/9/bitsy/gamma.h - 664 sys sys 1017695514 540718
 sys/src/9/bitsy/init9.s - 664 sys sys 1043922398 183
 sys/src/9/bitsy/io.h - 664 sys sys 1064584624 8040
 sys/src/9/bitsy/l.s - 664 sys sys 1055700934 18211
-sys/src/9/bitsy/main.c - 664 sys sys 1067722593 9083
+sys/src/9/bitsy/main.c - 664 sys sys 1126586256 9081
 sys/src/9/bitsy/map - 664 sys sys 1017695515 236
 sys/src/9/bitsy/mem.h - 664 sys sys 1055700932 8049
 sys/src/9/bitsy/mkfile - 664 sys sys 1072705544 2452
@@ -7894,7 +7894,7 @@ sys/src/9/mtx/initcode - 664 sys sys 1039753442 444
 sys/src/9/mtx/io.h - 664 sys sys 1087657404 4817
 sys/src/9/mtx/kbd.c - 664 sys sys 1018721286 8358
 sys/src/9/mtx/l.s - 664 sys sys 1067722599 10730
-sys/src/9/mtx/main.c - 664 sys sys 1018721287 8344
+sys/src/9/mtx/main.c - 664 sys sys 1126586256 8342
 sys/src/9/mtx/mem.h - 664 sys sys 1026848200 5959
 sys/src/9/mtx/mkfile - 664 sys sys 1072972534 1520
 sys/src/9/mtx/mmu.c - 664 sys sys 1123438210 4421
@@ -7965,7 +7965,7 @@ sys/src/9/pc/initcode.s - 664 sys sys 1015014519 282
 sys/src/9/pc/io.h - 664 sys sys 1099761152 8095
 sys/src/9/pc/kbd.c - 664 sys sys 1079617269 11655
 sys/src/9/pc/l.s - 664 sys sys 1115566067 23833
-sys/src/9/pc/main.c - 664 sys sys 1121858827 14693
+sys/src/9/pc/main.c - 664 sys sys 1126586232 14691
 sys/src/9/pc/mem.h - 664 sys sys 1018553448 4573
 sys/src/9/pc/memory.c - 664 sys sys 1071245460 13028
 sys/src/9/pc/mkfile - 664 sys sys 1067810339 3219
@@ -8038,11 +8038,11 @@ sys/src/9/port/alarm.c - 664 sys sys 1067722766 1426
 sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
-sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
-sys/src/9/port/chan.c - 664 sys sys 1125551975 31560
+sys/src/9/port/cache.c - 664 sys sys 1126586168 9241
+sys/src/9/port/chan.c - 664 sys sys 1126586131 33640
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
-sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
+sys/src/9/port/dev.c - 664 sys sys 1126586172 8246
 sys/src/9/port/devaudio.c - 664 sys sys 1067722761 21130
 sys/src/9/port/devbridge.c - 664 sys sys 1055688301 24308
 sys/src/9/port/devcap.c - 664 sys sys 1048644215 4113
@@ -8054,12 +8054,12 @@ sys/src/9/port/devfs.c - 664 sys sys 1105799131 10783
 sys/src/9/port/devkbmap.c - 664 sys sys 1079463756 2774
 sys/src/9/port/devkprof.c - 664 sys sys 1014931173 3111
 sys/src/9/port/devloopback.c - 664 sys sys 1076612248 14573
-sys/src/9/port/devmnt.c - 664 sys sys 1117197997 21545
+sys/src/9/port/devmnt.c - 664 sys sys 1126586197 21545
 sys/src/9/port/devmntstats.c - 664 sys sys 1014931173 4039
 sys/src/9/port/devmouse.c - 664 sys sys 1099760452 12504
 sys/src/9/port/devpipe.c - 664 sys sys 1077055016 5825
 sys/src/9/port/devpnp.c - 664 sys sys 1088560907 13624
-sys/src/9/port/devproc.c - 664 sys sys 1106585362 28465
+sys/src/9/port/devproc.c - 664 sys sys 1126586197 28465
 sys/src/9/port/devroot.c - 664 sys sys 1067722764 4254
 sys/src/9/port/devsd.c - 664 sys sys 1123255503 28564
 sys/src/9/port/devsdp.c - 664 sys sys 1057323393 44800
@@ -8069,10 +8069,11 @@ sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtls.c - 664 sys sys 1086406907 45225
 sys/src/9/port/devuart.c - 664 sys sys 1102093393 12192
+sys/src/9/port/devwd.c - 664 sys sys 1126582325 2342
 sys/src/9/port/edf.c - 664 sys sys 1099760881 12742
 sys/src/9/port/edf.h - 664 sys sys 1084475128 1156
 sys/src/9/port/error.h - 664 sys sys 1117055493 2637
-sys/src/9/port/fault.c - 664 sys sys 1123438654 7282
+sys/src/9/port/fault.c - 664 sys sys 1126586199 7282
 sys/src/9/port/initcode.c - 664 sys sys 1055688491 574
 sys/src/9/port/latin1.c - 664 sys sys 1015278339 1418
 sys/src/9/port/latin1.h - 664 sys sys 1103633666 3563
@@ -8098,8 +8099,8 @@ sys/src/9/port/page.c - 664 sys sys 1102133425 8281
 sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
 sys/src/9/port/pgrp.c - 664 sys sys 1072704671 3940
 sys/src/9/port/portclock.c - 664 sys sys 1102093397 4556
-sys/src/9/port/portdat.h - 664 sys sys 1109541435 22233
-sys/src/9/port/portfns.h - 664 sys sys 1123647283 10976
+sys/src/9/port/portdat.h - 664 sys sys 1126586141 22608
+sys/src/9/port/portfns.h - 664 sys sys 1126586141 11002
 sys/src/9/port/portmkfile - 664 sys sys 1124708650 2052
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
 sys/src/9/port/proc.c - 664 sys sys 1099760501 28207
@@ -8110,8 +8111,8 @@ sys/src/9/port/rebootcmd.c - 664 sys sys 1015278340 1561
 sys/src/9/port/sd.h - 664 sys sys 1098546338 2348
 sys/src/9/port/segment.c - 664 sys sys 1121259584 13761
 sys/src/9/port/swap.c - 664 sys sys 1055688551 6980
-sys/src/9/port/sysfile.c - 664 sys sys 1123647282 22249
-sys/src/9/port/sysproc.c - 664 sys sys 1123645064 15114
+sys/src/9/port/sysfile.c - 664 sys sys 1126586199 22173
+sys/src/9/port/sysproc.c - 664 sys sys 1126586213 15164
 sys/src/9/port/systab.h - 664 sys sys 1062721698 3044
 sys/src/9/port/taslock.c - 664 sys sys 1084475129 3658
 sys/src/9/port/thwack.c - 664 sys sys 1057323394 7253
@@ -8140,7 +8141,7 @@ sys/src/9/ppc/lblast.h - 664 sys sys 1059490752 1694
 sys/src/9/ppc/lucu.h - 664 sys sys 1059490752 935
 sys/src/9/ppc/m8260.c - 664 sys sys 1123094594 14482
 sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
-sys/src/9/ppc/main.c - 664 sys sys 1097073343 9041
+sys/src/9/ppc/main.c - 664 sys sys 1126586256 9039
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
 sys/src/9/ppc/mem.h - 664 sys sys 1091021860 7002
 sys/src/9/ppc/mkfile - 664 sys sys 1067722849 1813
@@ -9910,7 +9911,7 @@ sys/src/cmd/disk/prep - 20000000775 sys sys 988249968 0
 sys/src/cmd/disk/prep/calc.y - 664 sys sys 958519682 2378
 sys/src/cmd/disk/prep/edit.c - 664 sys sys 1017854327 9714
 sys/src/cmd/disk/prep/edit.h - 664 sys sys 1015009215 994
-sys/src/cmd/disk/prep/fdisk.c - 664 sys sys 1050689604 21894
+sys/src/cmd/disk/prep/fdisk.c - 664 sys sys 1126623191 21983
 sys/src/cmd/disk/prep/mkfile - 664 sys sys 1022450200 250
 sys/src/cmd/disk/prep/prep.c - 664 sys sys 1126278202 10098
 sys/src/cmd/disk/rd9660.c - 664 sys sys 1021579990 7446
@@ -14962,5 +14963,4 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
-sys/src/9/port/portdat.h - 664 sys sys 1126582287 22484
-sys/src/9/port/portfns.h - 664 sys sys 1126582287 11006
+386/bin/disk/fdisk - 775 sys sys 1126667443 103810

+ 18 - 17
dist/replica/plan9.db

@@ -201,7 +201,7 @@
 386/bin/disk - 20000000775 sys sys 984788664 0
 386/bin/disk/dump9660 - 775 sys sys 1125345967 152253
 386/bin/disk/exsort - 775 sys sys 1119496645 60226
-386/bin/disk/fdisk - 775 sys sys 1126321690 103794
+386/bin/disk/fdisk - 775 sys sys 1126667443 103810
 386/bin/disk/format - 775 sys sys 1126321690 89534
 386/bin/disk/kfs - 775 sys sys 1119496646 248974
 386/bin/disk/kfscmd - 775 sys sys 1115950064 38222
@@ -7765,7 +7765,7 @@ sys/src/9/alphapc/initcode - 664 sys sys 1039753419 779
 sys/src/9/alphapc/io.h - 664 sys sys 1087657423 4540
 sys/src/9/alphapc/kbd.c - 664 sys sys 1015012785 8676
 sys/src/9/alphapc/l.s - 664 sys sys 1067722580 9124
-sys/src/9/alphapc/main.c - 664 sys sys 1039753420 13626
+sys/src/9/alphapc/main.c - 664 sys sys 1126586256 13624
 sys/src/9/alphapc/mem.h - 664 sys sys 1077408326 3131
 sys/src/9/alphapc/memmove.s - 664 sys sys 1015012786 2936
 sys/src/9/alphapc/memset.s - 664 sys sys 1015012786 844
@@ -7801,7 +7801,7 @@ sys/src/9/bitsy/gamma.h - 664 sys sys 1017695514 540718
 sys/src/9/bitsy/init9.s - 664 sys sys 1043922398 183
 sys/src/9/bitsy/io.h - 664 sys sys 1064584624 8040
 sys/src/9/bitsy/l.s - 664 sys sys 1055700934 18211
-sys/src/9/bitsy/main.c - 664 sys sys 1067722593 9083
+sys/src/9/bitsy/main.c - 664 sys sys 1126586256 9081
 sys/src/9/bitsy/map - 664 sys sys 1017695515 236
 sys/src/9/bitsy/mem.h - 664 sys sys 1055700932 8049
 sys/src/9/bitsy/mkfile - 664 sys sys 1072705544 2452
@@ -7894,7 +7894,7 @@ sys/src/9/mtx/initcode - 664 sys sys 1039753442 444
 sys/src/9/mtx/io.h - 664 sys sys 1087657404 4817
 sys/src/9/mtx/kbd.c - 664 sys sys 1018721286 8358
 sys/src/9/mtx/l.s - 664 sys sys 1067722599 10730
-sys/src/9/mtx/main.c - 664 sys sys 1018721287 8344
+sys/src/9/mtx/main.c - 664 sys sys 1126586256 8342
 sys/src/9/mtx/mem.h - 664 sys sys 1026848200 5959
 sys/src/9/mtx/mkfile - 664 sys sys 1072972534 1520
 sys/src/9/mtx/mmu.c - 664 sys sys 1123438210 4421
@@ -7965,7 +7965,7 @@ sys/src/9/pc/initcode.s - 664 sys sys 1015014519 282
 sys/src/9/pc/io.h - 664 sys sys 1099761152 8095
 sys/src/9/pc/kbd.c - 664 sys sys 1079617269 11655
 sys/src/9/pc/l.s - 664 sys sys 1115566067 23833
-sys/src/9/pc/main.c - 664 sys sys 1121858827 14693
+sys/src/9/pc/main.c - 664 sys sys 1126586232 14691
 sys/src/9/pc/mem.h - 664 sys sys 1018553448 4573
 sys/src/9/pc/memory.c - 664 sys sys 1071245460 13028
 sys/src/9/pc/mkfile - 664 sys sys 1067810339 3219
@@ -8038,11 +8038,11 @@ sys/src/9/port/alarm.c - 664 sys sys 1067722766 1426
 sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
-sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
-sys/src/9/port/chan.c - 664 sys sys 1125551975 31560
+sys/src/9/port/cache.c - 664 sys sys 1126586168 9241
+sys/src/9/port/chan.c - 664 sys sys 1126586131 33640
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
-sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
+sys/src/9/port/dev.c - 664 sys sys 1126586172 8246
 sys/src/9/port/devaudio.c - 664 sys sys 1067722761 21130
 sys/src/9/port/devbridge.c - 664 sys sys 1055688301 24308
 sys/src/9/port/devcap.c - 664 sys sys 1048644215 4113
@@ -8054,12 +8054,12 @@ sys/src/9/port/devfs.c - 664 sys sys 1105799131 10783
 sys/src/9/port/devkbmap.c - 664 sys sys 1079463756 2774
 sys/src/9/port/devkprof.c - 664 sys sys 1014931173 3111
 sys/src/9/port/devloopback.c - 664 sys sys 1076612248 14573
-sys/src/9/port/devmnt.c - 664 sys sys 1117197997 21545
+sys/src/9/port/devmnt.c - 664 sys sys 1126586197 21545
 sys/src/9/port/devmntstats.c - 664 sys sys 1014931173 4039
 sys/src/9/port/devmouse.c - 664 sys sys 1099760452 12504
 sys/src/9/port/devpipe.c - 664 sys sys 1077055016 5825
 sys/src/9/port/devpnp.c - 664 sys sys 1088560907 13624
-sys/src/9/port/devproc.c - 664 sys sys 1106585362 28465
+sys/src/9/port/devproc.c - 664 sys sys 1126586197 28465
 sys/src/9/port/devroot.c - 664 sys sys 1067722764 4254
 sys/src/9/port/devsd.c - 664 sys sys 1123255503 28564
 sys/src/9/port/devsdp.c - 664 sys sys 1057323393 44800
@@ -8069,10 +8069,11 @@ sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtls.c - 664 sys sys 1086406907 45225
 sys/src/9/port/devuart.c - 664 sys sys 1102093393 12192
+sys/src/9/port/devwd.c - 664 sys sys 1126582325 2342
 sys/src/9/port/edf.c - 664 sys sys 1099760881 12742
 sys/src/9/port/edf.h - 664 sys sys 1084475128 1156
 sys/src/9/port/error.h - 664 sys sys 1117055493 2637
-sys/src/9/port/fault.c - 664 sys sys 1123438654 7282
+sys/src/9/port/fault.c - 664 sys sys 1126586199 7282
 sys/src/9/port/initcode.c - 664 sys sys 1055688491 574
 sys/src/9/port/latin1.c - 664 sys sys 1015278339 1418
 sys/src/9/port/latin1.h - 664 sys sys 1103633666 3563
@@ -8098,8 +8099,8 @@ sys/src/9/port/page.c - 664 sys sys 1102133425 8281
 sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
 sys/src/9/port/pgrp.c - 664 sys sys 1072704671 3940
 sys/src/9/port/portclock.c - 664 sys sys 1102093397 4556
-sys/src/9/port/portdat.h - 664 sys sys 1126582287 22484
-sys/src/9/port/portfns.h - 664 sys sys 1126582287 11006
+sys/src/9/port/portdat.h - 664 sys sys 1126586141 22608
+sys/src/9/port/portfns.h - 664 sys sys 1126586141 11002
 sys/src/9/port/portmkfile - 664 sys sys 1124708650 2052
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
 sys/src/9/port/proc.c - 664 sys sys 1099760501 28207
@@ -8110,8 +8111,8 @@ sys/src/9/port/rebootcmd.c - 664 sys sys 1015278340 1561
 sys/src/9/port/sd.h - 664 sys sys 1098546338 2348
 sys/src/9/port/segment.c - 664 sys sys 1121259584 13761
 sys/src/9/port/swap.c - 664 sys sys 1055688551 6980
-sys/src/9/port/sysfile.c - 664 sys sys 1123647282 22249
-sys/src/9/port/sysproc.c - 664 sys sys 1123645064 15114
+sys/src/9/port/sysfile.c - 664 sys sys 1126586199 22173
+sys/src/9/port/sysproc.c - 664 sys sys 1126586213 15164
 sys/src/9/port/systab.h - 664 sys sys 1062721698 3044
 sys/src/9/port/taslock.c - 664 sys sys 1084475129 3658
 sys/src/9/port/thwack.c - 664 sys sys 1057323394 7253
@@ -8140,7 +8141,7 @@ sys/src/9/ppc/lblast.h - 664 sys sys 1059490752 1694
 sys/src/9/ppc/lucu.h - 664 sys sys 1059490752 935
 sys/src/9/ppc/m8260.c - 664 sys sys 1123094594 14482
 sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
-sys/src/9/ppc/main.c - 664 sys sys 1097073343 9041
+sys/src/9/ppc/main.c - 664 sys sys 1126586256 9039
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
 sys/src/9/ppc/mem.h - 664 sys sys 1091021860 7002
 sys/src/9/ppc/mkfile - 664 sys sys 1067722849 1813
@@ -9910,7 +9911,7 @@ sys/src/cmd/disk/prep - 20000000775 sys sys 988249968 0
 sys/src/cmd/disk/prep/calc.y - 664 sys sys 958519682 2378
 sys/src/cmd/disk/prep/edit.c - 664 sys sys 1017854327 9714
 sys/src/cmd/disk/prep/edit.h - 664 sys sys 1015009215 994
-sys/src/cmd/disk/prep/fdisk.c - 664 sys sys 1050689604 21894
+sys/src/cmd/disk/prep/fdisk.c - 664 sys sys 1126623191 21983
 sys/src/cmd/disk/prep/mkfile - 664 sys sys 1022450200 250
 sys/src/cmd/disk/prep/prep.c - 664 sys sys 1126278202 10098
 sys/src/cmd/disk/rd9660.c - 664 sys sys 1021579990 7446

+ 18 - 0
dist/replica/plan9.log

@@ -21269,3 +21269,21 @@
 1126409473 0 c 386/bin/dd - 775 sys sys 1126408183 45398
 1126582261 0 c sys/src/9/port/portdat.h - 664 sys sys 1126582287 22484
 1126582261 1 c sys/src/9/port/portfns.h - 664 sys sys 1126582287 11006
+1126584062 0 a sys/src/9/port/devwd.c - 664 sys sys 1126582325 2342
+1126587661 0 c sys/src/9/alphapc/main.c - 664 sys sys 1126586256 13624
+1126587661 1 c sys/src/9/bitsy/main.c - 664 sys sys 1126586256 9081
+1126587661 2 c sys/src/9/mtx/main.c - 664 sys sys 1126586256 8342
+1126587661 3 c sys/src/9/pc/main.c - 664 sys sys 1126586232 14691
+1126587661 4 c sys/src/9/port/cache.c - 664 sys sys 1126586168 9241
+1126587661 5 c sys/src/9/port/chan.c - 664 sys sys 1126586131 33640
+1126587661 6 c sys/src/9/port/dev.c - 664 sys sys 1126586172 8246
+1126587661 7 c sys/src/9/port/devmnt.c - 664 sys sys 1126586197 21545
+1126587661 8 c sys/src/9/port/devproc.c - 664 sys sys 1126586197 28465
+1126587661 9 c sys/src/9/port/fault.c - 664 sys sys 1126586199 7282
+1126587661 10 c sys/src/9/port/portdat.h - 664 sys sys 1126586141 22608
+1126587661 11 c sys/src/9/port/portfns.h - 664 sys sys 1126586141 11002
+1126587661 12 c sys/src/9/port/sysfile.c - 664 sys sys 1126586199 22173
+1126587661 13 c sys/src/9/port/sysproc.c - 664 sys sys 1126586213 15164
+1126587661 14 c sys/src/9/ppc/main.c - 664 sys sys 1126586256 9039
+1126623670 0 c sys/src/cmd/disk/prep/fdisk.c - 664 sys sys 1126623191 21983
+1126668680 0 c 386/bin/disk/fdisk - 775 sys sys 1126667443 103810

+ 2 - 2
sys/src/9/alphapc/main.c

@@ -176,8 +176,8 @@ init0(void)
 	 * Then early kproc's will have a root and dot.
 	 */
 	up->slash = namec("#/", Atodir, 0, 0);
-	cnameclose(up->slash->name);
-	up->slash->name = newcname("/");
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
 	up->dot = cclone(up->slash);
 
 	chandevinit();

+ 2 - 2
sys/src/9/bitsy/main.c

@@ -96,8 +96,8 @@ init0(void)
 	 * Then early kproc's will have a root and dot.
 	 */
 	up->slash = namec("#/", Atodir, 0, 0);
-	cnameclose(up->slash->name);
-	up->slash->name = newcname("/");
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
 	up->dot = cclone(up->slash);
 
 	chandevinit();

+ 2 - 2
sys/src/9/mtx/main.c

@@ -116,8 +116,8 @@ init0(void)
 	 * Then early kproc's will have a root and dot.
 	 */
 	up->slash = namec("#/", Atodir, 0, 0);
-	cnameclose(up->slash->name);
-	up->slash->name = newcname("/");
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
 	up->dot = cclone(up->slash);
 
 	chandevinit();

+ 2 - 2
sys/src/9/pc/main.c

@@ -166,8 +166,8 @@ init0(void)
 	 * Then early kproc's will have a root and dot.
 	 */
 	up->slash = namec("#/", Atodir, 0, 0);
-	cnameclose(up->slash->name);
-	up->slash->name = newcname("/");
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
 	up->dot = cclone(up->slash);
 
 	chandevinit();

+ 1 - 1
sys/src/9/port/cache.c

@@ -148,7 +148,7 @@ cprint(Chan *c, Mntcache *m, char *s)
 		o = e->start+e->len;
 	}
 	pprint("%s: 0x%lux.0x%lux %d %d %s (%d %c)\n",
-	s, m->qid.path, m->qid.vers, m->type, m->dev, c->name, nb, ct ? 'C' : 'N');
+	s, m->qid.path, m->qid.vers, m->type, m->dev, c->path, nb, ct ? 'C' : 'N');
 
 	for(e = m->list; e; e = e->next) {
 		pprint("\t%4d %5d %4d %lux\n",

+ 317 - 230
sys/src/9/port/chan.c

@@ -6,11 +6,39 @@
 #include	"../port/error.h"
 
 int chandebug=0;		/* toggled by sysr1 */
-QLock chanprint;		/* probably asking for trouble (deadlocks) -rsc */
+#define DBG if(chandebug)iprint
 
-int domount(Chan**, Mhead**);
+enum
+{
+	PATHSLOP	= 20,
+	PATHMSLOP	= 20,
+};
 
-void
+struct
+{
+	Lock;
+	int	fid;
+	Chan	*free;
+	Chan	*list;
+}chanalloc;
+
+typedef struct Elemlist Elemlist;
+
+struct Elemlist
+{
+	char	*aname;	/* original name */
+	char	*name;	/* copy of name, so '/' can be overwritten */
+	int	nelems;
+	char	**elems;
+	int	*off;
+	int	mustbedir;
+	int	nerror;
+	int	prefix;
+};
+
+#define SEP(c) ((c) == 0 || (c) == '/')
+
+static void
 dumpmount(void)		/* DEBUGGING */
 {
 	Pgrp *pg;
@@ -27,69 +55,38 @@ dumpmount(void)		/* DEBUGGING */
 		return;
 	}
 	rlock(&pg->ns);
-	if(waserror()) {
+	if(waserror()){
 		runlock(&pg->ns);
 		nexterror();
 	}
 
 	he = &pg->mnthash[MNTHASH];
-	for(h = pg->mnthash; h < he; h++) {
-		for(f = *h; f; f = f->hash) {
+	for(h = pg->mnthash; h < he; h++){
+		for(f = *h; f; f = f->hash){
 			print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f,
-				f->from->name->s, f->from->qid.path,
+				f->from->path->s, f->from->qid.path,
 				f->from->qid.vers, devtab[f->from->type]->dc,
 				f->from->dev);
 			for(t = f->mount; t; t = t->next)
-				print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
+				print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->path->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
 		}
 	}
 	poperror();
 	runlock(&pg->ns);
 }
 
-
 char*
-channame(Chan *c)		/* DEBUGGING */
+chanpath(Chan *c)
 {
 	if(c == nil)
 		return "<nil chan>";
-	if(c->name == nil)
-		return "<nil name>";
-	if(c->name->s == nil)
-		return "<nil name.s>";
-	return c->name->s;
+	if(c->path == nil)
+		return "<nil path>";
+	if(c->path->s == nil)
+		return "<nil path.s>";
+	return c->path->s;
 }
 
-enum
-{
-	CNAMESLOP	= 20
-};
-
-struct
-{
-	Lock;
-	int	fid;
-	Chan	*free;
-	Chan	*list;
-}chanalloc;
-
-typedef struct Elemlist Elemlist;
-
-struct Elemlist
-{
-	char	*aname;	/* original name */
-	char	*name;	/* copy of name, so '/' can be overwritten */
-	int	nelems;
-	char	**elems;
-	int	*off;
-	int	mustbedir;
-	int	nerror;
-	int	prefix;
-};
-
-#define SEP(c) ((c) == 0 || (c) == '/')
-void cleancname(Cname*);
-
 int
 isdotdot(char *p)
 {
@@ -230,7 +227,7 @@ newchan(void)
 		chanalloc.free = c->next;
 	unlock(&chanalloc);
 
-	if(c == nil) {
+	if(c == nil){
 		c = smalloc(sizeof(Chan));
 		lock(&chanalloc);
 		c->fid = ++chanalloc.fid;
@@ -256,75 +253,183 @@ newchan(void)
 	c->mcp = 0;
 	c->mux = 0;
 	memset(&c->mqid, 0, sizeof(c->mqid));
-	c->name = 0;
+	c->path = 0;
 	c->ismtpt = 0;
+	
 	return c;
 }
 
-static Ref ncname;
+Ref npath;
 
-Cname*
-newcname(char *s)
+Path*
+newpath(char *s)
 {
-	Cname *n;
 	int i;
+	Path *p;
 
-	n = smalloc(sizeof(Cname));
+	p = smalloc(sizeof(Path));
 	i = strlen(s);
-	n->len = i;
-	n->alen = i+CNAMESLOP;
-	n->s = smalloc(n->alen);
-	memmove(n->s, s, i+1);
-	n->ref = 1;
-	incref(&ncname);
-	return n;
+	p->len = i;
+	p->alen = i+PATHSLOP;
+	p->s = smalloc(p->alen);
+	memmove(p->s, s, i+1);
+	p->ref = 1;
+	incref(&npath);
+
+	/*
+	 * Cannot use newpath for arbitrary names because the mtpt 
+	 * array will not be populated correctly.  The names #/ and / are
+	 * allowed, but other names with / in them draw warnings.
+	 */
+	if(strchr(s, '/') && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0)
+		print("newpath: %s from %lux\n", s, getcallerpc(&s));
+
+	p->mlen = 1;
+	p->malen = PATHMSLOP;
+	p->mtpt = smalloc(p->malen*sizeof p->mtpt[0]);
+	return p;
+}
+
+static Path*
+copypath(Path *p)
+{
+	int i;
+	Path *pp;
+	
+	pp = smalloc(sizeof(Path));
+	pp->ref = 1;
+	incref(&npath);
+	DBG("copypath %s %p => %p\n", p->s, p, pp);
+	
+	pp->len = p->len;
+	pp->alen = p->alen;
+	pp->s = smalloc(p->alen);
+	memmove(pp->s, p->s, p->len+1);
+	
+	pp->mlen = p->mlen;
+	pp->malen = p->malen;
+	pp->mtpt = smalloc(p->malen*sizeof pp->mtpt[0]);
+	for(i=0; i<pp->mlen; i++){
+		pp->mtpt[i] = p->mtpt[i];
+		if(pp->mtpt[i])
+			incref(pp->mtpt[i]);
+	}
+
+	return pp;
 }
 
 void
-cnameclose(Cname *n)
+pathclose(Path *p)
 {
-	if(n == nil)
+	int i;
+	
+	if(p == nil)
 		return;
-	if(decref(n))
+//XXX
+	DBG("pathclose %p %s ref=%ld =>", p, p->s, p->ref);
+	for(i=0; i<p->mlen; i++)
+		DBG(" %p", p->mtpt[i]);
+	DBG("\n");
+
+	if(decref(p))
 		return;
-	decref(&ncname);
-	free(n->s);
-	free(n);
+	decref(&npath);
+	free(p->s);
+	for(i=0; i<p->mlen; i++)
+		if(p->mtpt[i])
+			cclose(p->mtpt[i]);
+	free(p->mtpt);
+	free(p);
 }
 
-Cname*
-addelem(Cname *n, char *s)
+/*
+ * In place, rewrite name to compress multiple /, eliminate ., and process ..
+ * (Really only called to remove a trailing .. that has been added.
+ * Otherwise would need to update n->mtpt as well.)
+ */
+static void
+fixdotdotname(Path *p)
 {
-	int i, a;
-	char *t;
-	Cname *new;
+	char *r;
 
-	if(s[0]=='.' && s[1]=='\0')
-		return n;
+	if(p->s[0] == '#'){
+		r = strchr(p->s, '/');
+		if(r == nil)
+			return;
+		cleanname(r);
 
-	if(n->ref > 1){
+		/*
+		 * The correct name is #i rather than #i/,
+		 * but the correct name of #/ is #/.
+		 */
+		if(strcmp(r, "/")==0 && p->s[1] != '/')
+			*r = '\0';
+	}else
+		cleanname(p->s);
+	p->len = strlen(p->s);
+}
+
+static Path*
+uniquepath(Path *p)
+{
+	Path *new;
+	
+	if(p->ref > 1){
 		/* copy on write */
-		new = newcname(n->s);
-		cnameclose(n);
-		n = new;
+		new = copypath(p);
+		pathclose(p);
+		p = new;
 	}
+	return p;
+}
+
+static Path*
+addelem(Path *p, char *s, Chan *from)
+{
+	char *t;
+	int a, i;
+	Chan *c, **tt;
+
+	if(s[0]=='.' && s[1]=='\0')
+		return p;
+
+	p = uniquepath(p);
 
 	i = strlen(s);
-	if(n->len+1+i+1 > n->alen){
-		a = n->len+1+i+1 + CNAMESLOP;
+	if(p->len+1+i+1 > p->alen){
+		a = p->len+1+i+1 + PATHSLOP;
 		t = smalloc(a);
-		memmove(t, n->s, n->len+1);
-		free(n->s);
-		n->s = t;
-		n->alen = a;
+		memmove(t, p->s, p->len+1);
+		free(p->s);
+		p->s = t;
+		p->alen = a;
 	}
-	if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/')	/* don't insert extra slash if one is present */
-		n->s[n->len++] = '/';
-	memmove(n->s+n->len, s, i+1);
-	n->len += i;
-	if(isdotdot(s))
-		cleancname(n);
-	return n;
+	/* don't insert extra slash if one is present */
+	if(p->len>0 && p->s[p->len-1]!='/' && s[0]!='/')
+		p->s[p->len++] = '/';
+	memmove(p->s+p->len, s, i+1);
+	p->len += i;
+	if(isdotdot(s)){
+		fixdotdotname(p);
+		DBG("addelem %s .. => rm %p\n", p->s, p->mtpt[p->mlen-1]);
+		if(p->mlen>0 && (c = p->mtpt[--p->mlen])){
+			p->mtpt[p->mlen] = nil;
+			cclose(c);
+		}
+	}else{
+		if(p->mlen >= p->malen){
+			p->malen = p->mlen+1+PATHMSLOP;
+			tt = smalloc(p->malen*sizeof tt[0]);
+			memmove(tt, p->mtpt, p->mlen*sizeof tt[0]);
+			free(p->mtpt);
+			p->mtpt = tt;
+		}
+		DBG("addelem %s %s => add %p\n", p->s, s, from);
+		p->mtpt[p->mlen++] = from;
+		if(from)
+			incref(from);
+	}
+	return p;
 }
 
 void
@@ -355,7 +460,8 @@ chanfree(Chan *c)
 		c->mchan = nil;
 	}
 
-	cnameclose(c->name);
+	pathclose(c->path);
+	c->path = nil;
 
 	lock(&chanalloc);
 	c->next = chanalloc.free;
@@ -369,6 +475,7 @@ cclose(Chan *c)
 	if(c->flag&CFREE)
 		panic("cclose %lux", getcallerpc(&c));
 
+	DBG("cclose %p name=%s ref=%ld\n", c, c->path->s, c->ref);
 	if(decref(c))
 		return;
 
@@ -387,7 +494,7 @@ cunique(Chan *c)
 {
 	Chan *nc;
 
-	if(c->ref != 1) {
+	if(c->ref != 1){
 		nc = cclone(c);
 		cclose(c);
 		c = nc;
@@ -403,11 +510,11 @@ eqqid(Qid a, Qid b)
 }
 
 int
-eqchan(Chan *a, Chan *b, int pathonly)
+eqchan(Chan *a, Chan *b, int skipvers)
 {
 	if(a->qid.path != b->qid.path)
 		return 0;
-	if(!pathonly && a->qid.vers!=b->qid.vers)
+	if(!skipvers && a->qid.vers!=b->qid.vers)
 		return 0;
 	if(a->type != b->type)
 		return 0;
@@ -417,11 +524,11 @@ eqchan(Chan *a, Chan *b, int pathonly)
 }
 
 int
-eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly)
+eqchantdqid(Chan *a, int type, int dev, Qid qid, int skipvers)
 {
 	if(a->qid.path != qid.path)
 		return 0;
-	if(!pathonly && a->qid.vers!=qid.vers)
+	if(!skipvers && a->qid.vers!=qid.vers)
 		return 0;
 	if(a->type != type)
 		return 0;
@@ -439,30 +546,23 @@ newmhead(Chan *from)
 	mh->ref = 1;
 	mh->from = from;
 	incref(from);
-
-/*
-	n = from->name->len;
-	if(n >= sizeof(mh->fromname))
-		n = sizeof(mh->fromname)-1;
-	memmove(mh->fromname, from->name->s, n);
-	mh->fromname[n] = 0;
-*/
 	return mh;
 }
 
 int
 cmount(Chan **newp, Chan *old, int flag, char *spec)
 {
-	Pgrp *pg;
 	int order, flg;
+	Chan *new;
 	Mhead *m, **l, *mh;
 	Mount *nm, *f, *um, **h;
-	Chan *new;
+	Pgrp *pg;
 
 	if(QTDIR & (old->qid.type^(*newp)->qid.type))
 		error(Emount);
 
-if(old->umh)print("cmount old extra umh\n");
+	if(old->umh)
+		print("cmount: unexpected umh, caller %.8lux\n", getcallerpc(&newp));
 
 	order = flag&MORDER;
 
@@ -473,20 +573,22 @@ if(old->umh)print("cmount old extra umh\n");
 	mh = new->umh;
 
 	/*
-	 * Not allowed to bind when the old directory
-	 * is itself a union.  (Maybe it should be allowed, but I don't see
-	 * what the semantics would be.)
+	 * Not allowed to bind when the old directory is itself a union. 
+	 * (Maybe it should be allowed, but I don't see what the semantics
+	 * would be.)
 	 *
 	 * We need to check mh->mount->next to tell unions apart from
 	 * simple mount points, so that things like
 	 *	mount -c fd /root
 	 *	bind -c /root /
-	 * work.  The check of mount->mflag catches things like
+	 * work.  
+	 * 
+	 * The check of mount->mflag allows things like
 	 *	mount fd /root
 	 *	bind -c /root /
 	 * 
 	 * This is far more complicated than it should be, but I don't
-	 * see an easier way at the moment.		-rsc
+	 * see an easier way at the moment.
 	 */
 	if((flag&MCREATE) && mh && mh->mount
 	&& (mh->mount->next || !(mh->mount->mflag&MCREATE)))
@@ -496,13 +598,13 @@ if(old->umh)print("cmount old extra umh\n");
 	wlock(&pg->ns);
 
 	l = &MOUNTH(pg, old->qid);
-	for(m = *l; m; m = m->hash) {
+	for(m = *l; m; m = m->hash){
 		if(eqchan(m->from, old, 1))
 			break;
 		l = &m->hash;
 	}
 
-	if(m == nil) {
+	if(m == nil){
 		/*
 		 *  nothing mounted here yet.  create a mount
 		 *  head and add to the hash table.
@@ -525,7 +627,7 @@ if(old->umh)print("cmount old extra umh\n");
 	wunlock(&pg->ns);
 
 	nm = newmount(m, new, flag, spec);
-	if(mh != nil && mh->mount != nil) {
+	if(mh != nil && mh->mount != nil){
 		/*
 		 *  copy a union when binding it onto a directory
 		 */
@@ -534,14 +636,14 @@ if(old->umh)print("cmount old extra umh\n");
 			flg = MAFTER;
 		h = &nm->next;
 		um = mh->mount;
-		for(um = um->next; um; um = um->next) {
+		for(um = um->next; um; um = um->next){
 			f = newmount(m, um->to, flg, um->spec);
 			*h = f;
 			h = &f->next;
 		}
 	}
 
-	if(m->mount && order == MREPL) {
+	if(m->mount && order == MREPL){
 		mountfree(m->mount);
 		m->mount = 0;
 	}
@@ -549,12 +651,11 @@ if(old->umh)print("cmount old extra umh\n");
 	if(flag & MCREATE)
 		nm->mflag |= MCREATE;
 
-	if(m->mount && order == MAFTER) {
+	if(m->mount && order == MAFTER){
 		for(f = m->mount; f->next; f = f->next)
 			;
 		f->next = nm;
-	}
-	else {
+	}else{
 		for(f = nm; f->next; f = f->next)
 			;
 		f->next = m->mount;
@@ -589,19 +690,19 @@ cunmount(Chan *mnt, Chan *mounted)
 	wlock(&pg->ns);
 
 	l = &MOUNTH(pg, mnt->qid);
-	for(m = *l; m; m = m->hash) {
+	for(m = *l; m; m = m->hash){
 		if(eqchan(m->from, mnt, 1))
 			break;
 		l = &m->hash;
 	}
 
-	if(m == 0) {
+	if(m == 0){
 		wunlock(&pg->ns);
 		error(Eunmount);
 	}
 
 	wlock(&m->lock);
-	if(mounted == 0) {
+	if(mounted == 0){
 		*l = m->hash;
 		wunlock(&pg->ns);
 		mountfree(m->mount);
@@ -613,14 +714,14 @@ cunmount(Chan *mnt, Chan *mounted)
 	}
 
 	p = &m->mount;
-	for(f = *p; f; f = f->next) {
+	for(f = *p; f; f = f->next){
 		/* BUG: Needs to be 2 pass */
 		if(eqchan(f->to, mounted, 1) ||
-		  (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) {
+		  (f->to->mchan && eqchan(f->to->mchan, mounted, 1))){
 			*p = f->next;
 			f->next = 0;
 			mountfree(f);
-			if(m->mount == nil) {
+			if(m->mount == nil){
 				*l = m->hash;
 				cclose(m->from);
 				wunlock(&m->lock);
@@ -650,12 +751,13 @@ cclone(Chan *c)
 		error("clone failed");
 	nc = wq->clone;
 	free(wq);
-	nc->name = c->name;
-	if(c->name)
-		incref(c->name);
+	nc->path = c->path;
+	if(c->path)
+		incref(c->path);
 	return nc;
 }
 
+/* also used by sysfile.c:/^mountfix */
 int
 findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid)
 {
@@ -693,58 +795,61 @@ findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid)
 	return 0;
 }
 
-int
-domount(Chan **cp, Mhead **mp)
+/*
+ * Calls findmount but also updates path.
+ */
+static int
+domount(Chan **cp, Mhead **mp, Path **path)
 {
-	return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid);
+	Chan **lc;
+	Path *p;
+
+	if(findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid) == 0)
+		return 0;
+
+	if(path){
+		p = *path;
+		p = uniquepath(p);
+		if(p->mlen <= 0)
+			print("domount: path %s has mlen==%d\n", p->s, p->mlen);
+		else{
+			lc = &p->mtpt[p->mlen-1];
+DBG("domount %p %s => add %p (was %p)\n", p, p->s, (*mp)->from, p->mtpt[p->mlen-1]);
+			incref((*mp)->from);
+			if(*lc)
+				cclose(*lc);
+			*lc = (*mp)->from;
+		}
+		*path = p;
+	}
+	return 1;
 }
 
-Chan*
-undomount(Chan *c, Cname *name)
+/*
+ * If c is the right-hand-side of a mount point, returns the left hand side.
+ * Changes name to reflect the fact that we've uncrossed the mountpoint,
+ * so name had better be ours to change!
+ */
+static Chan*
+undomount(Chan *c, Path *path)
 {
 	Chan *nc;
-	Pgrp *pg;
-	Mount *t;
-	Mhead **h, **he, *f;
 
-	pg = up->pgrp;
-	rlock(&pg->ns);
-	if(waserror()) {
-		runlock(&pg->ns);
-		nexterror();
-	}
+	if(path->ref != 1 || path->mlen == 0)
+		print("undomount: path %s ref %ld mlen %d caller %lux\n",
+			path->s, path->ref, path->mlen, getcallerpc(&c));
 
-	he = &pg->mnthash[MNTHASH];
-	for(h = pg->mnthash; h < he; h++) {
-		for(f = *h; f; f = f->hash) {
-			if(strcmp(f->from->name->s, name->s) != 0)
-				continue;
-			for(t = f->mount; t; t = t->next) {
-				if(eqchan(c, t->to, 1)) {
-					/*
-					 * We want to come out on the left hand side of the mount
-					 * point using the element of the union that we entered on.
-					 * To do this, find the element that has a from name of
-					 * c->name->s.
-					 */
-					if(strcmp(t->head->from->name->s, name->s) != 0)
-						continue;
-					nc = t->head->from;
-					incref(nc);
-					cclose(c);
-					c = nc;
-					break;
-				}
-			}
-		}
+	if(path->mlen>0 && (nc=path->mtpt[path->mlen-1]) != nil){
+DBG("undomount %p %s => remove %p\n", path, path->s, nc);
+		cclose(c);
+		path->mtpt[path->mlen-1] = nil;
+		c = nc;
 	}
-	poperror();
-	runlock(&pg->ns);
 	return c;
 }
 
 /*
- * Walk but catch errors and return nil instead.
+ * Call dev walk but catch errors.
  */
 static Walkqid*
 ewalk(Chan *c, Chan *nc, char **name, int nname)
@@ -767,16 +872,16 @@ int
 walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 {
 	int dev, dotdot, i, n, nhave, ntry, type;
-	Chan *c, *nc;
-	Cname *cname;
-	Mount *f;
+	Chan *c, *nc, *mtpt;
+	Path *path;
 	Mhead *mh, *nmh;
+	Mount *f;
 	Walkqid *wq;
 
 	c = *cp;
 	incref(c);
-	cname = c->name;
-	incref(cname);
+	path = c->path;
+	incref(path);
 	mh = nil;
 
 	/*
@@ -787,13 +892,13 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 	 *    4. repeat.
 	 *
 	 * An invariant is that each time through the loop, c is on the undomount
-	 * side of the mount point, and c's name is cname.
+	 * side of the mount point, and c's full path is path.
 	 */
 	for(nhave=0; nhave<nnames; nhave+=n){
 		if((c->qid.type&QTDIR)==0){
 			if(nerror)
 				*nerror = nhave;
-			cnameclose(cname);
+			pathclose(path);
 			cclose(c);
 			strcpy(up->errstr, Enotdir);
 			if(mh != nil)
@@ -816,8 +921,8 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 		}
 
 		if(!dotdot && !nomount)
-			domount(&c, &mh);
-
+			domount(&c, &mh, &path);
+				
 		type = c->type;
 		dev = c->dev;
 
@@ -839,7 +944,7 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 			}
 			if(wq == nil){
 				cclose(c);
-				cnameclose(cname);
+				pathclose(path);
 				if(nerror)
 					*nerror = nhave+1;
 				if(mh != nil)
@@ -853,11 +958,12 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 			assert(wq->nqid == 1);
 			assert(wq->clone != nil);
 
-			cname = addelem(cname, "..");
-			nc = undomount(wq->clone, cname);
+			path = addelem(path, "..", nil);
+			nc = undomount(wq->clone, path);
 			n = 1;
 		}else{
 			nc = nil;
+			nmh = nil;
 			if(!nomount)
 				for(i=0; i<wq->nqid && i<ntry-1; i++)
 					if(findmount(&nc, &nmh, type, dev, wq->qid[i]))
@@ -865,7 +971,7 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 			if(nc == nil){	/* no mount points along path */
 				if(wq->clone == nil){
 					cclose(c);
-					cnameclose(cname);
+					pathclose(path);
 					if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){
 						if(nerror)
 							*nerror = nhave+wq->nqid+1;
@@ -889,8 +995,12 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 				}
 				n = i+1;
 			}
-			for(i=0; i<n; i++)
-				cname = addelem(cname, names[nhave+i]);
+			for(i=0; i<n; i++){
+				mtpt = nil;
+				if(i==n-1 && nmh)
+					mtpt = nmh->from;
+				path = addelem(path, names[nhave+i], mtpt);
+			}
 		}
 		cclose(c);
 		c = nc;
@@ -909,8 +1019,8 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 		c->umh = nil;
 	}
 
-	cnameclose(c->name);
-	c->name = cname;
+	pathclose(c->path);
+	c->path = path;
 
 	cclose(*cp);
 	*cp = c;
@@ -929,12 +1039,12 @@ createdir(Chan *c, Mhead *m)
 	Mount *f;
 
 	rlock(&m->lock);
-	if(waserror()) {
+	if(waserror()){
 		runlock(&m->lock);
 		nexterror();
 	}
-	for(f = m->mount; f; f = f->next) {
-		if(f->mflag&MCREATE) {
+	for(f = m->mount; f; f = f->next){
+		if(f->mflag&MCREATE){
 			nc = cclone(f->to);
 			runlock(&m->lock);
 			poperror();
@@ -951,31 +1061,6 @@ saveregisters(void)
 {
 }
 
-/*
- * In place, rewrite name to compress multiple /, eliminate ., and process ..
- */
-void
-cleancname(Cname *n)
-{
-	char *p;
-
-	if(n->s[0] == '#'){
-		p = strchr(n->s, '/');
-		if(p == nil)
-			return;
-		cleanname(p);
-
-		/*
-		 * The correct name is #i rather than #i/,
-		 * but the correct name of #/ is #/.
-		 */
-		if(strcmp(p, "/")==0 && n->s[1] != '/')
-			*p = '\0';
-	}else
-		cleanname(n->s);
-	n->len = strlen(n->s);
-}
-
 static void
 growparse(Elemlist *e)
 {
@@ -1035,7 +1120,7 @@ parsename(char *aname, Elemlist *e)
 		name = slash;
 	}
 	
-	if(chandebug){
+	if(0 && chandebug){
 		int i;
 		
 		print("parsename %s:", e->name);
@@ -1129,7 +1214,7 @@ namec(char *aname, int amode, int omode, ulong perm)
 {
 	int len, n, t, nomount;
 	Chan *c, *cnew;
-	Cname *cname;
+	Path *path;
 	Elemlist e;
 	Rune r;
 	Mhead *m;
@@ -1143,6 +1228,7 @@ namec(char *aname, int amode, int omode, ulong perm)
 		free(aname);
 		nexterror();
 	}
+	DBG("namec %s %d %d\n", aname, amode, omode);
 	name = aname;
 
 	/*
@@ -1217,7 +1303,7 @@ namec(char *aname, int amode, int omode, ulong perm)
 		if(e.off[e.nerror]==0)
 			print("nerror=%d but off=%d\n",
 				e.nerror, e.off[e.nerror]);
-		if(chandebug)
+		if(0 && chandebug)
 			print("showing %d+%d/%d (of %d) of %s (%d %d)\n", e.prefix, e.off[e.nerror], e.nerror, e.nelems, aname, e.off[0], e.off[1]);
 		len = e.prefix+e.off[e.nerror];
 		free(e.off);
@@ -1225,7 +1311,7 @@ namec(char *aname, int amode, int omode, ulong perm)
 	}
 
 	/*
-	 * Build a list of elements in the path.
+	 * Build a list of elements in the name.
 	 */
 	parsename(name, &e);
 
@@ -1261,9 +1347,10 @@ namec(char *aname, int amode, int omode, ulong perm)
 
 	switch(amode){
 	case Abind:
+		/* no need to maintain path - cannot dotdot an Abind */
 		m = nil;
 		if(!nomount)
-			domount(&c, &m);
+			domount(&c, &m, nil);
 		if(c->umh != nil)
 			putmhead(c->umh);
 		c->umh = m;
@@ -1273,19 +1360,19 @@ namec(char *aname, int amode, int omode, ulong perm)
 	case Aremove:
 	case Aopen:
 	Open:
-		/* save the name; domount might change c */
-		cname = c->name;
-		incref(cname);
+		/* save&update the name; domount might change c */
+		path = c->path;
+		incref(path);
 		m = nil;
 		if(!nomount)
-			domount(&c, &m);
+			domount(&c, &m, &path);
 
 		/* our own copy to open or remove */
 		c = cunique(c);
 
 		/* now it's our copy anyway, we can put the name back */
-		cnameclose(c->name);
-		c->name = cname;
+		pathclose(c->path);
+		c->path = path;
 
 		/* record whether c is on a mount point */
 		c->ismtpt = m!=nil;
@@ -1414,9 +1501,9 @@ if(c->umh != nil){
 			 * if findmount gave us a new Chan.
 			 */
 			cnew = cunique(cnew);
-			cnameclose(cnew->name);
-			cnew->name = c->name;
-			incref(cnew->name);
+			pathclose(cnew->path);
+			cnew->path = c->path;
+			incref(cnew->path);
 
 			devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
 			poperror();
@@ -1428,7 +1515,7 @@ if(c->umh != nil){
 				putmhead(m);
 			cclose(c);
 			c = cnew;
-			c->name = addelem(c->name, e.elems[e.nelems-1]);
+			c->path = addelem(c->path, e.elems[e.nelems-1], nil);
 			break;
 		}else{		/* create failed */
 			cclose(cnew);
@@ -1513,12 +1600,12 @@ validname0(char *aname, int slashok, int dup, ulong pc)
 	Rune r;
 
 	name = aname;
-	if(((ulong)name & KZERO) != KZERO) {
+	if(((ulong)name & KZERO) != KZERO){
 		if(!dup)
 			print("warning: validname called from %lux with user pointer", pc);
 		p = name;
 		t = BY2PG-((ulong)p&(BY2PG-1));
-		while((ename=vmemchr(p, 0, t)) == nil) {
+		while((ename=vmemchr(p, 0, t)) == nil){
 			p += t;
 			t = BY2PG;
 		}

+ 4 - 4
sys/src/9/port/dev.c

@@ -135,7 +135,7 @@ devattach(int tc, char *spec)
 		spec = "";
 	buf = smalloc(4+strlen(spec)+1);
 	sprint(buf, "#%C%s", tc, spec);
-	c->name = newcname(buf);
+	c->path = newpath(buf);
 	free(buf);
 	return c;
 }
@@ -269,12 +269,12 @@ devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
 		switch((*gen)(c, nil, tab, ntab, i, &dir)){
 		case -1:
 			if(c->qid.type & QTDIR){
-				if(c->name == nil)
+				if(c->path == nil)
 					elem = "???";
-				else if(strcmp(c->name->s, "/") == 0)
+				else if(strcmp(c->path->s, "/") == 0)
 					elem = "/";
 				else
-					for(elem=p=c->name->s; *p; p++)
+					for(elem=p=c->path->s; *p; p++)
 						if(*p == '/')
 							elem = p+1;
 				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);

+ 6 - 6
sys/src/9/port/devmnt.c

@@ -771,11 +771,11 @@ mountrpc(Mnt *m, Mntrpc *r)
 		if(t == r->request.type+1)
 			break;
 		sn = "?";
-		if(m->c->name != nil)
-			sn = m->c->name->s;
+		if(m->c->path != nil)
+			sn = m->c->path->s;
 		cn = "?";
-		if(r->c != nil && r->c->name != nil)
-			cn = r->c->name->s;
+		if(r->c != nil && r->c->path != nil)
+			cn = r->c->path->s;
 		print("mnt: proc %s %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n",
 			up->text, up->pid, sn, cn,
 			r, r->request.tag, r->request.fid, r->request.type,
@@ -1150,12 +1150,12 @@ mntchk(Chan *c)
 	/* This routine is mostly vestiges of prior lives; now it's just sanity checking */
 
 	if(c->mchan == nil)
-		panic("mntchk 1: nil mchan c %s\n", channame(c));
+		panic("mntchk 1: nil mchan c %s\n", chanpath(c));
 
 	m = c->mchan->mux;
 
 	if(m == nil)
-		print("mntchk 2: nil mux c %s c->mchan %s \n", channame(c), channame(c->mchan));
+		print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
 
 	/*
 	 * Was it closed and reused (was error(Eshutdown); now, it cannot happen)

+ 7 - 7
sys/src/9/port/devproc.c

@@ -539,7 +539,7 @@ procfdprint(Chan *c, int fd, int w, char *s, int ns)
 		&"r w rw"[(c->mode&3)<<1],
 		devtab[c->type]->dc, c->dev,
 		c->qid.path, w, c->qid.vers, c->qid.type,
-		c->iounit, c->offset, c->name->s);
+		c->iounit, c->offset, c->path->s);
 	return n;
 }
 
@@ -570,7 +570,7 @@ procfds(Proc *p, char *va, int count, long offset)
 		nexterror();
 	}
 
-	n = readstr(0, a, count, p->dot->name->s);
+	n = readstr(0, a, count, p->dot->path->s);
 	n += snprint(a+n, count-n, "\n");
 	offset = procoffset(offset, a, &n);
 	/* compute width of qid.path */
@@ -935,21 +935,21 @@ procread(Chan *c, void *va, long n, vlong off)
 		mntscan(mw, p);
 		if(mw->mh == 0){
 			mw->cddone = 1;
-			i = snprint(a, n, "cd %s\n", p->dot->name->s);
+			i = snprint(a, n, "cd %s\n", p->dot->path->s);
 			qunlock(&p->debug);
 			poperror();
 			return i;
 		}
 		int2flag(mw->cm->mflag, flag);
-		if(strcmp(mw->cm->to->name->s, "#M") == 0){
+		if(strcmp(mw->cm->to->path->s, "#M") == 0){
 			srv = srvname(mw->cm->to->mchan);
 			i = snprint(a, n, "mount %s %s %s %s\n", flag,
-				srv==nil? mw->cm->to->mchan->name->s : srv,
-				mw->mh->from->name->s, mw->cm->spec? mw->cm->spec : "");
+				srv==nil? mw->cm->to->mchan->path->s : srv,
+				mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
 			free(srv);
 		}else
 			i = snprint(a, n, "bind %s %s %s\n", flag,
-				mw->cm->to->name->s, mw->mh->from->name->s);
+				mw->cm->to->path->s, mw->mh->from->path->s);
 		qunlock(&p->debug);
 		poperror();
 		return i;

+ 2 - 2
sys/src/9/port/fault.c

@@ -44,8 +44,8 @@ faulterror(char *s, Chan *c, int freemem)
 {
 	char buf[ERRMAX];
 
-	if(c && c->name){
-		snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->name->s, up->errstr);
+	if(c && c->path){
+		snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr);
 		s = buf;
 	}
 	if(up->nerrlab) {

+ 8 - 5
sys/src/9/port/portdat.h

@@ -3,7 +3,6 @@ typedef struct Block	Block;
 typedef struct Chan	Chan;
 typedef struct Cmdbuf	Cmdbuf;
 typedef struct Cmdtab	Cmdtab;
-typedef struct Cname	Cname;
 typedef struct Dev	Dev;
 typedef struct Dirtab	Dirtab;
 typedef struct Edf	Edf;
@@ -22,6 +21,7 @@ typedef struct Mnt	Mnt;
 typedef struct Mhead	Mhead;
 typedef struct Note	Note;
 typedef struct Page	Page;
+typedef struct Path	Path;
 typedef struct Palloc	Palloc;
 typedef struct Perf	Perf;
 typedef struct PhysUart	PhysUart;
@@ -186,15 +186,18 @@ struct Chan
 	};
 	Chan*	mchan;			/* channel to mounted server */
 	Qid	mqid;			/* qid of root of mount point */
-	Cname*	name;
+	Path*	path;
 };
 
-struct Cname
+struct Path
 {
 	Ref;
-	int	alen;			/* allocated length */
-	int	len;			/* strlen(s) */
 	char	*s;
+	Chan	**mtpt;			/* mtpt history */
+	int	len;			/* strlen(s) */
+	int	alen;			/* allocated length of s */
+	int	mlen;			/* number of path elements */
+	int	malen;			/* allocated length of mtpt */
 };
 
 struct Dev

+ 3 - 3
sys/src/9/port/portfns.h

@@ -18,7 +18,7 @@ void		bootlinks(void);
 void		cachedel(Image*, ulong);
 void		cachepage(Page*, Image*);
 void		callwithureg(void(*)(Ureg*));
-char*		channame(Chan*);
+char*		chanpath(Chan*);
 int		canlock(Lock*);
 int		canpage(Proc*);
 int		canqlock(QLock*);
@@ -39,7 +39,6 @@ void		closergrp(Rgrp*);
 long		clrfpintr(void);
 void		cmderror(Cmdbuf*, char*);
 int		cmount(Chan**, Chan*, int, char*);
-void		cnameclose(Cname*);
 void		confinit(void);
 int		consactive(void);
 void		(*consdebug)(void);
@@ -192,11 +191,11 @@ int		newfd(Chan*);
 Mhead*		newmhead(Chan*);
 Mount*		newmount(Mhead*, Chan*, int, char*);
 Page*		newpage(int, Segment **, ulong);
+Path*		newpath(char*);
 Pgrp*		newpgrp(void);
 Rgrp*		newrgrp(void);
 Proc*		newproc(void);
 void		nexterror(void);
-Cname*		newcname(char*);
 int		notify(Ureg*);
 int		nrand(int);
 uvlong		ns2fastticks(uvlong);
@@ -209,6 +208,7 @@ void		pageinit(void);
 void		pagersummary(void);
 void		panic(char*, ...);
 Cmdbuf*		parsecmd(char *a, int n);
+void		pathclose(Path*);
 ulong		perfticks(void);
 void		pexit(char*, int);
 int		preempted(void);

+ 11 - 15
sys/src/9/port/sysfile.c

@@ -178,11 +178,7 @@ sysfd2path(ulong *arg)
 	validaddr(arg[1], arg[2], 1);
 
 	c = fdtochan(arg[0], -1, 0, 1);
-
-	if(c->name == nil)
-		snprint((char*)arg[1], arg[2], "<null>");
-	else
-		snprint((char*)arg[1], arg[2], "%s", c->name->s);
+	snprint((char*)arg[1], arg[2], "%s", chanpath(c));
 	cclose(c);
 	return 0;
 }
@@ -918,18 +914,18 @@ validstat(uchar *s, int n)
 }
 
 static char*
-cnamelast(Cname *n)
+pathlast(Path *p)
 {
 	char *s;
 
-	if(n == nil)
+	if(p == nil)
 		return nil;
-	if(n->len == 0)
+	if(p->len == 0)
 		return nil;
-	s = strrchr(n->s, '/');
+	s = strrchr(p->s, '/');
 	if(s)
 		return s+1;
-	return n->s;
+	return p->s;
 }
 
 long
@@ -967,7 +963,7 @@ sysstat(ulong *arg)
 		nexterror();
 	}
 	l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
-	name = cnamelast(c->name);
+	name = pathlast(c->path);
 	if(name)
 		l = dirsetname(name, strlen(name), (uchar*)arg[1], l, arg[2]);
 
@@ -1199,11 +1195,11 @@ wstat(Chan *c, uchar *d, int nd)
 	if(c->ismtpt){
 		/*
 		 * Renaming mount points is disallowed to avoid surprises
-		 * (which should be renamed: the mount point or the mounted Chan?).
+		 * (which should be renamed? the mount point or the mounted Chan?).
 		 */
 		dirname(d, &namelen);
 		if(namelen)
-			nameerror(channame(c), Eismtpt);
+			nameerror(chanpath(c), Eismtpt);
 	}
 	l = devtab[c->type]->wstat(c, d, nd);
 	poperror();
@@ -1293,7 +1289,7 @@ sys_stat(ulong *arg)
 	/* buf contains a new stat buf; convert to old. yuck. */
 	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
 		error(old);
-	name = cnamelast(c->name);
+	name = pathlast(c->path);
 	if(name)
 		l = dirsetname(name, strlen(name), buf, l, sizeof buf);
 	l = convM2D(buf, l, &d, strs);
@@ -1327,7 +1323,7 @@ sys_fstat(ulong *arg)
 	/* buf contains a new stat buf; convert to old. yuck. */
 	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
 		error(old);
-	name = cnamelast(c->name);
+	name = pathlast(c->path);
 	if(name)
 		l = dirsetname(name, strlen(name), buf, l, sizeof buf);
 	l = convM2D(buf, l, &d, strs);

+ 3 - 0
sys/src/9/port/sysproc.c

@@ -16,6 +16,9 @@ extern void checkpages(void);
 long
 sysr1(ulong*)
 {
+	extern int chandebug;
+	
+	chandebug = !chandebug;
 	checkpages();
 	return 0;
 }

+ 2 - 2
sys/src/9/ppc/main.c

@@ -160,8 +160,8 @@ init0(void)
 	 * Then early kproc's will have a root and dot.
 	 */
 	up->slash = namec("#/", Atodir, 0, 0);
-	cnameclose(up->slash->name);
-	up->slash->name = newcname("/");
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
 	up->dot = cclone(up->slash);
 
 	chandevinit();

+ 5 - 3
sys/src/cmd/disk/prep/fdisk.c

@@ -188,7 +188,7 @@ struct Tentry {
 	uchar	endh;			/* ending head */
 	uchar	ends;			/* ending sector */
 	uchar	endc;			/* ending cylinder */
-	uchar	xlba[4];			/* starting LBA from beginning of disc or ext. partition */
+	uchar	xlba[4];		/* starting LBA from beginning of disc or ext. partition */
 	uchar	xsize[4];		/* size in sectors */
 };
 
@@ -211,10 +211,11 @@ enum {
 	TypeOS2BOOT	= 0x0A,		/* OS/2 Boot Manager */
 	TypeFAT32	= 0x0B,		/* FAT 32 */
 	TypeFAT32LBA	= 0x0C,		/* FAT 32 needing LBA support */
+	TypeFAT16X	= 0x0E,		/* FAT 16 needing LBA support */
 	TypeEXTHUGE	= 0x0F,		/* FAT 32 extended partition */
 	TypeUNFORMATTED	= 0x16,		/* unformatted primary partition (OS/2 FDISK)? */
 	TypeHPFS2	= 0x17,
-	TypeIBMRecovery = 0x1C,	/* really hidden fat */
+	TypeIBMRecovery = 0x1C,		/* really hidden fat */
 	TypeCPM0	= 0x52,
 	TypeDMDDO	= 0x54,		/* Disk Manager Dynamic Disk Overlay */
 	TypeGB		= 0x56,		/* ???? */
@@ -234,7 +235,7 @@ enum {
 	TypeBSDISWAP	= 0xB8,
 	TypeOTHER	= 0xDA,
 	TypeCPM		= 0xDB,
-	TypeDellRecovery	= 0xDE,
+	TypeDellRecovery= 0xDE,
 	TypeSPEEDSTOR12	= 0xE1,
 	TypeSPEEDSTOR16	= 0xE4,
 	TypeLANSTEP	= 0xFE,
@@ -276,6 +277,7 @@ static Type types[256] = {
 	[TypeFAT16]		{ "FAT16", "dos" },
 	[TypeFAT32]		{ "FAT32", "dos" },
 	[TypeFAT32LBA]		{ "FAT32LBA", "dos" },
+	[TypeFAT16X]		{ "FAT16X", "dos" },
 	[TypeEXTHUGE]		{ "EXTHUGE", "" },
 	[TypeIBMRecovery]	{ "IBMRECOVERY", "ibm" },
 	[TypeEXTENDED]		{ "EXTENDED", "" },