Update mount implementation, add mount integration tests, and check that path exists.
parent
12e41aeaba
commit
8e801e3975
|
@ -26,7 +26,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv/examples/ufs"
|
||||
"k8s.io/minikube/third_party/go9p/ufs"
|
||||
)
|
||||
|
||||
// mountCmd represents the mount command
|
||||
|
@ -42,6 +42,15 @@ var mountCmd = &cobra.Command{
|
|||
fmt.Fprintln(os.Stderr, errText)
|
||||
os.Exit(1)
|
||||
}
|
||||
if _, err := os.Stat(args[0]); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
errText := fmt.Sprintf("Cannot find directory %s for mount", args[0])
|
||||
fmt.Fprintln(os.Stderr, errText)
|
||||
} else {
|
||||
errText := fmt.Sprintf("Error accesssing directory %s for mount", args[0])
|
||||
fmt.Fprintln(os.Stderr, errText)
|
||||
}
|
||||
}
|
||||
var debugVal int
|
||||
if glog.V(1) {
|
||||
debugVal = 1 // ufs.StartServer takes int debug param
|
||||
|
|
|
@ -30,6 +30,7 @@ gsutil cp gs://minikube-builds/${MINIKUBE_LOCATION}/minikube-${OS_ARCH} out/
|
|||
gsutil cp gs://minikube-builds/${MINIKUBE_LOCATION}/e2e-${OS_ARCH} out/
|
||||
gsutil cp gs://minikube-builds/${MINIKUBE_LOCATION}/testdata/busybox.yaml testdata/
|
||||
gsutil cp gs://minikube-builds/${MINIKUBE_LOCATION}/testdata/pvc.yaml testdata/
|
||||
gsutil cp gs://minikube-builds/${MINIKUBE_LOCATION}/testdata/busybox-mount-test.yaml testdata/
|
||||
|
||||
# Set the executable bit on the e2e binary and out binary
|
||||
chmod +x out/e2e-${OS_ARCH}
|
||||
|
@ -63,4 +64,4 @@ curl "https://api.github.com/repos/kubernetes/minikube/statuses/${COMMIT}?access
|
|||
-d "{\"state\": \"$status\", \"description\": \"Jenkins\", \"target_url\": \"$target_url\", \"context\": \"${JOB_NAME}\"}"
|
||||
set -x
|
||||
|
||||
exit $result
|
||||
exit $result
|
||||
|
|
|
@ -408,6 +408,7 @@ func Mount9pHost(api libmachine.API) error {
|
|||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting the host IP address to use from within the VM")
|
||||
}
|
||||
host.RunSSHCommand(GetMount9pCleanupCommand())
|
||||
_, err = host.RunSSHCommand(GetMount9pCommand(ip))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -77,7 +77,7 @@ func getVMHostIP(host *host.Host) (net.IP, error) {
|
|||
case "virtualbox":
|
||||
return net.ParseIP("10.0.2.2"), nil
|
||||
case "xhyve":
|
||||
return net.ParseIP("10.0.2.2"), nil
|
||||
return net.ParseIP("192.168.64.1"), nil
|
||||
default:
|
||||
return []byte{}, errors.New("Error, attempted to get host ip address for unsupported driver")
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ func GenLocalkubeStartCmd(kubernetesConfig KubernetesConfig) (string, error) {
|
|||
flagVals = append(flagVals, "--feature-gates="+kubernetesConfig.FeatureGates)
|
||||
}
|
||||
|
||||
if kubernetesConfig.APIServerName != "" {
|
||||
if kubernetesConfig.APIServerName != constants.APIServerName {
|
||||
flagVals = append(flagVals, "--apiserver-name="+kubernetesConfig.APIServerName)
|
||||
}
|
||||
|
||||
|
@ -226,9 +226,16 @@ else
|
|||
fi
|
||||
`, constants.LocalkubePIDPath)
|
||||
|
||||
func GetMount9pCleanupCommand() string {
|
||||
return `
|
||||
sudo umount /mount-9p;
|
||||
sudo rm -rf /mount-9p;
|
||||
`
|
||||
}
|
||||
|
||||
func GetMount9pCommand(ip net.IP) string {
|
||||
return fmt.Sprintf(`
|
||||
sudo mkdir /mount-9p;
|
||||
sudo mount -t 9p -o trans=tcp -o port=5640 %s /mount-9p;
|
||||
sudo mount -t 9p -o trans=tcp -o port=5640 -o uid=1001 -o gid=1001 %s /mount-9p;
|
||||
sudo chmod 775 /mount-9p;`, ip)
|
||||
}
|
||||
|
|
|
@ -41,4 +41,5 @@ func TestFunctional(t *testing.T) {
|
|||
t.Run("Dashboard", testDashboard)
|
||||
t.Run("ServicesList", testServicesList)
|
||||
t.Run("Provisioning", testProvisioning)
|
||||
t.Run("Mounting", testMounting)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
// +build integration
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
||||
func testMounting(t *testing.T) {
|
||||
t.Parallel()
|
||||
minikubeRunner := util.MinikubeRunner{
|
||||
Args: *args,
|
||||
BinaryPath: *binaryPath,
|
||||
T: t}
|
||||
|
||||
tempDir, err := ioutil.TempDir("", "mounttest")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error while creating tempDir: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
mountCmd := fmt.Sprintf("mount %s", tempDir)
|
||||
cmd := minikubeRunner.RunDaemon(mountCmd)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
kubectlRunner := util.NewKubectlRunner(t)
|
||||
podName := "busybox"
|
||||
podPath, _ := filepath.Abs("testdata/busybox-mount-test.yaml")
|
||||
|
||||
// Write file in mounted dir from host
|
||||
expected := "test\n"
|
||||
files := []string{"fromhost", "fromhostremove"}
|
||||
for _, file := range files {
|
||||
path := filepath.Join(tempDir, file)
|
||||
err = ioutil.WriteFile(path, []byte(expected), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error while writing file %s: %s.", path, err)
|
||||
}
|
||||
}
|
||||
mountTest := func() error {
|
||||
if _, err := kubectlRunner.RunCommand([]string{"create", "-f", podPath}); err != nil {
|
||||
return err
|
||||
}
|
||||
defer kubectlRunner.RunCommand([]string{"delete", "-f", podPath})
|
||||
|
||||
p := &api.Pod{}
|
||||
for p.Status.Phase != "Running" {
|
||||
p = kubectlRunner.GetPod(podName, "default")
|
||||
}
|
||||
|
||||
path := filepath.Join(tempDir, "frompod")
|
||||
out, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return &commonutil.RetriableError{Err: err}
|
||||
}
|
||||
// test that file written from pod can be read from host echo test > /mount-9p/frompod; in pod
|
||||
if string(out) != expected {
|
||||
t.Fatalf("Expected file %s to contain text %s, was %s.", path, expected, out)
|
||||
}
|
||||
|
||||
// test that file written from host was read in by the pod via cat /mount-9p/fromhost;
|
||||
if out, err = kubectlRunner.RunCommand([]string{"logs", podName}); err != nil {
|
||||
return &commonutil.RetriableError{Err: err}
|
||||
}
|
||||
if string(out) != expected {
|
||||
t.Fatalf("Expected file %s to contain text %s, was %s.", path, expected, out)
|
||||
}
|
||||
|
||||
// test that fromhostremove was deleted by the pod from the mount via rm /mount-9p/fromhostremove
|
||||
path = filepath.Join(tempDir, "fromhostremove")
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
t.Fatalf("Expected file %s to be removed", path, expected, out)
|
||||
}
|
||||
|
||||
// test that frompodremove can be deleted on the host
|
||||
path = filepath.Join(tempDir, "frompodremove")
|
||||
if err := os.Remove(path); err != nil {
|
||||
t.Fatalf("Unexpected error removing file %s: %s", path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := commonutil.RetryAfter(40, mountTest, 5*time.Second); err != nil {
|
||||
t.Fatal("mountTest failed with error:", err)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: busybox
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox:glibc
|
||||
command: [ "/bin/sh", "-c", "--" ]
|
||||
args: [ "cat /mount-9p/fromhost; echo test > /mount-9p/frompod; rm /mount-9p/fromhostremove; echo test > /mount-9p/frompodremove;" ]
|
||||
name: busybox
|
||||
volumeMounts:
|
||||
- mountPath: /mount-9p
|
||||
name: test-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
hostPath:
|
||||
# directory location on host
|
||||
path: /mount-9p
|
||||
|
|
@ -69,6 +69,17 @@ func (m *MinikubeRunner) RunCommand(command string, checkError bool) string {
|
|||
return string(stdout)
|
||||
}
|
||||
|
||||
func (m *MinikubeRunner) RunDaemon(command string) *exec.Cmd {
|
||||
commandArr := strings.Split(command, " ")
|
||||
path, _ := filepath.Abs(m.BinaryPath)
|
||||
cmd := exec.Command(path, commandArr...)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
m.T.Fatalf("Error running command: %s %s", command, err)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (m *MinikubeRunner) SSH(command string) (string, error) {
|
||||
path, _ := filepath.Abs(m.BinaryPath)
|
||||
cmd := exec.Command(path, "ssh", command)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
*.orig
|
||||
*.rej
|
|
@ -1,13 +0,0 @@
|
|||
# This is the official list of Go9p authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Latchesar Ionkov <lionkov@gmail.com>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
|
@ -1,18 +0,0 @@
|
|||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the Go9p repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# The submission process automatically checks to make sure
|
||||
# that people submitting code are listed in this file (by email address).
|
||||
# XXX more bumph here?
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Latchesar Ionkov <lionkov@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
|
@ -0,0 +1,11 @@
|
|||
This is go9p done in a way that I can understand.
|
||||
|
||||
To install:
|
||||
export GOPATH=~rminnich/go
|
||||
go get -a /k8s.io/minikube/third_party/go9p
|
||||
go get -a /k8s.io/minikube/third_party/go9p/ufs
|
||||
go install -a /k8s.io/minikube/third_party/go9p/ufs
|
||||
|
||||
~/go/bin/ufs
|
||||
|
||||
|
121
third_party/go9p/p/clnt/clnt.go → third_party/go9p/clnt_clnt.go
vendored
Executable file → Normal file
121
third_party/go9p/p/clnt/clnt.go → third_party/go9p/clnt_clnt.go
vendored
Executable file → Normal file
|
@ -2,31 +2,18 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The clnt package provides definitions and functions used to implement
|
||||
// The clnt package go9provides definitions and functions used to implement
|
||||
// a 9P2000 file client.
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Debug flags
|
||||
const (
|
||||
DbgPrintFcalls = (1 << iota) // print all 9P messages on stderr
|
||||
DbgPrintPackets // print the raw packets on stderr
|
||||
DbgLogFcalls // keep the last N 9P messages (can be accessed over http)
|
||||
DbgLogPackets // keep the last N 9P messages (can be accessed over http)
|
||||
)
|
||||
|
||||
type StatsOps interface {
|
||||
statsRegister()
|
||||
statsUnregister()
|
||||
}
|
||||
|
||||
// The Clnt type represents a 9P2000 client. The client is connected to
|
||||
// a 9P2000 file server and its methods can be used to access and manipulate
|
||||
// the files exported by the server.
|
||||
|
@ -37,7 +24,7 @@ type Clnt struct {
|
|||
Dotu bool // If true, 9P2000.u protocol is spoken
|
||||
Root *Fid // Fid that points to the rood directory
|
||||
Id string // Used when printing debug messages
|
||||
Log *p.Logger
|
||||
Log *Logger
|
||||
|
||||
conn net.Conn
|
||||
tagpool *pool
|
||||
|
@ -49,7 +36,7 @@ type Clnt struct {
|
|||
err error
|
||||
|
||||
reqchan chan *Req
|
||||
tchan chan *p.Fcall
|
||||
tchan chan *Fcall
|
||||
|
||||
next, prev *Clnt
|
||||
}
|
||||
|
@ -60,33 +47,26 @@ type Fid struct {
|
|||
sync.Mutex
|
||||
Clnt *Clnt // Client the fid belongs to
|
||||
Iounit uint32
|
||||
p.Qid // The Qid description for the file
|
||||
Mode uint8 // Open mode (one of p.O* values) (if file is open)
|
||||
Qid // The Qid description for the file
|
||||
Mode uint8 // Open mode (one of O* values) (if file is open)
|
||||
Fid uint32 // Fid number
|
||||
p.User // The user the fid belongs to
|
||||
User // The user the fid belongs to
|
||||
walked bool // true if the fid points to a walked file on the server
|
||||
}
|
||||
|
||||
// The file is similar to the Fid, but is used in the high-level client
|
||||
// interface.
|
||||
// interface. We expose the Fid so that client code can use Remove
|
||||
// on a fid, the same way a kernel can.
|
||||
type File struct {
|
||||
fid *Fid
|
||||
Fid *Fid
|
||||
offset uint64
|
||||
}
|
||||
|
||||
type pool struct {
|
||||
sync.Mutex
|
||||
need int
|
||||
nchan chan uint32
|
||||
maxid uint32
|
||||
imap []byte
|
||||
}
|
||||
|
||||
type Req struct {
|
||||
sync.Mutex
|
||||
Clnt *Clnt
|
||||
Tc *p.Fcall
|
||||
Rc *p.Fcall
|
||||
Tc *Fcall
|
||||
Rc *Fcall
|
||||
Err error
|
||||
Done chan *Req
|
||||
tag uint16
|
||||
|
@ -101,18 +81,18 @@ type ClntList struct {
|
|||
|
||||
var clnts *ClntList
|
||||
var DefaultDebuglevel int
|
||||
var DefaultLogger *p.Logger
|
||||
var DefaultLogger *Logger
|
||||
|
||||
func (clnt *Clnt) Rpcnb(r *Req) error {
|
||||
var tag uint16
|
||||
|
||||
if r.Tc.Type == p.Tversion {
|
||||
tag = p.NOTAG
|
||||
if r.Tc.Type == Tversion {
|
||||
tag = NOTAG
|
||||
} else {
|
||||
tag = r.tag
|
||||
}
|
||||
|
||||
p.SetTag(r.Tc, tag)
|
||||
SetTag(r.Tc, tag)
|
||||
clnt.Lock()
|
||||
if clnt.err != nil {
|
||||
clnt.Unlock()
|
||||
|
@ -133,7 +113,7 @@ func (clnt *Clnt) Rpcnb(r *Req) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (clnt *Clnt) Rpc(tc *p.Fcall) (rc *p.Fcall, err error) {
|
||||
func (clnt *Clnt) Rpc(tc *Fcall) (rc *Fcall, err error) {
|
||||
r := clnt.ReqAlloc()
|
||||
r.Tc = tc
|
||||
r.Done = make(chan *Req)
|
||||
|
@ -151,13 +131,15 @@ func (clnt *Clnt) Rpc(tc *p.Fcall) (rc *p.Fcall, err error) {
|
|||
|
||||
func (clnt *Clnt) recv() {
|
||||
var err error
|
||||
var buf []byte
|
||||
|
||||
err = nil
|
||||
buf := make([]byte, clnt.Msize*8)
|
||||
pos := 0
|
||||
for {
|
||||
if len(buf) < int(clnt.Msize) {
|
||||
b := make([]byte, clnt.Msize*8)
|
||||
// Connect can change the client Msize.
|
||||
clntmsize := int(atomic.LoadUint32(&clnt.Msize))
|
||||
if len(buf) < clntmsize {
|
||||
b := make([]byte, clntmsize*8)
|
||||
copy(b, buf[0:pos])
|
||||
buf = b
|
||||
b = nil
|
||||
|
@ -165,7 +147,7 @@ func (clnt *Clnt) recv() {
|
|||
|
||||
n, oerr := clnt.conn.Read(buf[pos:])
|
||||
if oerr != nil || n == 0 {
|
||||
err = &p.Error{oerr.Error(), p.EIO}
|
||||
err = &Error{oerr.Error(), EIO}
|
||||
clnt.Lock()
|
||||
clnt.err = err
|
||||
clnt.Unlock()
|
||||
|
@ -174,10 +156,10 @@ func (clnt *Clnt) recv() {
|
|||
|
||||
pos += n
|
||||
for pos > 4 {
|
||||
sz, _ := p.Gint32(buf)
|
||||
sz, _ := Gint32(buf)
|
||||
if pos < int(sz) {
|
||||
if len(buf) < int(sz) {
|
||||
b := make([]byte, clnt.Msize*8)
|
||||
b := make([]byte, atomic.LoadUint32(&clnt.Msize)*8)
|
||||
copy(b, buf[0:pos])
|
||||
buf = b
|
||||
b = nil
|
||||
|
@ -186,7 +168,7 @@ func (clnt *Clnt) recv() {
|
|||
break
|
||||
}
|
||||
|
||||
fc, err, fcsize := p.Unpack(buf, clnt.Dotu)
|
||||
fc, err, fcsize := Unpack(buf, clnt.Dotu)
|
||||
clnt.Lock()
|
||||
if err != nil {
|
||||
clnt.err = err
|
||||
|
@ -214,7 +196,7 @@ func (clnt *Clnt) recv() {
|
|||
}
|
||||
|
||||
if r == nil {
|
||||
clnt.err = &p.Error{"unexpected response", p.EINVAL}
|
||||
clnt.err = &Error{"unexpected response", EINVAL}
|
||||
clnt.conn.Close()
|
||||
clnt.Unlock()
|
||||
goto closed
|
||||
|
@ -235,13 +217,13 @@ func (clnt *Clnt) recv() {
|
|||
clnt.Unlock()
|
||||
|
||||
if r.Tc.Type != r.Rc.Type-1 {
|
||||
if r.Rc.Type != p.Rerror {
|
||||
r.Err = &p.Error{"invalid response", p.EINVAL}
|
||||
if r.Rc.Type != Rerror {
|
||||
r.Err = &Error{"invalid response", EINVAL}
|
||||
log.Println(fmt.Sprintf("TTT %v", r.Tc))
|
||||
log.Println(fmt.Sprintf("RRR %v", r.Rc))
|
||||
} else {
|
||||
if r.Err == nil {
|
||||
r.Err = &p.Error{r.Rc.Error, r.Rc.Errornum}
|
||||
r.Err = &Error{r.Rc.Error, r.Rc.Errornum}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,12 +317,12 @@ func NewClnt(c net.Conn, msize uint32, dotu bool) *Clnt {
|
|||
clnt.Debuglevel = DefaultDebuglevel
|
||||
clnt.Log = DefaultLogger
|
||||
clnt.Id = c.RemoteAddr().String() + ":"
|
||||
clnt.tagpool = newPool(uint32(p.NOTAG))
|
||||
clnt.fidpool = newPool(p.NOFID)
|
||||
clnt.tagpool = newPool(uint32(NOTAG))
|
||||
clnt.fidpool = newPool(NOFID)
|
||||
clnt.reqout = make(chan *Req)
|
||||
clnt.done = make(chan bool)
|
||||
clnt.reqchan = make(chan *Req, 16)
|
||||
clnt.tchan = make(chan *p.Fcall, 16)
|
||||
clnt.tchan = make(chan *Fcall, 16)
|
||||
|
||||
go clnt.recv()
|
||||
go clnt.send()
|
||||
|
@ -373,8 +355,9 @@ func Connect(c net.Conn, msize uint32, dotu bool) (*Clnt, error) {
|
|||
ver = "9P2000.u"
|
||||
}
|
||||
|
||||
tc := p.NewFcall(clnt.Msize)
|
||||
err := p.PackTversion(tc, clnt.Msize, ver)
|
||||
clntmsize := atomic.LoadUint32(&clnt.Msize)
|
||||
tc := NewFcall(clntmsize)
|
||||
err := PackTversion(tc, clntmsize, ver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -384,8 +367,8 @@ func Connect(c net.Conn, msize uint32, dotu bool) (*Clnt, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if rc.Msize < clnt.Msize {
|
||||
clnt.Msize = rc.Msize
|
||||
if rc.Msize < atomic.LoadUint32(&clnt.Msize) {
|
||||
atomic.StoreUint32(&clnt.Msize, rc.Msize)
|
||||
}
|
||||
|
||||
clnt.Dotu = rc.Version == "9P2000.u" && clnt.Dotu
|
||||
|
@ -401,17 +384,17 @@ func (clnt *Clnt) FidAlloc() *Fid {
|
|||
return fid
|
||||
}
|
||||
|
||||
func (clnt *Clnt) NewFcall() *p.Fcall {
|
||||
func (clnt *Clnt) NewFcall() *Fcall {
|
||||
select {
|
||||
case tc := <-clnt.tchan:
|
||||
return tc
|
||||
default:
|
||||
}
|
||||
return p.NewFcall(clnt.Msize)
|
||||
return NewFcall(atomic.LoadUint32(&clnt.Msize))
|
||||
}
|
||||
|
||||
func (clnt *Clnt) FreeFcall(fc *p.Fcall) {
|
||||
if fc != nil && len(fc.Buf) >= int(clnt.Msize) {
|
||||
func (clnt *Clnt) FreeFcall(fc *Fcall) {
|
||||
if fc != nil && len(fc.Buf) >= int(atomic.LoadUint32(&clnt.Msize)) {
|
||||
select {
|
||||
case clnt.tchan <- fc:
|
||||
break
|
||||
|
@ -450,15 +433,7 @@ func (clnt *Clnt) ReqFree(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func NewFile(f *Fid, offset uint64) *File {
|
||||
return &File{f, offset}
|
||||
}
|
||||
|
||||
func (f *File) Fid() *Fid {
|
||||
return f.fid
|
||||
}
|
||||
|
||||
func (clnt *Clnt) logFcall(fc *p.Fcall) {
|
||||
func (clnt *Clnt) logFcall(fc *Fcall) {
|
||||
if clnt.Debuglevel&DbgLogPackets != 0 {
|
||||
pkt := make([]byte, len(fc.Pkt))
|
||||
copy(pkt, fc.Pkt)
|
||||
|
@ -466,13 +441,19 @@ func (clnt *Clnt) logFcall(fc *p.Fcall) {
|
|||
}
|
||||
|
||||
if clnt.Debuglevel&DbgLogFcalls != 0 {
|
||||
f := new(p.Fcall)
|
||||
f := new(Fcall)
|
||||
*f = *fc
|
||||
f.Pkt = nil
|
||||
clnt.Log.Log(f, clnt, DbgLogFcalls)
|
||||
}
|
||||
}
|
||||
|
||||
// FidFile returns a File that represents the given Fid, initially at the given
|
||||
// offset.
|
||||
func FidFile(fid *Fid, offset uint64) *File {
|
||||
return &File{fid, offset}
|
||||
}
|
||||
|
||||
func init() {
|
||||
clnts = new(ClntList)
|
||||
if sop, ok := (interface{}(clnts)).(StatsOps); ok {
|
|
@ -2,16 +2,14 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
package go9p
|
||||
|
||||
// Clunks a fid. Returns nil if successful.
|
||||
func (clnt *Clnt) Clunk(fid *Fid) (err error) {
|
||||
err = nil
|
||||
if fid.walked {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTclunk(tc, fid.Fid)
|
||||
err := PackTclunk(tc, fid.Fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,12 +19,12 @@ func (clnt *Clnt) Clunk(fid *Fid) (err error) {
|
|||
|
||||
clnt.fidpool.putId(fid.Fid)
|
||||
fid.walked = false
|
||||
fid.Fid = p.NOFID
|
||||
fid.Fid = NOFID
|
||||
return
|
||||
}
|
||||
|
||||
// Closes a file. Returns nil if successful.
|
||||
func (file *File) Close() error {
|
||||
// Should we cancel all pending requests for the File
|
||||
return file.fid.Clnt.Clunk(file.fid)
|
||||
return file.Fid.Clnt.Clunk(file.Fid)
|
||||
}
|
|
@ -2,19 +2,18 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Creates an authentication fid for the specified user. Returns the fid, if
|
||||
// successful, or an Error.
|
||||
func (clnt *Clnt) Auth(user p.User, aname string) (*Fid, error) {
|
||||
func (clnt *Clnt) Auth(user User, aname string) (*Fid, error) {
|
||||
fid := clnt.FidAlloc()
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTauth(tc, fid.Fid, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
|
||||
err := PackTauth(tc, fid.Fid, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -24,7 +23,6 @@ func (clnt *Clnt) Auth(user p.User, aname string) (*Fid, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fid.Iounit = clnt.Msize - p.IOHDRSZ
|
||||
fid.User = user
|
||||
fid.walked = true
|
||||
return fid, nil
|
||||
|
@ -33,18 +31,18 @@ func (clnt *Clnt) Auth(user p.User, aname string) (*Fid, error) {
|
|||
// Creates a fid for the specified user that points to the root
|
||||
// of the file server's file tree. Returns a Fid pointing to the root,
|
||||
// if successful, or an Error.
|
||||
func (clnt *Clnt) Attach(afid *Fid, user p.User, aname string) (*Fid, error) {
|
||||
func (clnt *Clnt) Attach(afid *Fid, user User, aname string) (*Fid, error) {
|
||||
var afno uint32
|
||||
|
||||
if afid != nil {
|
||||
afno = afid.Fid
|
||||
} else {
|
||||
afno = p.NOFID
|
||||
afno = NOFID
|
||||
}
|
||||
|
||||
fid := clnt.FidAlloc()
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTattach(tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
|
||||
err := PackTattach(tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -61,17 +59,17 @@ func (clnt *Clnt) Attach(afid *Fid, user p.User, aname string) (*Fid, error) {
|
|||
}
|
||||
|
||||
// Connects to a file server and attaches to it as the specified user.
|
||||
func Mount(ntype, addr, aname string, user p.User) (*Clnt, error) {
|
||||
func Mount(ntype, addr, aname string, msize uint32, user User) (*Clnt, error) {
|
||||
c, e := net.Dial(ntype, addr)
|
||||
if e != nil {
|
||||
return nil, &p.Error{e.Error(), p.EIO}
|
||||
return nil, &Error{e.Error(), EIO}
|
||||
}
|
||||
|
||||
return MountConn(c, aname, user)
|
||||
return MountConn(c, aname, msize, user)
|
||||
}
|
||||
|
||||
func MountConn(c net.Conn, aname string, user p.User) (*Clnt, error) {
|
||||
clnt, err := Connect(c, 8192+p.IOHDRSZ, true)
|
||||
func MountConn(c net.Conn, aname string, msize uint32, user User) (*Clnt, error) {
|
||||
clnt, err := Connect(c, msize+IOHDRSZ, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -89,7 +87,7 @@ func MountConn(c net.Conn, aname string, user p.User) (*Clnt, error) {
|
|||
// Closes the connection to the file sever.
|
||||
func (clnt *Clnt) Unmount() {
|
||||
clnt.Lock()
|
||||
clnt.err = &p.Error{"connection closed", p.EIO}
|
||||
clnt.err = &Error{"connection closed", EIO}
|
||||
clnt.conn.Close()
|
||||
clnt.Unlock()
|
||||
}
|
|
@ -2,10 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -13,7 +12,7 @@ import (
|
|||
// the operation is successful.
|
||||
func (clnt *Clnt) Open(fid *Fid, mode uint8) error {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTopen(tc, fid.Fid, mode)
|
||||
err := PackTopen(tc, fid.Fid, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -25,8 +24,8 @@ func (clnt *Clnt) Open(fid *Fid, mode uint8) error {
|
|||
|
||||
fid.Qid = rc.Qid
|
||||
fid.Iounit = rc.Iounit
|
||||
if fid.Iounit == 0 || fid.Iounit > clnt.Msize-p.IOHDRSZ {
|
||||
fid.Iounit = clnt.Msize - p.IOHDRSZ
|
||||
if fid.Iounit == 0 || fid.Iounit > clnt.Msize-IOHDRSZ {
|
||||
fid.Iounit = clnt.Msize - IOHDRSZ
|
||||
}
|
||||
fid.Mode = mode
|
||||
return nil
|
||||
|
@ -36,7 +35,7 @@ func (clnt *Clnt) Open(fid *Fid, mode uint8) error {
|
|||
// if the operation is successful.
|
||||
func (clnt *Clnt) Create(fid *Fid, name string, perm uint32, mode uint8, ext string) error {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTcreate(tc, fid.Fid, name, perm, mode, ext, clnt.Dotu)
|
||||
err := PackTcreate(tc, fid.Fid, name, perm, mode, ext, clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -48,8 +47,8 @@ func (clnt *Clnt) Create(fid *Fid, name string, perm uint32, mode uint8, ext str
|
|||
|
||||
fid.Qid = rc.Qid
|
||||
fid.Iounit = rc.Iounit
|
||||
if fid.Iounit == 0 || fid.Iounit > clnt.Msize-p.IOHDRSZ {
|
||||
fid.Iounit = clnt.Msize - p.IOHDRSZ
|
||||
if fid.Iounit == 0 || fid.Iounit > clnt.Msize-IOHDRSZ {
|
||||
fid.Iounit = clnt.Msize - IOHDRSZ
|
||||
}
|
||||
fid.Mode = mode
|
||||
return nil
|
|
@ -2,7 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import "sync"
|
||||
|
||||
var m2id = [...]uint8{
|
||||
0, 1, 0, 2, 0, 1, 0, 3,
|
||||
|
@ -39,6 +41,14 @@ var m2id = [...]uint8{
|
|||
0, 1, 0, 2, 0, 1, 0, 0,
|
||||
}
|
||||
|
||||
type pool struct {
|
||||
sync.Mutex
|
||||
need int
|
||||
nchan chan uint32
|
||||
maxid uint32
|
||||
imap []byte
|
||||
}
|
||||
|
||||
func newPool(maxid uint32) *pool {
|
||||
p := new(pool)
|
||||
p.maxid = maxid
|
|
@ -2,11 +2,10 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
)
|
||||
|
||||
// Reads count bytes starting from offset from the file associated with the fid.
|
||||
|
@ -18,7 +17,7 @@ func (clnt *Clnt) Read(fid *Fid, offset uint64, count uint32) ([]byte, error) {
|
|||
}
|
||||
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTread(tc, fid.Fid, offset, count)
|
||||
err := PackTread(tc, fid.Fid, offset, count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -45,7 +44,7 @@ func (file *File) Read(buf []byte) (int, error) {
|
|||
// Reads up to len(buf) bytes from the file starting from offset.
|
||||
// Returns the number of bytes read, or an Error.
|
||||
func (file *File) ReadAt(buf []byte, offset int64) (int, error) {
|
||||
b, err := file.fid.Clnt.Read(file.fid, uint64(offset), uint32(len(buf)))
|
||||
b, err := file.Fid.Clnt.Read(file.Fid, uint64(offset), uint32(len(buf)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -85,10 +84,14 @@ func (file *File) Readn(buf []byte, offset uint64) (int, error) {
|
|||
// Returns an array of maximum num entries (if num is 0, returns
|
||||
// all entries from the directory). If the operation fails, returns
|
||||
// an Error.
|
||||
func (file *File) Readdir(num int) ([]*p.Dir, error) {
|
||||
buf := make([]byte, file.fid.Clnt.Msize-p.IOHDRSZ)
|
||||
dirs := make([]*p.Dir, 32)
|
||||
func (file *File) Readdir(num int) ([]*Dir, error) {
|
||||
buf := make([]byte, file.Fid.Clnt.Msize-IOHDRSZ)
|
||||
dirs := make([]*Dir, 32)
|
||||
pos := 0
|
||||
offset := file.offset
|
||||
defer func() {
|
||||
file.offset = offset
|
||||
}()
|
||||
for {
|
||||
n, err := file.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
|
@ -100,14 +103,20 @@ func (file *File) Readdir(num int) ([]*p.Dir, error) {
|
|||
}
|
||||
|
||||
for b := buf[0:n]; len(b) > 0; {
|
||||
d, perr := p.UnpackDir(b, file.fid.Clnt.Dotu)
|
||||
d, _, _, perr := UnpackDir(b, file.Fid.Clnt.Dotu)
|
||||
if perr != nil {
|
||||
// If we have unpacked anything, it is almost certainly
|
||||
// a too-short buffer. So return what we got.
|
||||
if pos > 0 {
|
||||
return dirs[0:pos], nil
|
||||
}
|
||||
return nil, perr
|
||||
}
|
||||
|
||||
b = b[d.Size+2:]
|
||||
offset += uint64(d.Size + 2)
|
||||
if pos >= len(dirs) {
|
||||
s := make([]*p.Dir, len(dirs)+32)
|
||||
s := make([]*Dir, len(dirs)+32)
|
||||
copy(s, dirs)
|
||||
dirs = s
|
||||
}
|
|
@ -2,22 +2,20 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
package go9p
|
||||
|
||||
// Removes the file associated with the Fid. Returns nil if the
|
||||
// operation is successful.
|
||||
func (clnt *Clnt) Remove(fid *Fid) error {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTremove(tc, fid.Fid)
|
||||
err := PackTremove(tc, fid.Fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = clnt.Rpc(tc)
|
||||
clnt.fidpool.putId(fid.Fid)
|
||||
fid.Fid = p.NOFID
|
||||
fid.Fid = NOFID
|
||||
|
||||
return err
|
||||
}
|
|
@ -2,14 +2,12 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
package go9p
|
||||
|
||||
// Returns the metadata for the file associated with the Fid, or an Error.
|
||||
func (clnt *Clnt) Stat(fid *Fid) (*p.Dir, error) {
|
||||
func (clnt *Clnt) Stat(fid *Fid) (*Dir, error) {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTstat(tc, fid.Fid)
|
||||
err := PackTstat(tc, fid.Fid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -23,7 +21,7 @@ func (clnt *Clnt) Stat(fid *Fid) (*p.Dir, error) {
|
|||
}
|
||||
|
||||
// Returns the metadata for a named file, or an Error.
|
||||
func (clnt *Clnt) FStat(path string) (*p.Dir, error) {
|
||||
func (clnt *Clnt) FStat(path string) (*Dir, error) {
|
||||
fid, err := clnt.FWalk(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -35,9 +33,9 @@ func (clnt *Clnt) FStat(path string) (*p.Dir, error) {
|
|||
}
|
||||
|
||||
// Modifies the data of the file associated with the Fid, or an Error.
|
||||
func (clnt *Clnt) Wstat(fid *Fid, dir *p.Dir) error {
|
||||
func (clnt *Clnt) Wstat(fid *Fid, dir *Dir) error {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTwstat(tc, fid.Fid, dir, clnt.Dotu)
|
||||
err := PackTwstat(tc, fid.Fid, dir, clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
// +build httpstats
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -18,7 +17,7 @@ func (clnt *Clnt) ServeHTTP(c http.ResponseWriter, r *http.Request) {
|
|||
fs := clnt.Log.Filter(clnt, DbgLogFcalls)
|
||||
io.WriteString(c, fmt.Sprintf("<h2>Last %d 9P messages</h2>", len(fs)))
|
||||
for _, l := range fs {
|
||||
fc := l.Data.(*p.Fcall)
|
||||
fc := l.Data.(*Fcall)
|
||||
if fc.Type != 0 {
|
||||
io.WriteString(c, fmt.Sprintf("<br>%s", fc))
|
||||
}
|
|
@ -2,9 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
package go9p
|
||||
|
||||
type Tag struct {
|
||||
clnt *Clnt
|
||||
|
@ -54,22 +52,22 @@ func (tag *Tag) reqproc() {
|
|||
case r := <-tag.respchan:
|
||||
rc := r.Rc
|
||||
fid := r.fid
|
||||
err := r.Rc.Type == p.Rerror
|
||||
err := r.Rc.Type == Rerror
|
||||
|
||||
switch r.Tc.Type {
|
||||
case p.Tauth:
|
||||
case Tauth:
|
||||
if err {
|
||||
fid.User = nil
|
||||
}
|
||||
|
||||
case p.Tattach:
|
||||
case Tattach:
|
||||
if !err {
|
||||
fid.Qid = rc.Qid
|
||||
} else {
|
||||
fid.User = nil
|
||||
}
|
||||
|
||||
case p.Twalk:
|
||||
case Twalk:
|
||||
if !err {
|
||||
fid.walked = true
|
||||
if len(rc.Wqid) > 0 {
|
||||
|
@ -79,8 +77,8 @@ func (tag *Tag) reqproc() {
|
|||
fid.User = nil
|
||||
}
|
||||
|
||||
case p.Topen:
|
||||
case p.Tcreate:
|
||||
case Topen:
|
||||
case Tcreate:
|
||||
if !err {
|
||||
fid.Iounit = rc.Iounit
|
||||
fid.Qid = rc.Qid
|
||||
|
@ -88,8 +86,8 @@ func (tag *Tag) reqproc() {
|
|||
fid.Mode = 0
|
||||
}
|
||||
|
||||
case p.Tclunk:
|
||||
case p.Tremove:
|
||||
case Tclunk:
|
||||
case Tremove:
|
||||
tag.clnt.fidpool.putId(fid.Fid)
|
||||
}
|
||||
|
||||
|
@ -98,10 +96,10 @@ func (tag *Tag) reqproc() {
|
|||
}
|
||||
}
|
||||
|
||||
func (tag *Tag) Auth(afid *Fid, user p.User, aname string) error {
|
||||
func (tag *Tag) Auth(afid *Fid, user User, aname string) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = afid
|
||||
err := p.PackTauth(req.Tc, afid.Fid, user.Name(), aname, uint32(user.Id()), tag.clnt.Dotu)
|
||||
err := PackTauth(req.Tc, afid.Fid, user.Name(), aname, uint32(user.Id()), tag.clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -110,18 +108,18 @@ func (tag *Tag) Auth(afid *Fid, user p.User, aname string) error {
|
|||
return tag.clnt.Rpcnb(req)
|
||||
}
|
||||
|
||||
func (tag *Tag) Attach(fid, afid *Fid, user p.User, aname string) error {
|
||||
func (tag *Tag) Attach(fid, afid *Fid, user User, aname string) error {
|
||||
var afno uint32
|
||||
|
||||
if afid != nil {
|
||||
afno = afid.Fid
|
||||
} else {
|
||||
afno = p.NOFID
|
||||
afno = NOFID
|
||||
}
|
||||
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTattach(req.Tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), tag.clnt.Dotu)
|
||||
err := PackTattach(req.Tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), tag.clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -137,7 +135,7 @@ func (tag *Tag) Walk(fid *Fid, newfid *Fid, wnames []string) error {
|
|||
newfid.Qid = fid.Qid
|
||||
}
|
||||
|
||||
err := p.PackTwalk(req.Tc, fid.Fid, newfid.Fid, wnames)
|
||||
err := PackTwalk(req.Tc, fid.Fid, newfid.Fid, wnames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -149,7 +147,7 @@ func (tag *Tag) Walk(fid *Fid, newfid *Fid, wnames []string) error {
|
|||
func (tag *Tag) Open(fid *Fid, mode uint8) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTopen(req.Tc, fid.Fid, mode)
|
||||
err := PackTopen(req.Tc, fid.Fid, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -161,7 +159,7 @@ func (tag *Tag) Open(fid *Fid, mode uint8) error {
|
|||
func (tag *Tag) Create(fid *Fid, name string, perm uint32, mode uint8, ext string) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTcreate(req.Tc, fid.Fid, name, perm, mode, ext, tag.clnt.Dotu)
|
||||
err := PackTcreate(req.Tc, fid.Fid, name, perm, mode, ext, tag.clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -173,7 +171,7 @@ func (tag *Tag) Create(fid *Fid, name string, perm uint32, mode uint8, ext strin
|
|||
func (tag *Tag) Read(fid *Fid, offset uint64, count uint32) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTread(req.Tc, fid.Fid, offset, count)
|
||||
err := PackTread(req.Tc, fid.Fid, offset, count)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -184,7 +182,7 @@ func (tag *Tag) Read(fid *Fid, offset uint64, count uint32) error {
|
|||
func (tag *Tag) Write(fid *Fid, data []byte, offset uint64) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTwrite(req.Tc, fid.Fid, offset, uint32(len(data)), data)
|
||||
err := PackTwrite(req.Tc, fid.Fid, offset, uint32(len(data)), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -195,7 +193,7 @@ func (tag *Tag) Write(fid *Fid, data []byte, offset uint64) error {
|
|||
func (tag *Tag) Clunk(fid *Fid) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTclunk(req.Tc, fid.Fid)
|
||||
err := PackTclunk(req.Tc, fid.Fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -206,7 +204,7 @@ func (tag *Tag) Clunk(fid *Fid) error {
|
|||
func (tag *Tag) Remove(fid *Fid) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTremove(req.Tc, fid.Fid)
|
||||
err := PackTremove(req.Tc, fid.Fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -217,7 +215,7 @@ func (tag *Tag) Remove(fid *Fid) error {
|
|||
func (tag *Tag) Stat(fid *Fid) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTstat(req.Tc, fid.Fid)
|
||||
err := PackTstat(req.Tc, fid.Fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -225,10 +223,10 @@ func (tag *Tag) Stat(fid *Fid) error {
|
|||
return tag.clnt.Rpcnb(req)
|
||||
}
|
||||
|
||||
func (tag *Tag) Wstat(fid *Fid, dir *p.Dir) error {
|
||||
func (tag *Tag) Wstat(fid *Fid, dir *Dir) error {
|
||||
req := tag.reqAlloc()
|
||||
req.fid = fid
|
||||
err := p.PackTwstat(req.Tc, fid.Fid, dir, tag.clnt.Dotu)
|
||||
err := PackTwstat(req.Tc, fid.Fid, dir, tag.clnt.Dotu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -2,10 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -13,9 +12,9 @@ import (
|
|||
// sequence and associates the resulting file with newfid. If no wnames
|
||||
// were walked successfully, an Error is returned. Otherwise a slice with a
|
||||
// Qid for each walked name is returned.
|
||||
func (clnt *Clnt) Walk(fid *Fid, newfid *Fid, wnames []string) ([]p.Qid, error) {
|
||||
func (clnt *Clnt) Walk(fid *Fid, newfid *Fid, wnames []string) ([]Qid, error) {
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTwalk(tc, fid.Fid, newfid.Fid, wnames)
|
||||
err := PackTwalk(tc, fid.Fid, newfid.Fid, wnames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -66,12 +65,12 @@ func (clnt *Clnt) FWalk(path string) (*Fid, error) {
|
|||
}
|
||||
|
||||
tc := clnt.NewFcall()
|
||||
err = p.PackTwalk(tc, fid.Fid, newfid.Fid, wnames[0:n])
|
||||
err = PackTwalk(tc, fid.Fid, newfid.Fid, wnames[0:n])
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
var rc *p.Fcall
|
||||
var rc *Fcall
|
||||
rc, err = clnt.Rpc(tc)
|
||||
if err != nil {
|
||||
goto error
|
||||
|
@ -79,7 +78,7 @@ func (clnt *Clnt) FWalk(path string) (*Fid, error) {
|
|||
|
||||
newfid.walked = true
|
||||
if len(rc.Wqid) != n {
|
||||
err = &p.Error{"file not found", p.ENOENT}
|
||||
err = &Error{"file not found", ENOENT}
|
||||
goto error
|
||||
}
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
package go9p
|
||||
|
||||
// Write up to len(data) bytes starting from offset. Returns the
|
||||
// number of bytes written, or an Error.
|
||||
|
@ -14,7 +12,7 @@ func (clnt *Clnt) Write(fid *Fid, data []byte, offset uint64) (int, error) {
|
|||
}
|
||||
|
||||
tc := clnt.NewFcall()
|
||||
err := p.PackTwrite(tc, fid.Fid, offset, uint32(len(data)), data)
|
||||
err := PackTwrite(tc, fid.Fid, offset, uint32(len(data)), data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -41,7 +39,7 @@ func (file *File) Write(buf []byte) (int, error) {
|
|||
// Writes up to len(buf) bytes starting from offset. Returns the number
|
||||
// of bytes written, or an Error.
|
||||
func (file *File) WriteAt(buf []byte, offset int64) (int, error) {
|
||||
return file.fid.Clnt.Write(file.fid, buf, uint64(offset))
|
||||
return file.Fid.Clnt.Write(file.Fid, buf, uint64(offset))
|
||||
}
|
||||
|
||||
// Writes exactly len(buf) bytes starting from offset. Returns the number of
|
|
@ -0,0 +1,9 @@
|
|||
package go9p
|
||||
|
||||
// Debug flags
|
||||
const (
|
||||
DbgPrintFcalls = (1 << iota) // print all 9P messages on stderr
|
||||
DbgPrintPackets // print the raw packets on stderr
|
||||
DbgLogFcalls // keep the last N 9P messages (can be accessed over http)
|
||||
DbgLogPackets // keep the last N 9P messages (can be accessed over http)
|
||||
)
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
package go9p
|
||||
|
||||
import "fmt"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package p
|
||||
package go9p
|
||||
|
||||
type Log struct {
|
||||
Data interface{}
|
|
@ -2,38 +2,33 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"os/user"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
import "sync"
|
||||
|
||||
var once sync.Once
|
||||
|
||||
type osUser struct {
|
||||
*user.User
|
||||
uid int
|
||||
gid int
|
||||
}
|
||||
|
||||
type osUsers struct {
|
||||
users map[int]*osUser
|
||||
groups map[int]*osGroup
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Simple Users implementation that defers to os/user and fakes
|
||||
// looking up groups by gid only.
|
||||
// Simple Users implementation that fakes looking up users and groups
|
||||
// by uid only. The names and groups memberships are empty
|
||||
var OsUsers *osUsers
|
||||
|
||||
func (u *osUser) Name() string { return u.Username }
|
||||
func (u *osUser) Name() string { return "" }
|
||||
|
||||
func (u *osUser) Id() int { return u.uid }
|
||||
|
||||
func (u *osUser) Groups() []Group { return []Group{OsUsers.Gid2Group(u.gid)} }
|
||||
func (u *osUser) Groups() []Group { return nil }
|
||||
|
||||
func (u *osUser) IsMember(g Group) bool { return u.gid == g.Id() }
|
||||
func (u *osUser) IsMember(g Group) bool { return false }
|
||||
|
||||
type osGroup struct {
|
||||
gid int
|
||||
|
@ -47,33 +42,28 @@ func (g *osGroup) Members() []User { return nil }
|
|||
|
||||
func initOsusers() {
|
||||
OsUsers = new(osUsers)
|
||||
OsUsers.users = make(map[int]*osUser)
|
||||
OsUsers.groups = make(map[int]*osGroup)
|
||||
}
|
||||
|
||||
func newUser(u *user.User) *osUser {
|
||||
uid, uerr := strconv.Atoi(u.Uid)
|
||||
gid, gerr := strconv.Atoi(u.Gid)
|
||||
if uerr != nil || gerr != nil {
|
||||
/* non-numeric uid/gid => unsupported system */
|
||||
return nil
|
||||
}
|
||||
return &osUser{u, uid, gid}
|
||||
}
|
||||
|
||||
func (up *osUsers) Uid2User(uid int) User {
|
||||
u, err := user.LookupId(strconv.Itoa(uid))
|
||||
if err != nil {
|
||||
return nil
|
||||
once.Do(initOsusers)
|
||||
OsUsers.Lock()
|
||||
defer OsUsers.Unlock()
|
||||
user, present := OsUsers.users[uid]
|
||||
if present {
|
||||
return user
|
||||
}
|
||||
return newUser(u)
|
||||
|
||||
user = new(osUser)
|
||||
user.uid = uid
|
||||
OsUsers.users[uid] = user
|
||||
return user
|
||||
}
|
||||
|
||||
func (up *osUsers) Uname2User(uname string) User {
|
||||
u, err := user.Lookup(uname)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return newUser(u)
|
||||
// unimplemented
|
||||
return nil
|
||||
}
|
||||
|
||||
func (up *osUsers) Gid2Group(gid int) Group {
|
|
@ -1,489 +0,0 @@
|
|||
package main
|
||||
|
||||
// An interactive client for 9P servers.
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
var ouser = flag.String("user", "", "user to connect as")
|
||||
var cmdfile = flag.String("file", "", "read commands from file")
|
||||
var prompt = flag.String("prompt", "9p> ", "prompt for interactive client")
|
||||
var debug = flag.Bool("d", false, "enable debugging (fcalls)")
|
||||
var debugall = flag.Bool("D", false, "enable debugging (raw packets)")
|
||||
|
||||
var cwd = "/"
|
||||
var cfid *clnt.Fid
|
||||
|
||||
type Cmd struct {
|
||||
fun func(c *clnt.Clnt, s []string)
|
||||
help string
|
||||
}
|
||||
|
||||
var cmds map[string]*Cmd
|
||||
|
||||
func init() {
|
||||
cmds = make(map[string]*Cmd)
|
||||
cmds["write"] = &Cmd{cmdwrite, "write file string [...]\t«write the unmodified string to file, create file if necessary»"}
|
||||
cmds["echo"] = &Cmd{cmdecho, "echo file string [...]\t«echo string to file (newline appended)»"}
|
||||
cmds["stat"] = &Cmd{cmdstat, "stat file [...]\t«stat file»"}
|
||||
cmds["ls"] = &Cmd{cmdls, "ls [-l] file [...]\t«list contents of directory or file»"}
|
||||
cmds["cd"] = &Cmd{cmdcd, "cd dir\t«change working directory»"}
|
||||
cmds["cat"] = &Cmd{cmdcat, "cat file [...]\t«print the contents of file»"}
|
||||
cmds["mkdir"] = &Cmd{cmdmkdir, "mkdir dir [...]\t«create dir on remote server»"}
|
||||
cmds["get"] = &Cmd{cmdget, "get file [local]\t«get file from remote server»"}
|
||||
cmds["put"] = &Cmd{cmdput, "put file [remote]\t«put file on the remote server as 'file'»"}
|
||||
cmds["pwd"] = &Cmd{cmdpwd, "pwd\t«print working directory»"}
|
||||
cmds["rm"] = &Cmd{cmdrm, "rm file [...]\t«remove file from remote server»"}
|
||||
cmds["help"] = &Cmd{cmdhelp, "help [cmd]\t«print available commands or help on cmd»"}
|
||||
cmds["quit"] = &Cmd{cmdquit, "quit\t«exit»"}
|
||||
cmds["exit"] = &Cmd{cmdquit, "exit\t«quit»"}
|
||||
}
|
||||
|
||||
// normalize user-supplied path. path starting with '/' is left untouched, otherwise is considered
|
||||
// local from cwd
|
||||
func normpath(s string) string {
|
||||
if len(s) > 0 {
|
||||
if s[0] == '/' {
|
||||
return path.Clean(s)
|
||||
}
|
||||
return path.Clean(cwd + "/" + s)
|
||||
}
|
||||
return "/"
|
||||
}
|
||||
|
||||
func b(mode uint32, s uint8) string {
|
||||
var bits = []string{"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}
|
||||
return bits[(mode>>s)&7]
|
||||
}
|
||||
|
||||
// Convert file mode bits to string representation
|
||||
func modetostr(mode uint32) string {
|
||||
d := "-"
|
||||
if mode&p.DMDIR != 0 {
|
||||
d = "d"
|
||||
} else if mode&p.DMAPPEND != 0 {
|
||||
d = "a"
|
||||
}
|
||||
return fmt.Sprintf("%s%s%s%s", d, b(mode, 6), b(mode, 3), b(mode, 0))
|
||||
}
|
||||
|
||||
// Write the string s to remote file f. Create f if it doesn't exist
|
||||
func writeone(c *clnt.Clnt, f, s string) {
|
||||
fname := normpath(f)
|
||||
file, oserr := c.FCreate(fname, 0666, p.OWRITE)
|
||||
if oserr != nil {
|
||||
file, oserr = c.FOpen(fname, p.OWRITE|p.OTRUNC)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s: %v\n", fname, oserr)
|
||||
return
|
||||
}
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
m, oserr := file.Write([]byte(s))
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error writing to %s: %v\n", fname, oserr)
|
||||
return
|
||||
}
|
||||
|
||||
if m != len(s) {
|
||||
fmt.Fprintf(os.Stderr, "short write %s\n", fname)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Write s[1:] (with appended spaces) to the file s[0]
|
||||
func cmdwrite(c *clnt.Clnt, s []string) {
|
||||
fname := normpath(s[0])
|
||||
str := strings.Join(s[1:], " ")
|
||||
writeone(c, fname, str)
|
||||
}
|
||||
|
||||
// Echo (append newline) s[1:] to s[0]
|
||||
func cmdecho(c *clnt.Clnt, s []string) {
|
||||
fname := normpath(s[0])
|
||||
str := strings.Join(s[1:], " ") + "\n"
|
||||
writeone(c, fname, str)
|
||||
}
|
||||
|
||||
// Stat the remote file f
|
||||
func statone(c *clnt.Clnt, f string) {
|
||||
fname := normpath(f)
|
||||
|
||||
stat, oserr := c.FStat(fname)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error in stat %s: %v\n", fname, oserr)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s\n", stat)
|
||||
}
|
||||
|
||||
func cmdstat(c *clnt.Clnt, s []string) {
|
||||
for _, f := range s {
|
||||
statone(c, normpath(f))
|
||||
}
|
||||
}
|
||||
|
||||
func dirtostr(d *p.Dir) string {
|
||||
return fmt.Sprintf("%s %s %s %-8d\t\t%s", modetostr(d.Mode), d.Uid, d.Gid, d.Length, d.Name)
|
||||
}
|
||||
|
||||
func lsone(c *clnt.Clnt, s string, long bool) {
|
||||
st, oserr := c.FStat(normpath(s))
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error stat: %v\n", oserr)
|
||||
return
|
||||
}
|
||||
if st.Mode&p.DMDIR != 0 {
|
||||
file, oserr := c.FOpen(s, p.OREAD)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening dir: %s\n", oserr)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
for {
|
||||
d, oserr := file.Readdir(0)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error reading dir: %v\n", oserr)
|
||||
}
|
||||
if d == nil || len(d) == 0 {
|
||||
break
|
||||
}
|
||||
for _, dir := range d {
|
||||
if long {
|
||||
fmt.Fprintf(os.Stdout, "%s\n", dirtostr(dir))
|
||||
} else {
|
||||
os.Stdout.WriteString(dir.Name + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stdout, "%s\n", dirtostr(st))
|
||||
}
|
||||
}
|
||||
|
||||
func cmdls(c *clnt.Clnt, s []string) {
|
||||
long := false
|
||||
if len(s) > 0 && s[0] == "-l" {
|
||||
long = true
|
||||
s = s[1:]
|
||||
}
|
||||
if len(s) == 0 {
|
||||
lsone(c, cwd, long)
|
||||
} else {
|
||||
for _, d := range s {
|
||||
lsone(c, cwd+d, long)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func walkone(c *clnt.Clnt, s string, fileok bool) {
|
||||
ncwd := normpath(s)
|
||||
|
||||
fid, err := c.FWalk(ncwd)
|
||||
defer c.Clunk(fid)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "walk error: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if fileok != true && (fid.Type&p.QTDIR == 0) {
|
||||
fmt.Fprintf(os.Stderr, "can't cd to file [%s]\n", ncwd)
|
||||
return
|
||||
}
|
||||
|
||||
cwd = ncwd
|
||||
}
|
||||
|
||||
func cmdcd(c *clnt.Clnt, s []string) {
|
||||
if s != nil {
|
||||
walkone(c, strings.Join(s, "/"), false)
|
||||
}
|
||||
}
|
||||
|
||||
// Print the contents of f
|
||||
func cmdcat(c *clnt.Clnt, s []string) {
|
||||
buf := make([]byte, 8192)
|
||||
Outer:
|
||||
for _, f := range s {
|
||||
fname := normpath(f)
|
||||
file, oserr := c.FOpen(fname, p.OREAD)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s: %v\n", f, oserr)
|
||||
continue Outer
|
||||
}
|
||||
defer file.Close()
|
||||
for {
|
||||
n, oserr := file.Read(buf)
|
||||
if oserr != nil && oserr != io.EOF {
|
||||
fmt.Fprintf(os.Stderr, "error reading %s: %v\n", f, oserr)
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
os.Stdout.Write(buf[0:n])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a single directory on remote server
|
||||
func mkone(c *clnt.Clnt, s string) {
|
||||
fname := normpath(s)
|
||||
file, oserr := c.FCreate(fname, 0777|p.DMDIR, p.OWRITE)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error creating directory %s: %v\n", fname, oserr)
|
||||
return
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
|
||||
// Create directories on remote server
|
||||
func cmdmkdir(c *clnt.Clnt, s []string) {
|
||||
for _, f := range s {
|
||||
mkone(c, f)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy a remote file to local filesystem
|
||||
func cmdget(c *clnt.Clnt, s []string) {
|
||||
var from, to string
|
||||
switch len(s) {
|
||||
case 1:
|
||||
from = normpath(s[0])
|
||||
_, to = path.Split(s[0])
|
||||
case 2:
|
||||
from, to = normpath(s[0]), s[1]
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "from arguments; usage: get from to\n")
|
||||
}
|
||||
|
||||
tofile, err := os.Create(to)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s for writing: %s\n", to, err)
|
||||
return
|
||||
}
|
||||
defer tofile.Close()
|
||||
|
||||
file, ferr := c.FOpen(from, p.OREAD)
|
||||
if ferr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s for writing: %s\n", to, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := make([]byte, 8192)
|
||||
for {
|
||||
n, oserr := file.Read(buf)
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error reading %s: %s\n", from, oserr)
|
||||
return
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
m, err := tofile.Write(buf[0:n])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error writing %s: %s\n", to, err)
|
||||
return
|
||||
}
|
||||
|
||||
if m != n {
|
||||
fmt.Fprintf(os.Stderr, "short write %s\n", to)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy a local file to remote server
|
||||
func cmdput(c *clnt.Clnt, s []string) {
|
||||
var from, to string
|
||||
switch len(s) {
|
||||
case 1:
|
||||
_, to = path.Split(s[0])
|
||||
to = normpath(to)
|
||||
from = s[0]
|
||||
case 2:
|
||||
from, to = s[0], normpath(s[1])
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "incorrect arguments; usage: put local [remote]\n")
|
||||
}
|
||||
|
||||
fromfile, err := os.Open(from)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s for reading: %s\n", from, err)
|
||||
return
|
||||
}
|
||||
defer fromfile.Close()
|
||||
|
||||
file, ferr := c.FOpen(to, p.OWRITE|p.OTRUNC)
|
||||
if ferr != nil {
|
||||
file, ferr = c.FCreate(to, 0666, p.OWRITE)
|
||||
if ferr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %s for writing: %s\n", to, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := make([]byte, 8192)
|
||||
for {
|
||||
n, oserr := fromfile.Read(buf)
|
||||
if oserr != nil && oserr != io.EOF {
|
||||
fmt.Fprintf(os.Stderr, "error reading %s: %s\n", from, oserr)
|
||||
return
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
m, oserr := file.Write(buf[0:n])
|
||||
if oserr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error writing %s: %v\n", to, oserr)
|
||||
return
|
||||
}
|
||||
|
||||
if m != n {
|
||||
fmt.Fprintf(os.Stderr, "short write %s\n", to)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cmdpwd(c *clnt.Clnt, s []string) { fmt.Fprintf(os.Stdout, cwd+"\n") }
|
||||
|
||||
// Remove f from remote server
|
||||
func rmone(c *clnt.Clnt, f string) {
|
||||
fname := normpath(f)
|
||||
|
||||
err := c.FRemove(fname)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error in stat %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Remove one or more files from the server
|
||||
func cmdrm(c *clnt.Clnt, s []string) {
|
||||
for _, f := range s {
|
||||
rmone(c, normpath(f))
|
||||
}
|
||||
}
|
||||
|
||||
// Print available commands
|
||||
func cmdhelp(c *clnt.Clnt, s []string) {
|
||||
cmdstr := ""
|
||||
if len(s) > 0 {
|
||||
for _, h := range s {
|
||||
v, ok := cmds[h]
|
||||
if ok {
|
||||
cmdstr = cmdstr + v.help + "\n"
|
||||
} else {
|
||||
cmdstr = cmdstr + "unknown command: " + h + "\n"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cmdstr = "available commands: "
|
||||
for k := range cmds {
|
||||
cmdstr = cmdstr + " " + k
|
||||
}
|
||||
cmdstr = cmdstr + "\n"
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s", cmdstr)
|
||||
}
|
||||
|
||||
func cmdquit(c *clnt.Clnt, s []string) { os.Exit(0) }
|
||||
|
||||
func cmd(c *clnt.Clnt, cmd string) {
|
||||
ncmd := strings.Fields(cmd)
|
||||
if len(ncmd) <= 0 {
|
||||
return
|
||||
}
|
||||
v, ok := cmds[ncmd[0]]
|
||||
if ok == false {
|
||||
fmt.Fprintf(os.Stderr, "unknown command: %s\n", ncmd[0])
|
||||
return
|
||||
}
|
||||
v.fun(c, ncmd[1:])
|
||||
return
|
||||
}
|
||||
|
||||
func interactive(c *clnt.Clnt) {
|
||||
reader := bufio.NewReaderSize(os.Stdin, 8192)
|
||||
for {
|
||||
fmt.Print(*prompt)
|
||||
line, err := reader.ReadSlice('\n')
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "exiting...\n")
|
||||
break
|
||||
}
|
||||
str := strings.TrimSpace(string(line))
|
||||
// TODO: handle larger input lines by doubling buffer
|
||||
in := strings.Split(str, "\n")
|
||||
for i := range in {
|
||||
if len(in[i]) > 0 {
|
||||
cmd(c, in[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var user p.User
|
||||
var err error
|
||||
var c *clnt.Clnt
|
||||
var file *clnt.File
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *ouser == "" {
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
} else {
|
||||
user = p.OsUsers.Uname2User(*ouser)
|
||||
}
|
||||
|
||||
naddr := *addr
|
||||
if strings.LastIndex(naddr, ":") == -1 {
|
||||
naddr = naddr + ":5640"
|
||||
}
|
||||
c, err = clnt.Mount("tcp", naddr, "", user)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error mounting %s: %s\n", naddr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *debug {
|
||||
c.Debuglevel = 1
|
||||
}
|
||||
if *debugall {
|
||||
c.Debuglevel = 2
|
||||
}
|
||||
|
||||
walkone(c, "/", false)
|
||||
|
||||
if file != nil {
|
||||
//process(c)
|
||||
fmt.Sprint(os.Stderr, "file reading unimplemented\n")
|
||||
} else if flag.NArg() > 0 {
|
||||
flags := flag.Args()
|
||||
for _, uc := range flags {
|
||||
cmd(c, uc)
|
||||
}
|
||||
} else {
|
||||
interactive(c)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var debuglevel = flag.Int("d", 0, "debuglevel")
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
|
||||
func main() {
|
||||
var user p.User
|
||||
var err error
|
||||
var c *clnt.Clnt
|
||||
var file *clnt.File
|
||||
var d []*p.Dir
|
||||
|
||||
flag.Parse()
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
clnt.DefaultDebuglevel = *debuglevel
|
||||
c, err = clnt.Mount("tcp", *addr, "", user)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
lsarg := "/"
|
||||
if flag.NArg() == 1 {
|
||||
lsarg = flag.Arg(0)
|
||||
} else if flag.NArg() > 1 {
|
||||
log.Fatal("error: only one argument expected")
|
||||
}
|
||||
|
||||
file, err = c.FOpen(lsarg, p.OREAD)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
d, err = file.Readdir(0)
|
||||
if d == nil || len(d) == 0 || err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
for i := 0; i < len(d); i++ {
|
||||
os.Stdout.WriteString(d[i].Name + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
file.Close()
|
||||
if err != nil && err != io.EOF {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var debuglevel = flag.Int("d", 0, "debuglevel")
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
|
||||
func main() {
|
||||
var n int
|
||||
var user p.User
|
||||
var err error
|
||||
var c *clnt.Clnt
|
||||
var file *clnt.File
|
||||
var buf []byte
|
||||
|
||||
flag.Parse()
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
clnt.DefaultDebuglevel = *debuglevel
|
||||
c, err = clnt.Mount("tcp", *addr, "", user)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if flag.NArg() != 1 {
|
||||
log.Println("invalid arguments")
|
||||
return
|
||||
}
|
||||
|
||||
file, err = c.FOpen(flag.Arg(0), p.OREAD)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
buf = make([]byte, 8192)
|
||||
for {
|
||||
n, err = file.Read(buf)
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
os.Stdout.Write(buf[0:n])
|
||||
}
|
||||
|
||||
file.Close()
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
goto error
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println("Error", err)
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var debuglevel = flag.Int("d", 0, "debuglevel")
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
|
||||
func main() {
|
||||
var user p.User
|
||||
var ba [][]byte
|
||||
var nreqs int
|
||||
var rchan chan *clnt.Req
|
||||
var tag *clnt.Tag
|
||||
var fid *clnt.Fid
|
||||
var wnames []string
|
||||
|
||||
flag.Parse()
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
clnt.DefaultDebuglevel = *debuglevel
|
||||
c, err := clnt.Mount("tcp", *addr, "", user)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if flag.NArg() != 1 {
|
||||
log.Println("invalid arguments")
|
||||
return
|
||||
}
|
||||
|
||||
ba = make([][]byte, 100)
|
||||
for i := 0; i < len(ba); i++ {
|
||||
ba[i] = make([]byte, 8192)
|
||||
}
|
||||
|
||||
nreqs = 0
|
||||
rchan = make(chan *clnt.Req)
|
||||
tag = c.TagAlloc(rchan)
|
||||
|
||||
// walk the file
|
||||
wnames = strings.Split(flag.Arg(0), "/")
|
||||
for wnames[0] == "" {
|
||||
wnames = wnames[1:]
|
||||
}
|
||||
|
||||
fid = c.FidAlloc()
|
||||
for root := c.Root; len(wnames) > 0; root = fid {
|
||||
n := len(wnames)
|
||||
if n > 8 {
|
||||
n = 8
|
||||
}
|
||||
|
||||
err = tag.Walk(root, fid, wnames[0:n])
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
nreqs++
|
||||
wnames = wnames[n:]
|
||||
}
|
||||
err = tag.Open(fid, p.OREAD)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
for i := 0; i < len(ba); i++ {
|
||||
err = tag.Read(fid, uint64(i*8192), 8192)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
nreqs++
|
||||
}
|
||||
|
||||
err = tag.Clunk(fid)
|
||||
|
||||
// now start reading...
|
||||
for nreqs > 0 {
|
||||
r := <-rchan
|
||||
if r.Tc.Type == p.Tread {
|
||||
i := r.Tc.Offset / 8192
|
||||
copy(ba[i], r.Rc.Data)
|
||||
ba[i] = ba[i][0:r.Rc.Count]
|
||||
}
|
||||
nreqs--
|
||||
}
|
||||
|
||||
for i := 0; i < len(ba); i++ {
|
||||
os.Stdout.Write(ba[i])
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println("error: ", err)
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
// Connects to a server over TLS and lists the specified directory
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var debuglevel = flag.Int("d", 0, "debuglevel")
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
|
||||
func main() {
|
||||
var user p.User
|
||||
var file *clnt.File
|
||||
|
||||
flag.Parse()
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
clnt.DefaultDebuglevel = *debuglevel
|
||||
|
||||
c, oerr := tls.Dial("tcp", *addr, &tls.Config{
|
||||
Rand: rand.Reader,
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
if oerr != nil {
|
||||
log.Println("can't dial", oerr)
|
||||
return
|
||||
}
|
||||
|
||||
clnt, err := clnt.MountConn(c, "", user)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if flag.NArg() != 1 {
|
||||
log.Println("invalid arguments")
|
||||
return
|
||||
}
|
||||
|
||||
file, oerr = clnt.FOpen(flag.Arg(0), p.OREAD)
|
||||
if oerr != nil {
|
||||
goto oerror
|
||||
}
|
||||
|
||||
for {
|
||||
d, oerr := file.Readdir(0)
|
||||
if oerr != nil {
|
||||
goto oerror
|
||||
}
|
||||
|
||||
if d == nil || len(d) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for i := 0; i < len(d); i++ {
|
||||
os.Stdout.WriteString(d[i].Name + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
file.Close()
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
return
|
||||
|
||||
oerror:
|
||||
log.Println("Error", oerr)
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/clnt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var debuglevel = flag.Int("d", 0, "debuglevel")
|
||||
var addr = flag.String("addr", "127.0.0.1:5640", "network address")
|
||||
|
||||
func main() {
|
||||
var n, m int
|
||||
var user p.User
|
||||
var err error
|
||||
var c *clnt.Clnt
|
||||
var file *clnt.File
|
||||
var buf []byte
|
||||
|
||||
flag.Parse()
|
||||
user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
clnt.DefaultDebuglevel = *debuglevel
|
||||
c, err = clnt.Mount("tcp", *addr, "", user)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if flag.NArg() != 1 {
|
||||
log.Println("invalid arguments")
|
||||
return
|
||||
}
|
||||
|
||||
file, err = c.FOpen(flag.Arg(0), p.OWRITE|p.OTRUNC)
|
||||
if err != nil {
|
||||
file, err = c.FCreate(flag.Arg(0), 0666, p.OWRITE)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
}
|
||||
|
||||
buf = make([]byte, 8192)
|
||||
for {
|
||||
n, err = os.Stdin.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
goto error
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
m, err = file.Write(buf[0:n])
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
if m != n {
|
||||
err = &p.Error{"short write", 0}
|
||||
goto error
|
||||
}
|
||||
}
|
||||
|
||||
file.Close()
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println("Error", err)
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2009 The Go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package clnt
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
)
|
||||
|
||||
var Eisdir = &p.Error{"file is a directory", p.EIO}
|
||||
var Enegoff = &p.Error{"negative i/o offset", p.EIO}
|
||||
|
||||
// Seek sets the offset for the next Read or Write to offset,
|
||||
// interpreted according to whence: 0 means relative to the origin of
|
||||
// the file, 1 means relative to the current offset, and 2 means
|
||||
// relative to the end. Seek returns the new offset and an error, if
|
||||
// any.
|
||||
//
|
||||
// Seeking to a negative offset is an error, and results in Enegoff.
|
||||
// Seeking to 0 in a directory is only valid if whence is 0. Seek returns
|
||||
// Eisdir otherwise.
|
||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
||||
var off int64
|
||||
|
||||
switch whence {
|
||||
case 0:
|
||||
// origin
|
||||
off = offset
|
||||
if f.fid.Qid.Type&p.QTDIR > 0 && off != 0 {
|
||||
return 0, Eisdir
|
||||
}
|
||||
|
||||
case 1:
|
||||
// current
|
||||
if f.fid.Qid.Type&p.QTDIR > 0 {
|
||||
return 0, Eisdir
|
||||
}
|
||||
off = offset + int64(f.offset)
|
||||
|
||||
case 2:
|
||||
// end
|
||||
if f.fid.Qid.Type&p.QTDIR > 0 {
|
||||
return 0, Eisdir
|
||||
}
|
||||
|
||||
dir, err := f.fid.Clnt.Stat(f.fid)
|
||||
if err != nil {
|
||||
return 0, &p.Error{"stat error in seek: " + err.Error(), p.EIO}
|
||||
}
|
||||
off = int64(dir.Length) + offset
|
||||
|
||||
default:
|
||||
return 0, &p.Error{"bad whence in seek", p.EIO}
|
||||
}
|
||||
|
||||
if off < 0 {
|
||||
return 0, Enegoff
|
||||
}
|
||||
f.offset = uint64(off)
|
||||
|
||||
return off, nil
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
// Copyright 2009 The Go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// A synthetic filesystem emulating a persistent cloning interface
|
||||
// from Plan 9. Reading the /clone file creates new entries in the filesystem
|
||||
// each containing unique information/data. Clone files remember what it written
|
||||
// to them. Removing a clone file does what is expected.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ClFile struct {
|
||||
srv.File
|
||||
created string
|
||||
id int
|
||||
data []byte
|
||||
}
|
||||
|
||||
type Clone struct {
|
||||
srv.File
|
||||
clones int
|
||||
}
|
||||
|
||||
var addr = flag.String("addr", ":5640", "network address")
|
||||
var debug = flag.Bool("d", false, "print debug messages")
|
||||
|
||||
var root *srv.File
|
||||
|
||||
func (cl *ClFile) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
var b []byte
|
||||
if len(cl.data) == 0 {
|
||||
str := strconv.Itoa(cl.id) + " created on:" + cl.created
|
||||
b = []byte(str)
|
||||
} else {
|
||||
b = cl.data
|
||||
}
|
||||
n := len(b)
|
||||
if offset >= uint64(n) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
b = b[int(offset):n]
|
||||
n -= int(offset)
|
||||
if len(buf) < n {
|
||||
n = len(buf)
|
||||
}
|
||||
|
||||
copy(buf[offset:int(offset)+n], b[offset:])
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (cl *ClFile) Write(fid *srv.FFid, data []byte, offset uint64) (int, error) {
|
||||
n := uint64(len(cl.data))
|
||||
nlen := offset + uint64(len(data))
|
||||
if nlen > n {
|
||||
ndata := make([]byte, nlen)
|
||||
copy(ndata, cl.data[0:n])
|
||||
cl.data = ndata
|
||||
}
|
||||
|
||||
copy(cl.data[offset:], data[offset:])
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (cl *ClFile) Wstat(fid *srv.FFid, dir *p.Dir) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cl *ClFile) Remove(fid *srv.FFid) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cl *Clone) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
// we only allow a single read from us, change the offset and we're done
|
||||
if offset > uint64(0) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
cl.clones += 1
|
||||
ncl := new(ClFile)
|
||||
ncl.id = cl.clones
|
||||
ncl.created = time.Now().String()
|
||||
name := strconv.Itoa(ncl.id)
|
||||
|
||||
err := ncl.Add(root, name, p.OsUsers.Uid2User(os.Geteuid()), nil, 0666, ncl)
|
||||
if err != nil {
|
||||
return 0, &p.Error{"can not create file", 0}
|
||||
}
|
||||
|
||||
b := []byte(name)
|
||||
if len(buf) < len(b) {
|
||||
// cleanup
|
||||
ncl.File.Remove()
|
||||
return 0, &p.Error{"not enough buffer space for result", 0}
|
||||
}
|
||||
|
||||
copy(buf, b)
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var cl *Clone
|
||||
var s *srv.Fsrv
|
||||
|
||||
flag.Parse()
|
||||
user := p.OsUsers.Uid2User(os.Geteuid())
|
||||
root = new(srv.File)
|
||||
err = root.Add(nil, "/", user, nil, p.DMDIR|0777, nil)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
cl = new(Clone)
|
||||
err = cl.Add(root, "clone", p.OsUsers.Uid2User(os.Geteuid()), nil, 0444, cl)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
s = srv.NewFileSrv(root)
|
||||
s.Dotu = true
|
||||
|
||||
if *debug {
|
||||
s.Debuglevel = 1
|
||||
}
|
||||
|
||||
s.Start(s)
|
||||
err = s.StartNetListener("tcp", *addr)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
}
|
|
@ -1,251 +0,0 @@
|
|||
// Copyright 2009 The Go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Ramfs struct {
|
||||
srv *srv.Fsrv
|
||||
user p.User
|
||||
group p.Group
|
||||
blksz int
|
||||
blkchan chan []byte
|
||||
zero []byte // blksz array of zeroes
|
||||
}
|
||||
|
||||
type RFile struct {
|
||||
srv.File
|
||||
data [][]byte
|
||||
}
|
||||
|
||||
var addr = flag.String("addr", ":5640", "network address")
|
||||
var debug = flag.Int("d", 0, "debuglevel")
|
||||
var blksize = flag.Int("b", 8192, "block size")
|
||||
var logsz = flag.Int("l", 2048, "log size")
|
||||
var rsrv Ramfs
|
||||
|
||||
func (f *RFile) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
if offset > f.Length {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
count := uint32(len(buf))
|
||||
if offset+uint64(count) > f.Length {
|
||||
count = uint32(f.Length - offset)
|
||||
}
|
||||
|
||||
for n, off, b := offset/uint64(rsrv.blksz), offset%uint64(rsrv.blksz), buf[0:count]; len(b) > 0; n++ {
|
||||
m := rsrv.blksz - int(off)
|
||||
if m > len(b) {
|
||||
m = len(b)
|
||||
}
|
||||
|
||||
blk := rsrv.zero
|
||||
if len(f.data[n]) != 0 {
|
||||
blk = f.data[n]
|
||||
}
|
||||
|
||||
// log.Stderr("read block", n, "off", off, "len", m, "l", len(blk), "ll", len(b))
|
||||
copy(b, blk[off:off+uint64(m)])
|
||||
b = b[m:]
|
||||
off = 0
|
||||
}
|
||||
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (f *RFile) Write(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
// make sure the data array is big enough
|
||||
sz := offset + uint64(len(buf))
|
||||
if f.Length < sz {
|
||||
f.expand(sz)
|
||||
}
|
||||
|
||||
count := 0
|
||||
for n, off := offset/uint64(rsrv.blksz), offset%uint64(rsrv.blksz); len(buf) > 0; n++ {
|
||||
blk := f.data[n]
|
||||
if len(blk) == 0 {
|
||||
select {
|
||||
case blk = <-rsrv.blkchan:
|
||||
break
|
||||
default:
|
||||
blk = make([]byte, rsrv.blksz)
|
||||
}
|
||||
|
||||
// if off>0 {
|
||||
copy(blk, rsrv.zero /*[0:off]*/)
|
||||
// }
|
||||
|
||||
f.data[n] = blk
|
||||
}
|
||||
|
||||
m := copy(blk[off:], buf)
|
||||
buf = buf[m:]
|
||||
count += m
|
||||
off = 0
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (f *RFile) Create(fid *srv.FFid, name string, perm uint32) (*srv.File, error) {
|
||||
ff := new(RFile)
|
||||
err := ff.Add(&f.File, name, rsrv.user, rsrv.group, perm, ff)
|
||||
return &ff.File, err
|
||||
}
|
||||
|
||||
func (f *RFile) Remove(fid *srv.FFid) error {
|
||||
f.trunc(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *RFile) Wstat(fid *srv.FFid, dir *p.Dir) error {
|
||||
var uid, gid uint32
|
||||
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
up := rsrv.srv.Upool
|
||||
uid = dir.Uidnum
|
||||
gid = dir.Gidnum
|
||||
if uid == p.NOUID && dir.Uid != "" {
|
||||
user := up.Uname2User(dir.Uid)
|
||||
if user == nil {
|
||||
return srv.Enouser
|
||||
}
|
||||
|
||||
f.Uidnum = uint32(user.Id())
|
||||
}
|
||||
|
||||
if gid == p.NOUID && dir.Gid != "" {
|
||||
group := up.Gname2Group(dir.Gid)
|
||||
if group == nil {
|
||||
return srv.Enouser
|
||||
}
|
||||
|
||||
f.Gidnum = uint32(group.Id())
|
||||
}
|
||||
|
||||
if dir.Mode != 0xFFFFFFFF {
|
||||
f.Mode = (f.Mode &^ 0777) | (dir.Mode & 0777)
|
||||
}
|
||||
|
||||
if dir.Name != "" {
|
||||
if err := f.Rename(dir.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if dir.Length != 0xFFFFFFFFFFFFFFFF {
|
||||
f.trunc(dir.Length)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// called with f locked
|
||||
func (f *RFile) trunc(sz uint64) {
|
||||
if f.Length == sz {
|
||||
return
|
||||
}
|
||||
|
||||
if f.Length > sz {
|
||||
f.shrink(sz)
|
||||
} else {
|
||||
f.expand(sz)
|
||||
}
|
||||
}
|
||||
|
||||
// called with f lock held
|
||||
func (f *RFile) shrink(sz uint64) {
|
||||
blknum := sz / uint64(rsrv.blksz)
|
||||
off := sz % uint64(rsrv.blksz)
|
||||
if off > 0 {
|
||||
if len(f.data[blknum]) > 0 {
|
||||
copy(f.data[blknum][off:], rsrv.zero)
|
||||
}
|
||||
|
||||
blknum++
|
||||
}
|
||||
|
||||
for i := blknum; i < uint64(len(f.data)); i++ {
|
||||
if len(f.data[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
select {
|
||||
case rsrv.blkchan <- f.data[i]:
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
f.data = f.data[0:blknum]
|
||||
f.Length = sz
|
||||
}
|
||||
|
||||
func (f *RFile) expand(sz uint64) {
|
||||
blknum := sz / uint64(rsrv.blksz)
|
||||
if sz%uint64(rsrv.blksz) != 0 {
|
||||
blknum++
|
||||
}
|
||||
|
||||
data := make([][]byte, blknum)
|
||||
if f.data != nil {
|
||||
copy(data, f.data)
|
||||
}
|
||||
|
||||
f.data = data
|
||||
f.Length = sz
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var l *p.Logger
|
||||
|
||||
flag.Parse()
|
||||
rsrv.user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
rsrv.group = p.OsUsers.Gid2Group(os.Getegid())
|
||||
rsrv.blksz = *blksize
|
||||
rsrv.blkchan = make(chan []byte, 2048)
|
||||
rsrv.zero = make([]byte, rsrv.blksz)
|
||||
|
||||
root := new(RFile)
|
||||
err = root.Add(nil, "/", rsrv.user, nil, p.DMDIR|0777, root)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
l = p.NewLogger(*logsz)
|
||||
rsrv.srv = srv.NewFileSrv(&root.File)
|
||||
rsrv.srv.Dotu = true
|
||||
rsrv.srv.Debuglevel = *debug
|
||||
rsrv.srv.Start(rsrv.srv)
|
||||
rsrv.srv.Id = "ramfs"
|
||||
rsrv.srv.Log = l
|
||||
|
||||
err = rsrv.srv.StartNetListener("tcp", *addr)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
// Copyright 2009 The Go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Time struct {
|
||||
srv.File
|
||||
}
|
||||
type InfTime struct {
|
||||
srv.File
|
||||
}
|
||||
|
||||
var addr = flag.String("addr", ":5640", "network address")
|
||||
var debug = flag.Bool("d", false, "print debug messages")
|
||||
var debugall = flag.Bool("D", false, "print packets as well as debug messages")
|
||||
|
||||
func (*InfTime) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
// push out time ignoring offset (infinite read)
|
||||
t := time.Now().String() + "\n"
|
||||
b := []byte(t)
|
||||
ml := len(b)
|
||||
if ml > len(buf) {
|
||||
ml = len(buf)
|
||||
}
|
||||
|
||||
copy(buf, b[0:ml])
|
||||
return ml, nil
|
||||
}
|
||||
|
||||
func (*Time) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
b := []byte(time.Now().String())
|
||||
have := len(b)
|
||||
off := int(offset)
|
||||
|
||||
if off >= have {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return copy(buf, b[off:]), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var tm *Time
|
||||
var ntm *InfTime
|
||||
var s *srv.Fsrv
|
||||
|
||||
flag.Parse()
|
||||
user := p.OsUsers.Uid2User(os.Geteuid())
|
||||
root := new(srv.File)
|
||||
err = root.Add(nil, "/", user, nil, p.DMDIR|0555, nil)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
tm = new(Time)
|
||||
err = tm.Add(root, "time", p.OsUsers.Uid2User(os.Geteuid()), nil, 0444, tm)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
ntm = new(InfTime)
|
||||
err = ntm.Add(root, "inftime", p.OsUsers.Uid2User(os.Geteuid()), nil, 0444, ntm)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
s = srv.NewFileSrv(root)
|
||||
s.Dotu = true
|
||||
|
||||
if *debug {
|
||||
s.Debuglevel = 1
|
||||
}
|
||||
if *debugall {
|
||||
s.Debuglevel = 2
|
||||
}
|
||||
|
||||
s.Start(s)
|
||||
err = s.StartNetListener("tcp", *addr)
|
||||
if err != nil {
|
||||
goto error
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
error:
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
}
|
|
@ -1,297 +0,0 @@
|
|||
// Copyright 2009 The Go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Listen on SSL connection, can be used as an example with p/clnt/examples/tls.go
|
||||
// Sample certificate was copied from the Go source code
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Ramfs struct {
|
||||
srv *srv.Fsrv
|
||||
user p.User
|
||||
group p.Group
|
||||
blksz int
|
||||
blkchan chan []byte
|
||||
zero []byte // blksz array of zeroes
|
||||
}
|
||||
|
||||
type RFile struct {
|
||||
srv.File
|
||||
data [][]byte
|
||||
}
|
||||
|
||||
var addr = flag.String("addr", ":5640", "network address")
|
||||
var debug = flag.Int("d", 0, "debuglevel")
|
||||
var blksize = flag.Int("b", 8192, "block size")
|
||||
var logsz = flag.Int("l", 2048, "log size")
|
||||
var rsrv Ramfs
|
||||
|
||||
func (f *RFile) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
if offset > f.Length {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
count := uint32(len(buf))
|
||||
if offset+uint64(count) > f.Length {
|
||||
count = uint32(f.Length - offset)
|
||||
}
|
||||
|
||||
for n, off, b := offset/uint64(rsrv.blksz), offset%uint64(rsrv.blksz), buf[0:count]; len(b) > 0; n++ {
|
||||
m := rsrv.blksz - int(off)
|
||||
if m > len(b) {
|
||||
m = len(b)
|
||||
}
|
||||
|
||||
blk := rsrv.zero
|
||||
if len(f.data[n]) != 0 {
|
||||
blk = f.data[n]
|
||||
}
|
||||
|
||||
// log.Stderr("read block", n, "off", off, "len", m, "l", len(blk), "ll", len(b))
|
||||
copy(b, blk[off:off+uint64(m)])
|
||||
b = b[m:]
|
||||
off = 0
|
||||
}
|
||||
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (f *RFile) Write(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
// make sure the data array is big enough
|
||||
sz := offset + uint64(len(buf))
|
||||
if f.Length < sz {
|
||||
f.expand(sz)
|
||||
}
|
||||
|
||||
count := 0
|
||||
for n, off := offset/uint64(rsrv.blksz), offset%uint64(rsrv.blksz); len(buf) > 0; n++ {
|
||||
blk := f.data[n]
|
||||
if len(blk) == 0 {
|
||||
select {
|
||||
case blk = <-rsrv.blkchan:
|
||||
break
|
||||
default:
|
||||
blk = make([]byte, rsrv.blksz)
|
||||
}
|
||||
|
||||
// if off>0 {
|
||||
copy(blk, rsrv.zero /*[0:off]*/)
|
||||
// }
|
||||
|
||||
f.data[n] = blk
|
||||
}
|
||||
|
||||
m := copy(blk[off:], buf)
|
||||
buf = buf[m:]
|
||||
count += m
|
||||
off = 0
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (f *RFile) Create(fid *srv.FFid, name string, perm uint32) (*srv.File, error) {
|
||||
ff := new(RFile)
|
||||
err := ff.Add(&f.File, name, rsrv.user, rsrv.group, perm, ff)
|
||||
return &ff.File, err
|
||||
}
|
||||
|
||||
func (f *RFile) Remove(fid *srv.FFid) error {
|
||||
f.trunc(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *RFile) Wstat(fid *srv.FFid, dir *p.Dir) error {
|
||||
var uid, gid uint32
|
||||
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
up := rsrv.srv.Upool
|
||||
uid = dir.Uidnum
|
||||
gid = dir.Gidnum
|
||||
if uid == p.NOUID && dir.Uid != "" {
|
||||
user := up.Uname2User(dir.Uid)
|
||||
if user == nil {
|
||||
return srv.Enouser
|
||||
}
|
||||
|
||||
f.Uidnum = uint32(user.Id())
|
||||
}
|
||||
|
||||
if gid == p.NOUID && dir.Gid != "" {
|
||||
group := up.Gname2Group(dir.Gid)
|
||||
if group == nil {
|
||||
return srv.Enouser
|
||||
}
|
||||
|
||||
f.Gidnum = uint32(group.Id())
|
||||
}
|
||||
|
||||
if dir.Mode != 0xFFFFFFFF {
|
||||
f.Mode = (f.Mode &^ 0777) | (dir.Mode & 0777)
|
||||
}
|
||||
|
||||
if dir.Name != "" {
|
||||
if err := f.Rename(dir.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if dir.Length != 0xFFFFFFFFFFFFFFFF {
|
||||
f.trunc(dir.Length)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// called with f locked
|
||||
func (f *RFile) trunc(sz uint64) {
|
||||
if f.Length == sz {
|
||||
return
|
||||
}
|
||||
|
||||
if f.Length > sz {
|
||||
f.shrink(sz)
|
||||
} else {
|
||||
f.expand(sz)
|
||||
}
|
||||
}
|
||||
|
||||
// called with f lock held
|
||||
func (f *RFile) shrink(sz uint64) {
|
||||
blknum := sz / uint64(rsrv.blksz)
|
||||
off := sz % uint64(rsrv.blksz)
|
||||
if off > 0 {
|
||||
if len(f.data[blknum]) > 0 {
|
||||
copy(f.data[blknum][off:], rsrv.zero)
|
||||
}
|
||||
|
||||
blknum++
|
||||
}
|
||||
|
||||
for i := blknum; i < uint64(len(f.data)); i++ {
|
||||
if len(f.data[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
select {
|
||||
case rsrv.blkchan <- f.data[i]:
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
f.data = f.data[0:blknum]
|
||||
f.Length = sz
|
||||
}
|
||||
|
||||
func (f *RFile) expand(sz uint64) {
|
||||
blknum := sz / uint64(rsrv.blksz)
|
||||
if sz%uint64(rsrv.blksz) != 0 {
|
||||
blknum++
|
||||
}
|
||||
|
||||
data := make([][]byte, blknum)
|
||||
if f.data != nil {
|
||||
copy(data, f.data)
|
||||
}
|
||||
|
||||
f.data = data
|
||||
f.Length = sz
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
flag.Parse()
|
||||
rsrv.user = p.OsUsers.Uid2User(os.Geteuid())
|
||||
rsrv.group = p.OsUsers.Gid2Group(os.Getegid())
|
||||
rsrv.blksz = *blksize
|
||||
rsrv.blkchan = make(chan []byte, 2048)
|
||||
rsrv.zero = make([]byte, rsrv.blksz)
|
||||
|
||||
root := new(RFile)
|
||||
err = root.Add(nil, "/", rsrv.user, nil, p.DMDIR|0777, root)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
l := p.NewLogger(*logsz)
|
||||
rsrv.srv = srv.NewFileSrv(&root.File)
|
||||
rsrv.srv.Dotu = true
|
||||
rsrv.srv.Debuglevel = *debug
|
||||
rsrv.srv.Start(rsrv.srv)
|
||||
rsrv.srv.Id = "ramfs"
|
||||
rsrv.srv.Log = l
|
||||
|
||||
cert := make([]tls.Certificate, 1)
|
||||
cert[0].Certificate = [][]byte{testCertificate}
|
||||
cert[0].PrivateKey = testPrivateKey
|
||||
|
||||
ls, oerr := tls.Listen("tcp", *addr, &tls.Config{
|
||||
Rand: rand.Reader,
|
||||
Certificates: cert,
|
||||
CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA},
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
if oerr != nil {
|
||||
log.Println("can't listen:", oerr)
|
||||
return
|
||||
}
|
||||
|
||||
err = rsrv.srv.StartListener(ls)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error: %s", err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Copied from crypto/tls/handshake_server_test.go from the Go repository
|
||||
func bigFromString(s string) *big.Int {
|
||||
ret := new(big.Int)
|
||||
ret.SetString(s, 10)
|
||||
return ret
|
||||
}
|
||||
|
||||
func fromHex(s string) []byte {
|
||||
b, _ := hex.DecodeString(s)
|
||||
return b
|
||||
}
|
||||
|
||||
var testCertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
|
||||
|
||||
var testPrivateKey = &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
|
||||
E: 65537,
|
||||
},
|
||||
D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
|
||||
Primes: []*big.Int{
|
||||
bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
|
||||
bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
|
||||
},
|
||||
}
|
|
@ -2,9 +2,11 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The p9 package provides the definitions and functions used to implement
|
||||
// The p9 package go9provides the definitions and functions used to implement
|
||||
// the 9P2000 protocol.
|
||||
package p
|
||||
// TODO.
|
||||
// All the packet conversion code in this file is crap and needs a rewrite.
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -44,9 +46,9 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
MSIZE = 8192 + IOHDRSZ // default message size (8192+IOHdrSz)
|
||||
IOHDRSZ = 24 // the non-data size of the Twrite messages
|
||||
PORT = 564 // default port for 9P file servers
|
||||
MSIZE = 1048576 + IOHDRSZ // default message size (1048576+IOHdrSz)
|
||||
IOHDRSZ = 24 // the non-data size of the Twrite messages
|
||||
PORT = 564 // default port for 9P file servers
|
||||
)
|
||||
|
||||
// Qid types
|
||||
|
@ -301,11 +303,12 @@ func gint64(buf []byte) (uint64, []byte) {
|
|||
func gstr(buf []byte) (string, []byte) {
|
||||
var n uint16
|
||||
|
||||
if buf == nil {
|
||||
if buf == nil || len(buf) < 2 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
n, buf = gint16(buf)
|
||||
|
||||
if int(n) > len(buf) {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -321,7 +324,8 @@ func gqid(buf []byte, qid *Qid) []byte {
|
|||
return buf
|
||||
}
|
||||
|
||||
func gstat(buf []byte, d *Dir, dotu bool) []byte {
|
||||
func gstat(buf []byte, d *Dir, dotu bool) ([]byte, error) {
|
||||
sz := len(buf)
|
||||
d.Size, buf = gint16(buf)
|
||||
d.Type, buf = gint16(buf)
|
||||
d.Dev, buf = gint32(buf)
|
||||
|
@ -332,27 +336,29 @@ func gstat(buf []byte, d *Dir, dotu bool) []byte {
|
|||
d.Length, buf = gint64(buf)
|
||||
d.Name, buf = gstr(buf)
|
||||
if buf == nil {
|
||||
return nil
|
||||
s := fmt.Sprintf("Buffer too short for basic 9p: need %d, have %d",
|
||||
49, sz)
|
||||
return nil, &Error{s, EINVAL}
|
||||
}
|
||||
|
||||
d.Uid, buf = gstr(buf)
|
||||
if buf == nil {
|
||||
return nil
|
||||
return nil, &Error{"d.Uid failed", EINVAL}
|
||||
}
|
||||
d.Gid, buf = gstr(buf)
|
||||
if buf == nil {
|
||||
return nil
|
||||
return nil, &Error{"d.Gid failed", EINVAL}
|
||||
}
|
||||
|
||||
d.Muid, buf = gstr(buf)
|
||||
if buf == nil {
|
||||
return nil
|
||||
return nil, &Error{"d.Muid failed", EINVAL}
|
||||
}
|
||||
|
||||
if dotu {
|
||||
d.Ext, buf = gstr(buf)
|
||||
if buf == nil {
|
||||
return nil
|
||||
return nil, &Error{"d.Ext failed", EINVAL}
|
||||
}
|
||||
|
||||
d.Uidnum, buf = gint32(buf)
|
||||
|
@ -364,7 +370,7 @@ func gstat(buf []byte, d *Dir, dotu bool) []byte {
|
|||
d.Muidnum = NOUID
|
||||
}
|
||||
|
||||
return buf
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func pint8(val uint8, buf []byte) []byte {
|
||||
|
@ -449,20 +455,17 @@ func pstat(d *Dir, buf []byte, dotu bool) []byte {
|
|||
|
||||
// Converts a Dir value to its on-the-wire representation and writes it to
|
||||
// the buf. Returns the number of bytes written, 0 if there is not enough space.
|
||||
func PackDir(d *Dir, buf []byte, dotu bool) int {
|
||||
func PackDir(d *Dir, dotu bool) []byte {
|
||||
sz := statsz(d, dotu)
|
||||
if sz > len(buf) {
|
||||
return 0
|
||||
}
|
||||
|
||||
buf = pstat(d, buf, dotu)
|
||||
return sz
|
||||
buf := make([]byte, sz)
|
||||
pstat(d, buf, dotu)
|
||||
return buf
|
||||
}
|
||||
|
||||
// Converts the on-the-wire representation of a stat to Stat value.
|
||||
// Returns an error if the conversion is impossible, otherwise
|
||||
// a pointer to a Stat value.
|
||||
func UnpackDir(buf []byte, dotu bool) (d *Dir, err error) {
|
||||
func UnpackDir(buf []byte, dotu bool) (d *Dir, b []byte, amt int, err error) {
|
||||
sz := 2 + 2 + 4 + 13 + 4 + /* size[2] type[2] dev[4] qid[13] mode[4] */
|
||||
4 + 4 + 8 + /* atime[4] mtime[4] length[8] */
|
||||
2 + 2 + 2 + 2 /* name[s] uid[s] gid[s] muid[s] */
|
||||
|
@ -472,19 +475,17 @@ func UnpackDir(buf []byte, dotu bool) (d *Dir, err error) {
|
|||
}
|
||||
|
||||
if len(buf) < sz {
|
||||
goto szerror
|
||||
s := fmt.Sprintf("short buffer: Need %d and have %v", sz, len(buf))
|
||||
return nil, nil, 0, &Error{s, EINVAL}
|
||||
}
|
||||
|
||||
d = new(Dir)
|
||||
buf = gstat(buf, d, dotu)
|
||||
if buf == nil {
|
||||
goto szerror
|
||||
b, err = gstat(buf, d, dotu)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
||||
szerror:
|
||||
return nil, &Error{"short buffer", EINVAL}
|
||||
return d, b, len(buf) - len(b), nil
|
||||
|
||||
}
|
||||
|
||||
|
@ -522,7 +523,7 @@ func packCommon(fc *Fcall, size int, id uint8) ([]byte, error) {
|
|||
|
||||
func (err *Error) Error() string {
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%s: %d", err.Err, err.Errornum)
|
||||
return err.Err
|
||||
}
|
||||
|
||||
return ""
|
|
@ -2,7 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
package go9p
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Create a Rversion message in the specified Fcall.
|
||||
func PackRversion(fc *Fcall, msize uint32, version string) error {
|
||||
|
@ -34,9 +36,17 @@ func PackRauth(fc *Fcall, aqid *Qid) error {
|
|||
}
|
||||
|
||||
// Create a Rerror message in the specified Fcall. If dotu is true,
|
||||
// the function will create a 9P2000.u message. If false, nerror is
|
||||
// the function will create a 9P2000.u message. If false, errornum is
|
||||
// ignored.
|
||||
// The Akaros global is hurl-inducing but this whole blob of code
|
||||
// needs a redo. dotu is even worse, since it bakes in ONE PARTICULAR
|
||||
// EXTENSION ...
|
||||
|
||||
func PackRerror(fc *Fcall, error string, errornum uint32, dotu bool) error {
|
||||
if *Akaros {
|
||||
error = fmt.Sprintf("%04X %v", errornum, error)
|
||||
}
|
||||
|
||||
size := 2 + len(error) /* ename[s] */
|
||||
if dotu {
|
||||
size += 4 /* ecode[4] */
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
package go9p
|
||||
|
||||
// Create a Tversion message in the specified Fcall.
|
||||
func PackTversion(fc *Fcall, msize uint32, version string) error {
|
|
@ -2,11 +2,10 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
@ -18,11 +17,11 @@ func (srv *Srv) NewConn(c net.Conn) {
|
|||
conn.Dotu = srv.Dotu
|
||||
conn.Debuglevel = srv.Debuglevel
|
||||
conn.conn = c
|
||||
conn.fidpool = make(map[uint32]*Fid)
|
||||
conn.reqs = make(map[uint16]*Req)
|
||||
conn.reqout = make(chan *Req, srv.Maxpend)
|
||||
conn.fidpool = make(map[uint32]*SrvFid)
|
||||
conn.reqs = make(map[uint16]*SrvReq)
|
||||
conn.reqout = make(chan *SrvReq, srv.Maxpend)
|
||||
conn.done = make(chan bool)
|
||||
conn.rchan = make(chan *p.Fcall, 64)
|
||||
conn.rchan = make(chan *Fcall, 64)
|
||||
|
||||
srv.Lock()
|
||||
if srv.conns == nil {
|
||||
|
@ -58,7 +57,7 @@ func (conn *Conn) close() {
|
|||
}
|
||||
|
||||
/* call FidDestroy for all remaining fids */
|
||||
if op, ok := (conn.Srv.ops).(FidOps); ok {
|
||||
if op, ok := (conn.Srv.ops).(SrvFidOps); ok {
|
||||
for _, fid := range conn.fidpool {
|
||||
op.FidDestroy(fid)
|
||||
}
|
||||
|
@ -87,7 +86,7 @@ func (conn *Conn) recv() {
|
|||
|
||||
pos += n
|
||||
for pos > 4 {
|
||||
sz, _ := p.Gint32(buf)
|
||||
sz, _ := Gint32(buf)
|
||||
if sz > conn.Msize {
|
||||
log.Println("bad client connection: ", conn.conn.RemoteAddr())
|
||||
conn.conn.Close()
|
||||
|
@ -104,7 +103,7 @@ func (conn *Conn) recv() {
|
|||
|
||||
break
|
||||
}
|
||||
fc, err, fcsize := p.Unpack(buf, conn.Dotu)
|
||||
fc, err, fcsize := Unpack(buf, conn.Dotu)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("invalid packet : %v %v", err, buf))
|
||||
conn.conn.Close()
|
||||
|
@ -113,12 +112,12 @@ func (conn *Conn) recv() {
|
|||
}
|
||||
|
||||
tag := fc.Tag
|
||||
req := new(Req)
|
||||
req := new(SrvReq)
|
||||
select {
|
||||
case req.Rc = <-conn.rchan:
|
||||
break
|
||||
default:
|
||||
req.Rc = p.NewFcall(conn.Msize)
|
||||
req.Rc = NewFcall(conn.Msize)
|
||||
}
|
||||
|
||||
req.Conn = conn
|
||||
|
@ -151,7 +150,15 @@ func (conn *Conn) recv() {
|
|||
}
|
||||
conn.Unlock()
|
||||
if process {
|
||||
go req.process()
|
||||
// Tversion may change some attributes of the
|
||||
// connection, so we block on it. Otherwise,
|
||||
// we may loop back to reading and that is a race.
|
||||
// This fix brought to you by the race detector.
|
||||
if req.Tc.Type == Tversion {
|
||||
req.process()
|
||||
} else {
|
||||
go req.process()
|
||||
}
|
||||
}
|
||||
|
||||
buf = buf[fcsize:]
|
||||
|
@ -159,7 +166,6 @@ func (conn *Conn) recv() {
|
|||
}
|
||||
}
|
||||
|
||||
panic("unreached")
|
||||
}
|
||||
|
||||
func (conn *Conn) send() {
|
||||
|
@ -169,7 +175,7 @@ func (conn *Conn) send() {
|
|||
return
|
||||
|
||||
case req := <-conn.reqout:
|
||||
p.SetTag(req.Rc, req.Tc.Tag)
|
||||
SetTag(req.Rc, req.Tc.Tag)
|
||||
conn.Lock()
|
||||
conn.rsz += uint64(req.Rc.Size)
|
||||
conn.npend--
|
||||
|
@ -216,7 +222,7 @@ func (conn *Conn) LocalAddr() net.Addr {
|
|||
return conn.conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (conn *Conn) logFcall(fc *p.Fcall) {
|
||||
func (conn *Conn) logFcall(fc *Fcall) {
|
||||
if conn.Debuglevel&DbgLogPackets != 0 {
|
||||
pkt := make([]byte, len(fc.Pkt))
|
||||
copy(pkt, fc.Pkt)
|
||||
|
@ -224,7 +230,7 @@ func (conn *Conn) logFcall(fc *p.Fcall) {
|
|||
}
|
||||
|
||||
if conn.Debuglevel&DbgLogFcalls != 0 {
|
||||
f := new(p.Fcall)
|
||||
f := new(Fcall)
|
||||
*f = *fc
|
||||
f.Pkt = nil
|
||||
conn.Srv.Log.Log(f, conn, DbgLogFcalls)
|
||||
|
@ -234,7 +240,7 @@ func (conn *Conn) logFcall(fc *p.Fcall) {
|
|||
func (srv *Srv) StartNetListener(ntype, addr string) error {
|
||||
l, err := net.Listen(ntype, addr)
|
||||
if err != nil {
|
||||
return &p.Error{err.Error(), p.EIO}
|
||||
return &Error{err.Error(), EIO}
|
||||
}
|
||||
|
||||
return srv.StartListener(l)
|
||||
|
@ -248,7 +254,7 @@ func (srv *Srv) StartListener(l net.Listener) error {
|
|||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
return &p.Error{err.Error(), p.EIO}
|
||||
return &Error{err.Error(), EIO}
|
||||
}
|
||||
|
||||
srv.NewConn(c)
|
|
@ -2,20 +2,16 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
import "runtime"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
)
|
||||
|
||||
func (srv *Srv) version(req *Req) {
|
||||
func (srv *Srv) version(req *SrvReq) {
|
||||
tc := req.Tc
|
||||
conn := req.Conn
|
||||
|
||||
if tc.Msize < p.IOHDRSZ {
|
||||
req.RespondError(&p.Error{"msize too small", p.EINVAL})
|
||||
if tc.Msize < IOHDRSZ {
|
||||
req.RespondError(&Error{"msize too small", EINVAL})
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -32,7 +28,7 @@ func (srv *Srv) version(req *Req) {
|
|||
/* make sure that the responses of all current requests will be ignored */
|
||||
conn.Lock()
|
||||
for tag, r := range conn.reqs {
|
||||
if tag == p.NOTAG {
|
||||
if tag == NOTAG {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -47,10 +43,10 @@ func (srv *Srv) version(req *Req) {
|
|||
req.RespondRversion(conn.Msize, ver)
|
||||
}
|
||||
|
||||
func (srv *Srv) auth(req *Req) {
|
||||
func (srv *Srv) auth(req *SrvReq) {
|
||||
tc := req.Tc
|
||||
conn := req.Conn
|
||||
if tc.Afid == p.NOFID {
|
||||
if tc.Afid == NOFID {
|
||||
req.RespondError(Eunknownfid)
|
||||
return
|
||||
}
|
||||
|
@ -61,8 +57,8 @@ func (srv *Srv) auth(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
var user p.User = nil
|
||||
if tc.Unamenum != p.NOUID || conn.Dotu {
|
||||
var user User = nil
|
||||
if tc.Unamenum != NOUID || conn.Dotu {
|
||||
user = srv.Upool.Uid2User(int(tc.Unamenum))
|
||||
} else if tc.Uname != "" {
|
||||
user = srv.Upool.Uname2User(tc.Uname)
|
||||
|
@ -76,13 +72,13 @@ func (srv *Srv) auth(req *Req) {
|
|||
}
|
||||
|
||||
req.Afid.User = user
|
||||
req.Afid.Type = p.QTAUTH
|
||||
req.Afid.Type = QTAUTH
|
||||
if aop, ok := (srv.ops).(AuthOps); ok {
|
||||
aqid, err := aop.AuthInit(req.Afid, tc.Aname)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
aqid.Type |= p.QTAUTH // just in case
|
||||
aqid.Type |= QTAUTH // just in case
|
||||
req.RespondRauth(aqid)
|
||||
}
|
||||
} else {
|
||||
|
@ -91,16 +87,16 @@ func (srv *Srv) auth(req *Req) {
|
|||
|
||||
}
|
||||
|
||||
func (srv *Srv) authPost(req *Req) {
|
||||
if req.Rc != nil && req.Rc.Type == p.Rauth {
|
||||
func (srv *Srv) authPost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Rc.Type == Rauth {
|
||||
req.Afid.IncRef()
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) attach(req *Req) {
|
||||
func (srv *Srv) attach(req *SrvReq) {
|
||||
tc := req.Tc
|
||||
conn := req.Conn
|
||||
if tc.Fid == p.NOFID {
|
||||
if tc.Fid == NOFID {
|
||||
req.RespondError(Eunknownfid)
|
||||
return
|
||||
}
|
||||
|
@ -111,15 +107,15 @@ func (srv *Srv) attach(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if tc.Afid != p.NOFID {
|
||||
if tc.Afid != NOFID {
|
||||
req.Afid = conn.FidGet(tc.Afid)
|
||||
if req.Afid == nil {
|
||||
req.RespondError(Eunknownfid)
|
||||
}
|
||||
}
|
||||
|
||||
var user p.User = nil
|
||||
if tc.Unamenum != p.NOUID || conn.Dotu {
|
||||
var user User = nil
|
||||
if tc.Unamenum != NOUID || conn.Dotu {
|
||||
user = srv.Upool.Uid2User(int(tc.Unamenum))
|
||||
} else if tc.Uname != "" {
|
||||
user = srv.Upool.Uname2User(tc.Uname)
|
||||
|
@ -141,20 +137,20 @@ func (srv *Srv) attach(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
(srv.ops).(ReqOps).Attach(req)
|
||||
(srv.ops).(SrvReqOps).Attach(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) attachPost(req *Req) {
|
||||
if req.Rc != nil && req.Rc.Type == p.Rattach {
|
||||
func (srv *Srv) attachPost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Rc.Type == Rattach {
|
||||
req.Fid.Type = req.Rc.Qid.Type
|
||||
req.Fid.IncRef()
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) flush(req *Req) {
|
||||
func (srv *Srv) flush(req *SrvReq) {
|
||||
conn := req.Conn
|
||||
tag := req.Tc.Oldtag
|
||||
p.PackRflush(req.Rc)
|
||||
PackRflush(req.Rc)
|
||||
conn.Lock()
|
||||
r := conn.reqs[tag]
|
||||
if r != nil {
|
||||
|
@ -186,13 +182,13 @@ func (srv *Srv) flush(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) walk(req *Req) {
|
||||
func (srv *Srv) walk(req *SrvReq) {
|
||||
conn := req.Conn
|
||||
tc := req.Tc
|
||||
fid := req.Fid
|
||||
|
||||
/* we can't walk regular files, only clone them */
|
||||
if len(tc.Wname) > 0 && (fid.Type&p.QTDIR) == 0 {
|
||||
if len(tc.Wname) > 0 && (fid.Type&QTDIR) == 0 {
|
||||
req.RespondError(Enotdir)
|
||||
return
|
||||
}
|
||||
|
@ -217,12 +213,12 @@ func (srv *Srv) walk(req *Req) {
|
|||
req.Newfid.IncRef()
|
||||
}
|
||||
|
||||
(req.Conn.Srv.ops).(ReqOps).Walk(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Walk(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) walkPost(req *Req) {
|
||||
func (srv *Srv) walkPost(req *SrvReq) {
|
||||
rc := req.Rc
|
||||
if rc == nil || rc.Type != p.Rwalk || req.Newfid == nil {
|
||||
if rc == nil || rc.Type != Rwalk || req.Newfid == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -243,7 +239,7 @@ func (srv *Srv) walkPost(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) open(req *Req) {
|
||||
func (srv *Srv) open(req *SrvReq) {
|
||||
fid := req.Fid
|
||||
tc := req.Tc
|
||||
if fid.opened {
|
||||
|
@ -251,22 +247,22 @@ func (srv *Srv) open(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if (fid.Type&p.QTDIR) != 0 && tc.Mode != p.OREAD {
|
||||
if (fid.Type&QTDIR) != 0 && tc.Mode != OREAD {
|
||||
req.RespondError(Eperm)
|
||||
return
|
||||
}
|
||||
|
||||
fid.Omode = tc.Mode
|
||||
(req.Conn.Srv.ops).(ReqOps).Open(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Open(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) openPost(req *Req) {
|
||||
func (srv *Srv) openPost(req *SrvReq) {
|
||||
if req.Fid != nil {
|
||||
req.Fid.opened = req.Rc != nil && req.Rc.Type == p.Ropen
|
||||
req.Fid.opened = req.Rc != nil && req.Rc.Type == Ropen
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) create(req *Req) {
|
||||
func (srv *Srv) create(req *SrvReq) {
|
||||
fid := req.Fid
|
||||
tc := req.Tc
|
||||
if fid.opened {
|
||||
|
@ -274,47 +270,47 @@ func (srv *Srv) create(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if (fid.Type & p.QTDIR) == 0 {
|
||||
if (fid.Type & QTDIR) == 0 {
|
||||
req.RespondError(Enotdir)
|
||||
return
|
||||
}
|
||||
|
||||
/* can't open directories for other than reading */
|
||||
if (tc.Perm&p.DMDIR) != 0 && tc.Mode != p.OREAD {
|
||||
if (tc.Perm&DMDIR) != 0 && tc.Mode != OREAD {
|
||||
req.RespondError(Eperm)
|
||||
return
|
||||
}
|
||||
|
||||
/* can't create special files if not 9P2000.u */
|
||||
if (tc.Perm&(p.DMNAMEDPIPE|p.DMSYMLINK|p.DMLINK|p.DMDEVICE|p.DMSOCKET)) != 0 && !req.Conn.Dotu {
|
||||
if (tc.Perm&(DMNAMEDPIPE|DMSYMLINK|DMLINK|DMDEVICE|DMSOCKET)) != 0 && !req.Conn.Dotu {
|
||||
req.RespondError(Eperm)
|
||||
return
|
||||
}
|
||||
|
||||
fid.Omode = tc.Mode
|
||||
(req.Conn.Srv.ops).(ReqOps).Create(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Create(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) createPost(req *Req) {
|
||||
if req.Rc != nil && req.Rc.Type == p.Rcreate && req.Fid != nil {
|
||||
func (srv *Srv) createPost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Rc.Type == Rcreate && req.Fid != nil {
|
||||
req.Fid.Type = req.Rc.Qid.Type
|
||||
req.Fid.opened = true
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) read(req *Req) {
|
||||
func (srv *Srv) read(req *SrvReq) {
|
||||
tc := req.Tc
|
||||
fid := req.Fid
|
||||
if tc.Count+p.IOHDRSZ > req.Conn.Msize {
|
||||
if tc.Count+IOHDRSZ > req.Conn.Msize {
|
||||
req.RespondError(Etoolarge)
|
||||
return
|
||||
}
|
||||
|
||||
if (fid.Type & p.QTAUTH) != 0 {
|
||||
if (fid.Type & QTAUTH) != 0 {
|
||||
var n int
|
||||
|
||||
rc := req.Rc
|
||||
err := p.InitRread(rc, tc.Count)
|
||||
err := InitRread(rc, tc.Count)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
|
@ -327,7 +323,7 @@ func (srv *Srv) read(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
p.SetRreadCount(rc, uint32(n))
|
||||
SetRreadCount(rc, uint32(n))
|
||||
req.Respond()
|
||||
} else {
|
||||
req.RespondError(Enotimpl)
|
||||
|
@ -336,28 +332,27 @@ func (srv *Srv) read(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if (fid.Type & p.QTDIR) != 0 {
|
||||
if (fid.Type & QTDIR) != 0 {
|
||||
if tc.Offset == 0 {
|
||||
fid.Diroffset = 0
|
||||
} else if tc.Offset != fid.Diroffset {
|
||||
req.RespondError(Ebadoffset)
|
||||
return
|
||||
fid.Diroffset = tc.Offset
|
||||
}
|
||||
}
|
||||
|
||||
(req.Conn.Srv.ops).(ReqOps).Read(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Read(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) readPost(req *Req) {
|
||||
if req.Rc != nil && req.Rc.Type == p.Rread && (req.Fid.Type&p.QTDIR) != 0 {
|
||||
func (srv *Srv) readPost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Rc.Type == Rread && (req.Fid.Type&QTDIR) != 0 {
|
||||
req.Fid.Diroffset += uint64(req.Rc.Count)
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) write(req *Req) {
|
||||
func (srv *Srv) write(req *SrvReq) {
|
||||
fid := req.Fid
|
||||
tc := req.Tc
|
||||
if (fid.Type & p.QTAUTH) != 0 {
|
||||
if (fid.Type & QTAUTH) != 0 {
|
||||
tc := req.Tc
|
||||
if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
|
||||
n, err := op.AuthWrite(req.Fid, tc.Offset, tc.Data)
|
||||
|
@ -373,22 +368,22 @@ func (srv *Srv) write(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if !fid.opened || (fid.Type&p.QTDIR) != 0 || (fid.Omode&3) == p.OREAD {
|
||||
if !fid.opened || (fid.Type&QTDIR) != 0 || (fid.Omode&3) == OREAD {
|
||||
req.RespondError(Ebaduse)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.Count+p.IOHDRSZ > req.Conn.Msize {
|
||||
if tc.Count+IOHDRSZ > req.Conn.Msize {
|
||||
req.RespondError(Etoolarge)
|
||||
return
|
||||
}
|
||||
|
||||
(req.Conn.Srv.ops).(ReqOps).Write(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Write(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) clunk(req *Req) {
|
||||
func (srv *Srv) clunk(req *SrvReq) {
|
||||
fid := req.Fid
|
||||
if (fid.Type & p.QTAUTH) != 0 {
|
||||
if (fid.Type & QTAUTH) != 0 {
|
||||
if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
|
||||
op.AuthDestroy(fid)
|
||||
req.RespondRclunk()
|
||||
|
@ -399,26 +394,26 @@ func (srv *Srv) clunk(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
(req.Conn.Srv.ops).(ReqOps).Clunk(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Clunk(req)
|
||||
}
|
||||
|
||||
func (srv *Srv) clunkPost(req *Req) {
|
||||
if req.Rc != nil && req.Rc.Type == p.Rclunk && req.Fid != nil {
|
||||
func (srv *Srv) clunkPost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Rc.Type == Rclunk && req.Fid != nil {
|
||||
req.Fid.DecRef()
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) remove(req *Req) { (req.Conn.Srv.ops).(ReqOps).Remove(req) }
|
||||
func (srv *Srv) remove(req *SrvReq) { (req.Conn.Srv.ops).(SrvReqOps).Remove(req) }
|
||||
|
||||
func (srv *Srv) removePost(req *Req) {
|
||||
func (srv *Srv) removePost(req *SrvReq) {
|
||||
if req.Rc != nil && req.Fid != nil {
|
||||
req.Fid.DecRef()
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Srv) stat(req *Req) { (req.Conn.Srv.ops).(ReqOps).Stat(req) }
|
||||
func (srv *Srv) stat(req *SrvReq) { (req.Conn.Srv.ops).(SrvReqOps).Stat(req) }
|
||||
|
||||
func (srv *Srv) wstat(req *Req) {
|
||||
func (srv *Srv) wstat(req *SrvReq) {
|
||||
/*
|
||||
fid := req.Fid
|
||||
d := &req.Tc.Dir
|
||||
|
@ -428,12 +423,12 @@ func (srv *Srv) wstat(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if (d.Mode != 0xFFFFFFFF) && (((fid.Type&p.QTDIR) != 0 && (d.Mode&p.DMDIR) == 0) ||
|
||||
((d.Type&p.QTDIR) == 0 && (d.Mode&p.DMDIR) != 0)) {
|
||||
if (d.Mode != 0xFFFFFFFF) && (((fid.Type&QTDIR) != 0 && (d.Mode&DMDIR) == 0) ||
|
||||
((d.Type&QTDIR) == 0 && (d.Mode&DMDIR) != 0)) {
|
||||
req.RespondError(Edirchange)
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
(req.Conn.Srv.ops).(ReqOps).Wstat(req)
|
||||
(req.Conn.Srv.ops).(SrvReqOps).Wstat(req)
|
||||
}
|
|
@ -2,10 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -13,18 +12,18 @@ import (
|
|||
|
||||
// The FStatOp interface provides a single operation (Stat) that will be
|
||||
// called before a file stat is sent back to the client. If implemented,
|
||||
// the operation should update the data in the File struct.
|
||||
// the operation should update the data in the srvFile struct.
|
||||
type FStatOp interface {
|
||||
Stat(fid *FFid) error
|
||||
}
|
||||
|
||||
// The FWstatOp interface provides a single operation (Wstat) that will be
|
||||
// called when the client requests the File metadata to be modified. If
|
||||
// called when the client requests the srvFile metadata to be modified. If
|
||||
// implemented, the operation will be called when Twstat message is received.
|
||||
// If not implemented, "permission denied" error will be sent back. If the
|
||||
// operation returns an Error, the error is send back to the client.
|
||||
type FWstatOp interface {
|
||||
Wstat(*FFid, *p.Dir) error
|
||||
Wstat(*FFid, *Dir) error
|
||||
}
|
||||
|
||||
// If the FReadOp interface is implemented, the Read operation will be called
|
||||
|
@ -44,16 +43,16 @@ type FWriteOp interface {
|
|||
}
|
||||
|
||||
// If the FCreateOp interface is implemented, the Create operation will be called
|
||||
// when the client attempts to create a file in the File implementing the interface.
|
||||
// when the client attempts to create a file in the srvFile implementing the interface.
|
||||
// If not implemented, "permission denied" error will be send back. If successful,
|
||||
// the operation should call (*File)Add() to add the created file to the directory.
|
||||
// The operation returns the created file, or the error occured while creating it.
|
||||
type FCreateOp interface {
|
||||
Create(fid *FFid, name string, perm uint32) (*File, error)
|
||||
Create(fid *FFid, name string, perm uint32) (*srvFile, error)
|
||||
}
|
||||
|
||||
// If the FRemoveOp interface is implemented, the Remove operation will be called
|
||||
// when the client attempts to create a file in the File implementing the interface.
|
||||
// when the client attempts to create a file in the srvFile implementing the interface.
|
||||
// If not implemented, "permission denied" error will be send back.
|
||||
// The operation returns nil if successful, or the error that occured while removing
|
||||
// the file.
|
||||
|
@ -79,39 +78,40 @@ const (
|
|||
Fremoved FFlags = 1 << iota
|
||||
)
|
||||
|
||||
// The File type represents a file (or directory) served by the file server.
|
||||
type File struct {
|
||||
// The srvFile type represents a file (or directory) served by the file server.
|
||||
type srvFile struct {
|
||||
sync.Mutex
|
||||
p.Dir
|
||||
Dir
|
||||
flags FFlags
|
||||
|
||||
Parent *File // parent
|
||||
next, prev *File // siblings, guarded by parent.Lock
|
||||
cfirst, clast *File // children (if directory)
|
||||
Ops interface{}
|
||||
Parent *srvFile // parent
|
||||
next, prev *srvFile // siblings, guarded by parent.Lock
|
||||
cfirst, clast *srvFile // children (if directory)
|
||||
ops interface{}
|
||||
}
|
||||
|
||||
type FFid struct {
|
||||
F *File
|
||||
Fid *Fid
|
||||
dirs []*File // used for readdir
|
||||
F *srvFile
|
||||
Fid *SrvFid
|
||||
dirs []*srvFile // used for readdir
|
||||
dirents []byte // serialized version of dirs
|
||||
}
|
||||
|
||||
// The Fsrv can be used to create file servers that serve
|
||||
// simple trees of synthetic files.
|
||||
type Fsrv struct {
|
||||
Srv
|
||||
Root *File
|
||||
Root *srvFile
|
||||
}
|
||||
|
||||
var lock sync.Mutex
|
||||
var qnext uint64
|
||||
var Eexist = &p.Error{"file already exists", p.EEXIST}
|
||||
var Enoent = &p.Error{"file not found", p.ENOENT}
|
||||
var Enotempty = &p.Error{"directory not empty", p.EPERM}
|
||||
var Eexist = &Error{"file already exists", EEXIST}
|
||||
var Enoent = &Error{"file not found", ENOENT}
|
||||
var Enotempty = &Error{"directory not empty", EPERM}
|
||||
|
||||
// Creates a file server with root as root directory
|
||||
func NewFileSrv(root *File) *Fsrv {
|
||||
func NewsrvFileSrv(root *srvFile) *Fsrv {
|
||||
srv := new(Fsrv)
|
||||
srv.Root = root
|
||||
root.Parent = root // make sure we can .. in root
|
||||
|
@ -121,7 +121,7 @@ func NewFileSrv(root *File) *Fsrv {
|
|||
|
||||
// Initializes the fields of a file and add it to a directory.
|
||||
// Returns nil if successful, or an error.
|
||||
func (f *File) Add(dir *File, name string, uid p.User, gid p.Group, mode uint32, ops interface{}) error {
|
||||
func (f *srvFile) Add(dir *srvFile, name string, uid User, gid Group, mode uint32, ops interface{}) error {
|
||||
|
||||
lock.Lock()
|
||||
qpath := qnext
|
||||
|
@ -141,7 +141,7 @@ func (f *File) Add(dir *File, name string, uid p.User, gid p.Group, mode uint32,
|
|||
f.Uidnum = uint32(uid.Id())
|
||||
} else {
|
||||
f.Uid = "none"
|
||||
f.Uidnum = p.NOUID
|
||||
f.Uidnum = NOUID
|
||||
}
|
||||
|
||||
if gid != nil {
|
||||
|
@ -149,11 +149,11 @@ func (f *File) Add(dir *File, name string, uid p.User, gid p.Group, mode uint32,
|
|||
f.Gidnum = uint32(gid.Id())
|
||||
} else {
|
||||
f.Gid = "none"
|
||||
f.Gidnum = p.NOUID
|
||||
f.Gidnum = NOUID
|
||||
}
|
||||
|
||||
f.Muid = ""
|
||||
f.Muidnum = p.NOUID
|
||||
f.Muidnum = NOUID
|
||||
f.Ext = ""
|
||||
|
||||
if dir != nil {
|
||||
|
@ -180,12 +180,12 @@ func (f *File) Add(dir *File, name string, uid p.User, gid p.Group, mode uint32,
|
|||
f.Parent = f
|
||||
}
|
||||
|
||||
f.Ops = ops
|
||||
f.ops = ops
|
||||
return nil
|
||||
}
|
||||
|
||||
// Removes a file from its parent directory.
|
||||
func (f *File) Remove() {
|
||||
func (f *srvFile) Remove() {
|
||||
f.Lock()
|
||||
if (f.flags & Fremoved) != 0 {
|
||||
f.Unlock()
|
||||
|
@ -214,7 +214,7 @@ func (f *File) Remove() {
|
|||
p.Unlock()
|
||||
}
|
||||
|
||||
func (f *File) Rename(name string) error {
|
||||
func (f *srvFile) Rename(name string) error {
|
||||
p := f.Parent
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
@ -229,8 +229,8 @@ func (f *File) Rename(name string) error {
|
|||
}
|
||||
|
||||
// Looks for a file in a directory. Returns nil if the file is not found.
|
||||
func (p *File) Find(name string) *File {
|
||||
var f *File
|
||||
func (p *srvFile) Find(name string) *srvFile {
|
||||
var f *srvFile
|
||||
|
||||
p.Lock()
|
||||
for f = p.cfirst; f != nil; f = f.next {
|
||||
|
@ -244,8 +244,8 @@ func (p *File) Find(name string) *File {
|
|||
|
||||
// Checks if the specified user has permission to perform
|
||||
// certain operation on a file. Perm contains one or more
|
||||
// of p.DMREAD, p.DMWRITE, and p.DMEXEC.
|
||||
func (f *File) CheckPerm(user p.User, perm uint32) bool {
|
||||
// of DMREAD, DMWRITE, and DMEXEC.
|
||||
func (f *srvFile) CheckPerm(user User, perm uint32) bool {
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ func (f *File) CheckPerm(user p.User, perm uint32) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *Fsrv) Attach(req *Req) {
|
||||
func (s *Fsrv) Attach(req *SrvReq) {
|
||||
fid := new(FFid)
|
||||
fid.F = s.Root
|
||||
fid.Fid = req.Fid
|
||||
|
@ -293,7 +293,7 @@ func (s *Fsrv) Attach(req *Req) {
|
|||
req.RespondRattach(&s.Root.Qid)
|
||||
}
|
||||
|
||||
func (*Fsrv) Walk(req *Req) {
|
||||
func (*Fsrv) Walk(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
tc := req.Tc
|
||||
|
||||
|
@ -304,7 +304,7 @@ func (*Fsrv) Walk(req *Req) {
|
|||
}
|
||||
|
||||
nfid := req.Newfid.Aux.(*FFid)
|
||||
wqids := make([]p.Qid, len(tc.Wname))
|
||||
wqids := make([]Qid, len(tc.Wname))
|
||||
i := 0
|
||||
f := fid.F
|
||||
for ; i < len(tc.Wname); i++ {
|
||||
|
@ -314,8 +314,8 @@ func (*Fsrv) Walk(req *Req) {
|
|||
wqids[i] = f.Qid
|
||||
continue
|
||||
}
|
||||
if (wqids[i].Type & p.QTDIR) > 0 {
|
||||
if !f.CheckPerm(req.Fid.User, p.DMEXEC) {
|
||||
if (wqids[i].Type & QTDIR) > 0 {
|
||||
if !f.CheckPerm(req.Fid.User, DMEXEC) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -342,22 +342,22 @@ func mode2Perm(mode uint8) uint32 {
|
|||
var perm uint32 = 0
|
||||
|
||||
switch mode & 3 {
|
||||
case p.OREAD:
|
||||
perm = p.DMREAD
|
||||
case p.OWRITE:
|
||||
perm = p.DMWRITE
|
||||
case p.ORDWR:
|
||||
perm = p.DMREAD | p.DMWRITE
|
||||
case OREAD:
|
||||
perm = DMREAD
|
||||
case OWRITE:
|
||||
perm = DMWRITE
|
||||
case ORDWR:
|
||||
perm = DMREAD | DMWRITE
|
||||
}
|
||||
|
||||
if (mode & p.OTRUNC) != 0 {
|
||||
perm |= p.DMWRITE
|
||||
if (mode & OTRUNC) != 0 {
|
||||
perm |= DMWRITE
|
||||
}
|
||||
|
||||
return perm
|
||||
}
|
||||
|
||||
func (*Fsrv) Open(req *Req) {
|
||||
func (*Fsrv) Open(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
tc := req.Tc
|
||||
|
||||
|
@ -366,7 +366,7 @@ func (*Fsrv) Open(req *Req) {
|
|||
return
|
||||
}
|
||||
|
||||
if op, ok := (fid.F.Ops).(FOpenOp); ok {
|
||||
if op, ok := (fid.F.ops).(FOpenOp); ok {
|
||||
err := op.Open(fid, tc.Mode)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -376,17 +376,17 @@ func (*Fsrv) Open(req *Req) {
|
|||
req.RespondRopen(&fid.F.Qid, 0)
|
||||
}
|
||||
|
||||
func (*Fsrv) Create(req *Req) {
|
||||
func (*Fsrv) Create(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
tc := req.Tc
|
||||
|
||||
dir := fid.F
|
||||
if !dir.CheckPerm(req.Fid.User, p.DMWRITE) {
|
||||
if !dir.CheckPerm(req.Fid.User, DMWRITE) {
|
||||
req.RespondError(Eperm)
|
||||
return
|
||||
}
|
||||
|
||||
if cop, ok := (dir.Ops).(FCreateOp); ok {
|
||||
if cop, ok := (dir.ops).(FCreateOp); ok {
|
||||
f, err := cop.Create(fid, tc.Name, tc.Perm)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -399,55 +399,48 @@ func (*Fsrv) Create(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (*Fsrv) Read(req *Req) {
|
||||
var i, n int
|
||||
func (*Fsrv) Read(req *SrvReq) {
|
||||
var n int
|
||||
var err error
|
||||
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
f := fid.F
|
||||
tc := req.Tc
|
||||
rc := req.Rc
|
||||
p.InitRread(rc, tc.Count)
|
||||
InitRread(rc, tc.Count)
|
||||
|
||||
if f.Mode&p.DMDIR != 0 {
|
||||
// directory
|
||||
if f.Mode&DMDIR != 0 {
|
||||
// Get all the directory entries and
|
||||
// serialize them all into an output buffer.
|
||||
// This greatly simplifies the directory read.
|
||||
if tc.Offset == 0 {
|
||||
var g *File
|
||||
var g *srvFile
|
||||
fid.dirents = nil
|
||||
f.Lock()
|
||||
for n, g = 0, f.cfirst; g != nil; n, g = n+1, g.next {
|
||||
}
|
||||
|
||||
fid.dirs = make([]*File, n)
|
||||
fid.dirs = make([]*srvFile, n)
|
||||
for n, g = 0, f.cfirst; g != nil; n, g = n+1, g.next {
|
||||
fid.dirs[n] = g
|
||||
fid.dirents = append(fid.dirents,
|
||||
PackDir(&g.Dir, req.Conn.Dotu)...)
|
||||
}
|
||||
f.Unlock()
|
||||
}
|
||||
|
||||
n = 0
|
||||
b := rc.Data
|
||||
for i = 0; i < len(fid.dirs); i++ {
|
||||
g := fid.dirs[i]
|
||||
g.Lock()
|
||||
if (g.flags & Fremoved) != 0 {
|
||||
g.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
sz := p.PackDir(&g.Dir, b, req.Conn.Dotu)
|
||||
g.Unlock()
|
||||
if sz == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
b = b[sz:]
|
||||
n += sz
|
||||
switch {
|
||||
case tc.Offset > uint64(len(fid.dirents)):
|
||||
n = 0
|
||||
case len(fid.dirents[tc.Offset:]) > int(tc.Size):
|
||||
n = int(tc.Size)
|
||||
default:
|
||||
n = len(fid.dirents[tc.Offset:])
|
||||
}
|
||||
copy(rc.Data, fid.dirents[tc.Offset:int(tc.Offset)+1+n])
|
||||
|
||||
fid.dirs = fid.dirs[i:]
|
||||
} else {
|
||||
// file
|
||||
if rop, ok := f.Ops.(FReadOp); ok {
|
||||
if rop, ok := f.ops.(FReadOp); ok {
|
||||
n, err = rop.Read(fid, rc.Data, tc.Offset)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -459,16 +452,16 @@ func (*Fsrv) Read(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
p.SetRreadCount(rc, uint32(n))
|
||||
SetRreadCount(rc, uint32(n))
|
||||
req.Respond()
|
||||
}
|
||||
|
||||
func (*Fsrv) Write(req *Req) {
|
||||
func (*Fsrv) Write(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
f := fid.F
|
||||
tc := req.Tc
|
||||
|
||||
if wop, ok := (f.Ops).(FWriteOp); ok {
|
||||
if wop, ok := (f.ops).(FWriteOp); ok {
|
||||
n, err := wop.Write(fid, tc.Data, tc.Offset)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -481,10 +474,10 @@ func (*Fsrv) Write(req *Req) {
|
|||
|
||||
}
|
||||
|
||||
func (*Fsrv) Clunk(req *Req) {
|
||||
func (*Fsrv) Clunk(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
|
||||
if op, ok := (fid.F.Ops).(FClunkOp); ok {
|
||||
if op, ok := (fid.F.ops).(FClunkOp); ok {
|
||||
err := op.Clunk(fid)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -493,7 +486,7 @@ func (*Fsrv) Clunk(req *Req) {
|
|||
req.RespondRclunk()
|
||||
}
|
||||
|
||||
func (*Fsrv) Remove(req *Req) {
|
||||
func (*Fsrv) Remove(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
f := fid.F
|
||||
f.Lock()
|
||||
|
@ -504,7 +497,7 @@ func (*Fsrv) Remove(req *Req) {
|
|||
}
|
||||
f.Unlock()
|
||||
|
||||
if rop, ok := (f.Ops).(FRemoveOp); ok {
|
||||
if rop, ok := (f.ops).(FRemoveOp); ok {
|
||||
err := rop.Remove(fid)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -518,11 +511,11 @@ func (*Fsrv) Remove(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (*Fsrv) Stat(req *Req) {
|
||||
func (*Fsrv) Stat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
f := fid.F
|
||||
|
||||
if sop, ok := (f.Ops).(FStatOp); ok {
|
||||
if sop, ok := (f.ops).(FStatOp); ok {
|
||||
err := sop.Stat(fid)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -534,12 +527,12 @@ func (*Fsrv) Stat(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (*Fsrv) Wstat(req *Req) {
|
||||
func (*Fsrv) Wstat(req *SrvReq) {
|
||||
tc := req.Tc
|
||||
fid := req.Fid.Aux.(*FFid)
|
||||
f := fid.F
|
||||
|
||||
if wop, ok := (f.Ops).(FWstatOp); ok {
|
||||
if wop, ok := (f.ops).(FWstatOp); ok {
|
||||
err := wop.Wstat(fid, &tc.Dir)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -551,7 +544,7 @@ func (*Fsrv) Wstat(req *Req) {
|
|||
}
|
||||
}
|
||||
|
||||
func (*Fsrv) FidDestroy(ffid *Fid) {
|
||||
func (*Fsrv) FidDestroy(ffid *SrvFid) {
|
||||
if ffid.Aux == nil {
|
||||
return
|
||||
}
|
||||
|
@ -562,7 +555,7 @@ func (*Fsrv) FidDestroy(ffid *Fid) {
|
|||
return // otherwise errs in bad walks
|
||||
}
|
||||
|
||||
if op, ok := (f.Ops).(FDestroyOp); ok {
|
||||
if op, ok := (f.ops).(FDestroyOp); ok {
|
||||
op.FidDestroy(fid)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type pipeFid struct {
|
||||
path string
|
||||
file *os.File
|
||||
dirs []os.FileInfo
|
||||
dirents []byte
|
||||
diroffset uint64
|
||||
st os.FileInfo
|
||||
data []uint8
|
||||
eof bool
|
||||
}
|
||||
|
||||
type Pipefs struct {
|
||||
Srv
|
||||
Root string
|
||||
}
|
||||
|
||||
func (fid *pipeFid) stat() *Error {
|
||||
var err error
|
||||
|
||||
fid.st, err = os.Lstat(fid.path)
|
||||
if err != nil {
|
||||
return toError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Dir is an instantiation of the p.Dir structure
|
||||
// that can act as a receiver for local methods.
|
||||
type pipeDir struct {
|
||||
Dir
|
||||
}
|
||||
|
||||
func (*Pipefs) ConnOpened(conn *Conn) {
|
||||
if conn.Srv.Debuglevel > 0 {
|
||||
log.Println("connected")
|
||||
}
|
||||
}
|
||||
|
||||
func (*Pipefs) ConnClosed(conn *Conn) {
|
||||
if conn.Srv.Debuglevel > 0 {
|
||||
log.Println("disconnected")
|
||||
}
|
||||
}
|
||||
|
||||
func (*Pipefs) FidDestroy(sfid *SrvFid) {
|
||||
var fid *pipeFid
|
||||
|
||||
if sfid.Aux == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fid = sfid.Aux.(*pipeFid)
|
||||
if fid.file != nil {
|
||||
fid.file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (pipe *Pipefs) Attach(req *SrvReq) {
|
||||
if req.Afid != nil {
|
||||
req.RespondError(Enoauth)
|
||||
return
|
||||
}
|
||||
|
||||
tc := req.Tc
|
||||
fid := new(pipeFid)
|
||||
if len(tc.Aname) == 0 {
|
||||
fid.path = pipe.Root
|
||||
} else {
|
||||
fid.path = tc.Aname
|
||||
}
|
||||
|
||||
req.Fid.Aux = fid
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
qid := dir2Qid(fid.st)
|
||||
req.RespondRattach(qid)
|
||||
}
|
||||
|
||||
func (*Pipefs) Flush(req *SrvReq) {}
|
||||
|
||||
func (*Pipefs) Walk(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
tc := req.Tc
|
||||
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Newfid.Aux == nil {
|
||||
req.Newfid.Aux = new(pipeFid)
|
||||
}
|
||||
|
||||
nfid := req.Newfid.Aux.(*pipeFid)
|
||||
wqids := make([]Qid, len(tc.Wname))
|
||||
path := fid.path
|
||||
i := 0
|
||||
for ; i < len(tc.Wname); i++ {
|
||||
p := path + "/" + tc.Wname[i]
|
||||
st, err := os.Lstat(p)
|
||||
if err != nil {
|
||||
if i == 0 {
|
||||
req.RespondError(Enoent)
|
||||
return
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
wqids[i] = *dir2Qid(st)
|
||||
path = p
|
||||
}
|
||||
|
||||
nfid.path = path
|
||||
req.RespondRwalk(wqids[0:i])
|
||||
}
|
||||
|
||||
func (*Pipefs) Open(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
var e error
|
||||
fid.file, e = os.OpenFile(fid.path, omode2uflags(tc.Mode), 0)
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
req.RespondRopen(dir2Qid(fid.st), 0)
|
||||
}
|
||||
|
||||
func (*Pipefs) Create(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
path := fid.path + "/" + tc.Name
|
||||
var e error = nil
|
||||
var file *os.File = nil
|
||||
switch {
|
||||
case tc.Perm&DMDIR != 0:
|
||||
e = os.Mkdir(path, os.FileMode(tc.Perm&0777))
|
||||
|
||||
case tc.Perm&DMSYMLINK != 0:
|
||||
e = os.Symlink(tc.Ext, path)
|
||||
|
||||
case tc.Perm&DMLINK != 0:
|
||||
n, e := strconv.ParseUint(tc.Ext, 10, 0)
|
||||
if e != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ofid := req.Conn.FidGet(uint32(n))
|
||||
if ofid == nil {
|
||||
req.RespondError(Eunknownfid)
|
||||
return
|
||||
}
|
||||
|
||||
e = os.Link(ofid.Aux.(*pipeFid).path, path)
|
||||
ofid.DecRef()
|
||||
|
||||
case tc.Perm&DMNAMEDPIPE != 0:
|
||||
case tc.Perm&DMDEVICE != 0:
|
||||
req.RespondError(&Error{"not implemented", EIO})
|
||||
return
|
||||
|
||||
default:
|
||||
var mode uint32 = tc.Perm & 0777
|
||||
if req.Conn.Dotu {
|
||||
if tc.Perm&DMSETUID > 0 {
|
||||
mode |= syscall.S_ISUID
|
||||
}
|
||||
if tc.Perm&DMSETGID > 0 {
|
||||
mode |= syscall.S_ISGID
|
||||
}
|
||||
}
|
||||
file, e = os.OpenFile(path, omode2uflags(tc.Mode)|os.O_CREATE, os.FileMode(mode))
|
||||
}
|
||||
|
||||
if file == nil && e == nil {
|
||||
file, e = os.OpenFile(path, omode2uflags(tc.Mode), 0)
|
||||
}
|
||||
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
fid.path = path
|
||||
fid.file = file
|
||||
err = fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
req.RespondRcreate(dir2Qid(fid.st), 0)
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (*Pipefs) Read(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
tc := req.Tc
|
||||
rc := req.Rc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
InitRread(rc, tc.Count)
|
||||
var count int
|
||||
var e error
|
||||
if fid.st.IsDir() {
|
||||
if tc.Offset == 0 {
|
||||
var e error
|
||||
// If we got here, it was open. Can't really seek
|
||||
// in most cases, just close and reopen it.
|
||||
fid.file.Close()
|
||||
if fid.file, e = os.OpenFile(fid.path, omode2uflags(req.Fid.Omode), 0); e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
if fid.dirs, e = fid.file.Readdir(-1); e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
fid.dirents = nil
|
||||
|
||||
for i := 0; i < len(fid.dirs); i++ {
|
||||
path := fid.path + "/" + fid.dirs[i].Name()
|
||||
st, _ := dir2Dir(path, fid.dirs[i], req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
if st == nil {
|
||||
continue
|
||||
}
|
||||
b := PackDir(st, req.Conn.Dotu)
|
||||
fid.dirents = append(fid.dirents, b...)
|
||||
count += len(b)
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case tc.Offset > uint64(len(fid.dirents)):
|
||||
count = 0
|
||||
case len(fid.dirents[tc.Offset:]) > int(tc.Count):
|
||||
count = int(tc.Count)
|
||||
default:
|
||||
count = len(fid.dirents[tc.Offset:])
|
||||
}
|
||||
|
||||
copy(rc.Data, fid.dirents[tc.Offset:int(tc.Offset)+count])
|
||||
|
||||
} else {
|
||||
if fid.eof {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
length := min(len(rc.Data), len(fid.data))
|
||||
count = length
|
||||
copy(rc.Data, fid.data[:length])
|
||||
fid.data = fid.data[length:]
|
||||
}
|
||||
|
||||
SetRreadCount(rc, uint32(count))
|
||||
req.Respond()
|
||||
}
|
||||
|
||||
func (*Pipefs) Write(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
fid.data = append(fid.data, tc.Data...)
|
||||
|
||||
req.RespondRwrite(uint32(len(tc.Data)))
|
||||
}
|
||||
|
||||
func (*Pipefs) Clunk(req *SrvReq) { req.RespondRclunk() }
|
||||
|
||||
func (*Pipefs) Remove(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
e := os.Remove(fid.path)
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
req.RespondRremove()
|
||||
}
|
||||
|
||||
func (*Pipefs) Stat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*pipeFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
st, derr := dir2Dir(fid.path, fid.st, req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
if st == nil {
|
||||
req.RespondError(derr)
|
||||
return
|
||||
}
|
||||
|
||||
req.RespondRstat(st)
|
||||
}
|
||||
|
||||
func (*Pipefs) Wstat(req *SrvReq) {
|
||||
req.RespondError(Eperm)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (dir *pipeDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Stat_t) {
|
||||
u := upool.Uid2User(int(sysMode.Uid))
|
||||
g := upool.Gid2Group(int(sysMode.Gid))
|
||||
dir.Uid = u.Name()
|
||||
if dir.Uid == "" {
|
||||
dir.Uid = "none"
|
||||
}
|
||||
|
||||
dir.Gid = g.Name()
|
||||
if dir.Gid == "" {
|
||||
dir.Gid = "none"
|
||||
}
|
||||
dir.Muid = "none"
|
||||
dir.Ext = ""
|
||||
dir.Uidnum = uint32(u.Id())
|
||||
dir.Gidnum = uint32(g.Id())
|
||||
dir.Muidnum = NOUID
|
||||
if d.Mode()&os.ModeSymlink != 0 {
|
||||
var err error
|
||||
dir.Ext, err = os.Readlink(path)
|
||||
if err != nil {
|
||||
dir.Ext = ""
|
||||
}
|
||||
} else if isBlock(d) {
|
||||
dir.Ext = fmt.Sprintf("b %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
} else if isChar(d) {
|
||||
dir.Ext = fmt.Sprintf("c %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (dir *pipeDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Stat_t) {
|
||||
u := upool.Uid2User(int(sysMode.Uid))
|
||||
g := upool.Gid2Group(int(sysMode.Gid))
|
||||
dir.Uid = u.Name()
|
||||
if dir.Uid == "" {
|
||||
dir.Uid = "none"
|
||||
}
|
||||
|
||||
dir.Gid = g.Name()
|
||||
if dir.Gid == "" {
|
||||
dir.Gid = "none"
|
||||
}
|
||||
dir.Muid = "none"
|
||||
dir.Ext = ""
|
||||
dir.Uidnum = uint32(u.Id())
|
||||
dir.Gidnum = uint32(g.Id())
|
||||
dir.Muidnum = NOUID
|
||||
if d.Mode()&os.ModeSymlink != 0 {
|
||||
var err error
|
||||
dir.Ext, err = os.Readlink(path)
|
||||
if err != nil {
|
||||
dir.Ext = ""
|
||||
}
|
||||
} else if isBlock(d) {
|
||||
dir.Ext = fmt.Sprintf("b %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
} else if isChar(d) {
|
||||
dir.Ext = fmt.Sprintf("c %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (dir *pipeDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Win32FileAttributeData) {
|
||||
// u := upool.Uid2User(int(sysMode.Uid))
|
||||
// g := upool.Gid2Group(int(sysMode.Gid))
|
||||
// dir.Uid = u.Name()
|
||||
// if dir.Uid == "" {
|
||||
// dir.Uid = "none"
|
||||
// }
|
||||
|
||||
// dir.Gid = g.Name()
|
||||
// if dir.Gid == "" {
|
||||
// dir.Gid = "none"
|
||||
// }
|
||||
// dir.Muid = "none"
|
||||
// dir.Ext = ""
|
||||
// dir.Uidnum = uint32(u.Id())
|
||||
// dir.Gidnum = uint32(g.Id())
|
||||
// dir.Muidnum = NOUID
|
||||
// if d.Mode()&os.ModeSymlink != 0 {
|
||||
// var err error
|
||||
// dir.Ext, err = os.Readlink(path)
|
||||
// if err != nil {
|
||||
// dir.Ext = ""
|
||||
// }
|
||||
// } else if isBlock(d) {
|
||||
// dir.Ext = fmt.Sprintf("b %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
// } else if isChar(d) {
|
||||
// dir.Ext = fmt.Sprintf("c %d %d", sysMode.Rdev>>24, sysMode.Rdev&0xFFFFFF)
|
||||
// }
|
||||
|
||||
dir.Uid = "none"
|
||||
dir.Gid = "none"
|
||||
dir.Muid = "none"
|
||||
dir.Uidnum = 0
|
||||
dir.Gidnum = 0
|
||||
dir.Muidnum = NOUID
|
||||
dir.Ext = ""
|
||||
}
|
|
@ -2,28 +2,42 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import "fmt"
|
||||
import "k8s.io/minikube/third_party/go9p/p"
|
||||
|
||||
// SrvRequest operations. This interface should be implemented by all file servers.
|
||||
// The operations correspond directly to most of the 9P2000 message types.
|
||||
type SrvReqOps interface {
|
||||
Attach(*SrvReq)
|
||||
Walk(*SrvReq)
|
||||
Open(*SrvReq)
|
||||
Create(*SrvReq)
|
||||
Read(*SrvReq)
|
||||
Write(*SrvReq)
|
||||
Clunk(*SrvReq)
|
||||
Remove(*SrvReq)
|
||||
Stat(*SrvReq)
|
||||
Wstat(*SrvReq)
|
||||
}
|
||||
|
||||
// Respond to the request with Rerror message
|
||||
func (req *Req) RespondError(err interface{}) {
|
||||
func (req *SrvReq) RespondError(err interface{}) {
|
||||
switch e := err.(type) {
|
||||
case *p.Error:
|
||||
p.PackRerror(req.Rc, e.Error(), uint32(e.Errornum), req.Conn.Dotu)
|
||||
case *Error:
|
||||
PackRerror(req.Rc, e.Error(), uint32(e.Errornum), req.Conn.Dotu)
|
||||
case error:
|
||||
p.PackRerror(req.Rc, e.Error(), uint32(p.EIO), req.Conn.Dotu)
|
||||
PackRerror(req.Rc, e.Error(), uint32(EIO), req.Conn.Dotu)
|
||||
default:
|
||||
p.PackRerror(req.Rc, fmt.Sprintf("%v", e), uint32(p.EIO), req.Conn.Dotu)
|
||||
PackRerror(req.Rc, fmt.Sprintf("%v", e), uint32(EIO), req.Conn.Dotu)
|
||||
}
|
||||
|
||||
req.Respond()
|
||||
}
|
||||
|
||||
// Respond to the request with Rversion message
|
||||
func (req *Req) RespondRversion(msize uint32, version string) {
|
||||
err := p.PackRversion(req.Rc, msize, version)
|
||||
func (req *SrvReq) RespondRversion(msize uint32, version string) {
|
||||
err := PackRversion(req.Rc, msize, version)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -32,8 +46,8 @@ func (req *Req) RespondRversion(msize uint32, version string) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rauth message
|
||||
func (req *Req) RespondRauth(aqid *p.Qid) {
|
||||
err := p.PackRauth(req.Rc, aqid)
|
||||
func (req *SrvReq) RespondRauth(aqid *Qid) {
|
||||
err := PackRauth(req.Rc, aqid)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -42,8 +56,8 @@ func (req *Req) RespondRauth(aqid *p.Qid) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rflush message
|
||||
func (req *Req) RespondRflush() {
|
||||
err := p.PackRflush(req.Rc)
|
||||
func (req *SrvReq) RespondRflush() {
|
||||
err := PackRflush(req.Rc)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -52,8 +66,8 @@ func (req *Req) RespondRflush() {
|
|||
}
|
||||
|
||||
// Respond to the request with Rattach message
|
||||
func (req *Req) RespondRattach(aqid *p.Qid) {
|
||||
err := p.PackRattach(req.Rc, aqid)
|
||||
func (req *SrvReq) RespondRattach(aqid *Qid) {
|
||||
err := PackRattach(req.Rc, aqid)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -62,8 +76,8 @@ func (req *Req) RespondRattach(aqid *p.Qid) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rwalk message
|
||||
func (req *Req) RespondRwalk(wqids []p.Qid) {
|
||||
err := p.PackRwalk(req.Rc, wqids)
|
||||
func (req *SrvReq) RespondRwalk(wqids []Qid) {
|
||||
err := PackRwalk(req.Rc, wqids)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -72,8 +86,8 @@ func (req *Req) RespondRwalk(wqids []p.Qid) {
|
|||
}
|
||||
|
||||
// Respond to the request with Ropen message
|
||||
func (req *Req) RespondRopen(qid *p.Qid, iounit uint32) {
|
||||
err := p.PackRopen(req.Rc, qid, iounit)
|
||||
func (req *SrvReq) RespondRopen(qid *Qid, iounit uint32) {
|
||||
err := PackRopen(req.Rc, qid, iounit)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -82,8 +96,8 @@ func (req *Req) RespondRopen(qid *p.Qid, iounit uint32) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rcreate message
|
||||
func (req *Req) RespondRcreate(qid *p.Qid, iounit uint32) {
|
||||
err := p.PackRcreate(req.Rc, qid, iounit)
|
||||
func (req *SrvReq) RespondRcreate(qid *Qid, iounit uint32) {
|
||||
err := PackRcreate(req.Rc, qid, iounit)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -92,8 +106,8 @@ func (req *Req) RespondRcreate(qid *p.Qid, iounit uint32) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rread message
|
||||
func (req *Req) RespondRread(data []byte) {
|
||||
err := p.PackRread(req.Rc, data)
|
||||
func (req *SrvReq) RespondRread(data []byte) {
|
||||
err := PackRread(req.Rc, data)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -102,8 +116,8 @@ func (req *Req) RespondRread(data []byte) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rwrite message
|
||||
func (req *Req) RespondRwrite(count uint32) {
|
||||
err := p.PackRwrite(req.Rc, count)
|
||||
func (req *SrvReq) RespondRwrite(count uint32) {
|
||||
err := PackRwrite(req.Rc, count)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -112,8 +126,8 @@ func (req *Req) RespondRwrite(count uint32) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rclunk message
|
||||
func (req *Req) RespondRclunk() {
|
||||
err := p.PackRclunk(req.Rc)
|
||||
func (req *SrvReq) RespondRclunk() {
|
||||
err := PackRclunk(req.Rc)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -122,8 +136,8 @@ func (req *Req) RespondRclunk() {
|
|||
}
|
||||
|
||||
// Respond to the request with Rremove message
|
||||
func (req *Req) RespondRremove() {
|
||||
err := p.PackRremove(req.Rc)
|
||||
func (req *SrvReq) RespondRremove() {
|
||||
err := PackRremove(req.Rc)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -132,8 +146,8 @@ func (req *Req) RespondRremove() {
|
|||
}
|
||||
|
||||
// Respond to the request with Rstat message
|
||||
func (req *Req) RespondRstat(st *p.Dir) {
|
||||
err := p.PackRstat(req.Rc, st, req.Conn.Dotu)
|
||||
func (req *SrvReq) RespondRstat(st *Dir) {
|
||||
err := PackRstat(req.Rc, st, req.Conn.Dotu)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
||||
|
@ -142,8 +156,8 @@ func (req *Req) RespondRstat(st *p.Dir) {
|
|||
}
|
||||
|
||||
// Respond to the request with Rwstat message
|
||||
func (req *Req) RespondRwstat() {
|
||||
err := p.PackRwstat(req.Rc)
|
||||
func (req *SrvReq) RespondRwstat() {
|
||||
err := PackRwstat(req.Rc)
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
} else {
|
|
@ -2,12 +2,11 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The srv package provides definitions and functions used to implement
|
||||
// The srv package go9provides definitions and functions used to implement
|
||||
// a 9P2000 file server.
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
@ -22,26 +21,18 @@ const (
|
|||
reqSaved /* no response was produced after the request is worked on */
|
||||
)
|
||||
|
||||
// Debug flags
|
||||
const (
|
||||
DbgPrintFcalls = (1 << iota) // print all 9P messages on stderr
|
||||
DbgPrintPackets // print the raw packets on stderr
|
||||
DbgLogFcalls // keep the last N 9P messages (can be accessed over http)
|
||||
DbgLogPackets // keep the last N 9P messages (can be accessed over http)
|
||||
)
|
||||
|
||||
var Eunknownfid error = &p.Error{"unknown fid", p.EINVAL}
|
||||
var Enoauth error = &p.Error{"no authentication required", p.EINVAL}
|
||||
var Einuse error = &p.Error{"fid already in use", p.EINVAL}
|
||||
var Ebaduse error = &p.Error{"bad use of fid", p.EINVAL}
|
||||
var Eopen error = &p.Error{"fid already opened", p.EINVAL}
|
||||
var Enotdir error = &p.Error{"not a directory", p.ENOTDIR}
|
||||
var Eperm error = &p.Error{"permission denied", p.EPERM}
|
||||
var Etoolarge error = &p.Error{"i/o count too large", p.EINVAL}
|
||||
var Ebadoffset error = &p.Error{"bad offset in directory read", p.EINVAL}
|
||||
var Edirchange error = &p.Error{"cannot convert between files and directories", p.EINVAL}
|
||||
var Enouser error = &p.Error{"unknown user", p.EINVAL}
|
||||
var Enotimpl error = &p.Error{"not implemented", p.EINVAL}
|
||||
var Eunknownfid error = &Error{"unknown fid", EINVAL}
|
||||
var Enoauth error = &Error{"no authentication required", EINVAL}
|
||||
var Einuse error = &Error{"fid already in use", EINVAL}
|
||||
var Ebaduse error = &Error{"bad use of fid", EINVAL}
|
||||
var Eopen error = &Error{"fid already opened", EINVAL}
|
||||
var Enotdir error = &Error{"not a directory", ENOTDIR}
|
||||
var Eperm error = &Error{"permission denied", EPERM}
|
||||
var Etoolarge error = &Error{"i/o count too large", EINVAL}
|
||||
var Ebadoffset error = &Error{"bad offset in directory read", EINVAL}
|
||||
var Edirchange error = &Error{"cannot convert between files and directories", EINVAL}
|
||||
var Enouser error = &Error{"unknown user", EINVAL}
|
||||
var Enotimpl error = &Error{"not implemented", EINVAL}
|
||||
|
||||
// Authentication operations. The file server should implement them if
|
||||
// it requires user authentication. The authentication in 9P2000 is
|
||||
|
@ -50,28 +41,28 @@ var Enotimpl error = &p.Error{"not implemented", p.EINVAL}
|
|||
// fid can be used by the user to get access to the actual files.
|
||||
type AuthOps interface {
|
||||
// AuthInit is called when the user starts the authentication
|
||||
// process on Fid afid. The user that is being authenticated
|
||||
// process on SrvFid afid. The user that is being authenticated
|
||||
// is referred by afid.User. The function should return the Qid
|
||||
// for the authentication file, or an Error if the user can't be
|
||||
// authenticated
|
||||
AuthInit(afid *Fid, aname string) (*p.Qid, error)
|
||||
AuthInit(afid *SrvFid, aname string) (*Qid, error)
|
||||
|
||||
// AuthDestroy is called when an authentication fid is destroyed.
|
||||
AuthDestroy(afid *Fid)
|
||||
AuthDestroy(afid *SrvFid)
|
||||
|
||||
// AuthCheck is called after the authentication process is finished
|
||||
// when the user tries to attach to the file server. If the function
|
||||
// returns nil, the authentication was successful and the user has
|
||||
// permission to access the files.
|
||||
AuthCheck(fid *Fid, afid *Fid, aname string) error
|
||||
AuthCheck(fid *SrvFid, afid *SrvFid, aname string) error
|
||||
|
||||
// AuthRead is called when the user attempts to read data from an
|
||||
// authentication fid.
|
||||
AuthRead(afid *Fid, offset uint64, data []byte) (count int, err error)
|
||||
AuthRead(afid *SrvFid, offset uint64, data []byte) (count int, err error)
|
||||
|
||||
// AuthWrite is called when the user attempts to write data to an
|
||||
// authentication fid.
|
||||
AuthWrite(afid *Fid, offset uint64, data []byte) (count int, err error)
|
||||
AuthWrite(afid *SrvFid, offset uint64, data []byte) (count int, err error)
|
||||
}
|
||||
|
||||
// Connection operations. These should be implemented if the file server
|
||||
|
@ -81,61 +72,41 @@ type ConnOps interface {
|
|||
ConnClosed(*Conn)
|
||||
}
|
||||
|
||||
// Fid operations. This interface should be implemented if the file server
|
||||
// needs to be called when a Fid is destroyed.
|
||||
type FidOps interface {
|
||||
FidDestroy(*Fid)
|
||||
// SrvFid operations. This interface should be implemented if the file server
|
||||
// needs to be called when a SrvFid is destroyed.
|
||||
type SrvFidOps interface {
|
||||
FidDestroy(*SrvFid)
|
||||
}
|
||||
|
||||
// Request operations. This interface should be implemented if the file server
|
||||
// needs to bypass the default request process, or needs to perform certain
|
||||
// operations before the (any) request is processed, or before (any) response
|
||||
// sent back to the client.
|
||||
type ReqProcessOps interface {
|
||||
type SrvReqProcessOps interface {
|
||||
// Called when a new request is received from the client. If the
|
||||
// interface is not implemented, (req *Req) srv.Process() method is
|
||||
// interface is not implemented, (req *SrvReq) srv.Process() method is
|
||||
// called. If the interface is implemented, it is the user's
|
||||
// responsibility to call srv.Process. If srv.Process isn't called,
|
||||
// Fid, Afid and Newfid fields in Req are not set, and the ReqOps
|
||||
// SrvFid, Afid and Newfid fields in SrvReq are not set, and the SrvReqOps
|
||||
// methods are not called.
|
||||
ReqProcess(*Req)
|
||||
SrvReqProcess(*SrvReq)
|
||||
|
||||
// Called when a request is responded, i.e. when (req *Req)srv.Respond()
|
||||
// Called when a request is responded, i.e. when (req *SrvReq)srv.Respond()
|
||||
// is called and before the response is sent. If the interface is not
|
||||
// implemented, (req *Req) srv.PostProcess() method is called to finalize
|
||||
// the request. If the interface is implemented and ReqProcess calls
|
||||
// the srv.Process method, ReqRespond should call the srv.PostProcess
|
||||
// implemented, (req *SrvReq) srv.PostProcess() method is called to finalize
|
||||
// the request. If the interface is implemented and SrvReqProcess calls
|
||||
// the srv.Process method, SrvReqRespond should call the srv.PostProcess
|
||||
// method.
|
||||
ReqRespond(*Req)
|
||||
SrvReqRespond(*SrvReq)
|
||||
}
|
||||
|
||||
// Flush operation. This interface should be implemented if the file server
|
||||
// can flush pending requests. If the interface is not implemented, requests
|
||||
// that were passed to the file server implementation won't be flushed.
|
||||
// The flush method should call the (req *Req) srv.Flush() method if the flush
|
||||
// The flush method should call the (req *SrvReq) srv.Flush() method if the flush
|
||||
// was successful so the request can be marked appropriately.
|
||||
type FlushOp interface {
|
||||
Flush(*Req)
|
||||
}
|
||||
|
||||
// Request operations. This interface should be implemented by all file servers.
|
||||
// The operations correspond directly to most of the 9P2000 message types.
|
||||
type ReqOps interface {
|
||||
Attach(*Req)
|
||||
Walk(*Req)
|
||||
Open(*Req)
|
||||
Create(*Req)
|
||||
Read(*Req)
|
||||
Write(*Req)
|
||||
Clunk(*Req)
|
||||
Remove(*Req)
|
||||
Stat(*Req)
|
||||
Wstat(*Req)
|
||||
}
|
||||
|
||||
type StatsOps interface {
|
||||
statsRegister()
|
||||
statsUnregister()
|
||||
Flush(*SrvReq)
|
||||
}
|
||||
|
||||
// The Srv type contains the basic fields used to control the 9P2000
|
||||
|
@ -145,13 +116,13 @@ type StatsOps interface {
|
|||
// that implements the file server operations.
|
||||
type Srv struct {
|
||||
sync.Mutex
|
||||
Id string // Used for debugging and stats
|
||||
Msize uint32 // Maximum size of the 9P2000 messages supported by the server
|
||||
Dotu bool // If true, the server supports the 9P2000.u extension
|
||||
Debuglevel int // debug level
|
||||
Upool p.Users // Interface for finding users and groups known to the file server
|
||||
Maxpend int // Maximum pending outgoing requests
|
||||
Log *p.Logger
|
||||
Id string // Used for debugging and stats
|
||||
Msize uint32 // Maximum size of the 9P2000 messages supported by the server
|
||||
Dotu bool // If true, the server supports the 9P2000.u extension
|
||||
Debuglevel int // debug level
|
||||
Upool Users // Interface for finding users and groups known to the file server
|
||||
Maxpend int // Maximum pending outgoing requests
|
||||
Log *Logger
|
||||
|
||||
ops interface{} // operations
|
||||
conns map[*Conn]*Conn // List of connections
|
||||
|
@ -167,11 +138,11 @@ type Conn struct {
|
|||
Debuglevel int
|
||||
|
||||
conn net.Conn
|
||||
fidpool map[uint32]*Fid
|
||||
reqs map[uint16]*Req // all outstanding requests
|
||||
fidpool map[uint32]*SrvFid
|
||||
reqs map[uint16]*SrvReq // all outstanding requests
|
||||
|
||||
reqout chan *Req
|
||||
rchan chan *p.Fcall
|
||||
reqout chan *SrvReq
|
||||
rchan chan *Fcall
|
||||
done chan bool
|
||||
|
||||
// stats
|
||||
|
@ -184,41 +155,42 @@ type Conn struct {
|
|||
nwrites int // number of writes
|
||||
}
|
||||
|
||||
// The Fid type identifies a file on the file server.
|
||||
// A new Fid is created when the user attaches to the file server (the Attach
|
||||
// operation), or when Walk-ing to a file. The Fid values are created
|
||||
// automatically by the srv implementation. The FidDestroy operation is called
|
||||
// when a Fid is destroyed.
|
||||
type Fid struct {
|
||||
// The SrvFid type identifies a file on the file server.
|
||||
// A new SrvFid is created when the user attaches to the file server (the Attach
|
||||
// operation), or when Walk-ing to a file. The SrvFid values are created
|
||||
// automatically by the srv implementation. The SrvFidDestroy operation is called
|
||||
// when a SrvFid is destroyed.
|
||||
type SrvFid struct {
|
||||
sync.Mutex
|
||||
fid uint32
|
||||
refcount int
|
||||
opened bool // True if the Fid is opened
|
||||
Fconn *Conn // Connection the Fid belongs to
|
||||
Omode uint8 // Open mode (p.O* flags), if the fid is opened
|
||||
Type uint8 // Fid type (p.QT* flags)
|
||||
opened bool // True if the SrvFid is opened
|
||||
Fconn *Conn // Connection the SrvFid belongs to
|
||||
Omode uint8 // Open mode (O* flags), if the fid is opened
|
||||
Type uint8 // SrvFid type (QT* flags)
|
||||
Diroffset uint64 // If directory, the next valid read position
|
||||
User p.User // The Fid's user
|
||||
Aux interface{} // Can be used by the file server implementation for per-Fid data
|
||||
Dirents []byte // If directory, the serialized dirents
|
||||
User User // The SrvFid's user
|
||||
Aux interface{} // Can be used by the file server implementation for per-SrvFid data
|
||||
}
|
||||
|
||||
// The Req type represents a 9P2000 request. Each request has a
|
||||
// T-message (Tc) and a R-message (Rc). If the ReqProcessOps don't
|
||||
// override the default behavior, the implementation initializes Fid,
|
||||
// Afid and Newfid values and automatically keeps track on when the Fids
|
||||
// The SrvReq type represents a 9P2000 request. Each request has a
|
||||
// T-message (Tc) and a R-message (Rc). If the SrvReqProcessOps don't
|
||||
// override the default behavior, the implementation initializes SrvFid,
|
||||
// Afid and Newfid values and automatically keeps track on when the SrvFids
|
||||
// should be destroyed.
|
||||
type Req struct {
|
||||
type SrvReq struct {
|
||||
sync.Mutex
|
||||
Tc *p.Fcall // Incoming 9P2000 message
|
||||
Rc *p.Fcall // Outgoing 9P2000 response
|
||||
Fid *Fid // The Fid value for all messages that contain fid[4]
|
||||
Afid *Fid // The Fid value for the messages that contain afid[4] (Tauth and Tattach)
|
||||
Newfid *Fid // The Fid value for the messages that contain newfid[4] (Twalk)
|
||||
Conn *Conn // Connection that the request belongs to
|
||||
Tc *Fcall // Incoming 9P2000 message
|
||||
Rc *Fcall // Outgoing 9P2000 response
|
||||
Fid *SrvFid // The SrvFid value for all messages that contain fid[4]
|
||||
Afid *SrvFid // The SrvFid value for the messages that contain afid[4] (Tauth and Tattach)
|
||||
Newfid *SrvFid // The SrvFid value for the messages that contain newfid[4] (Twalk)
|
||||
Conn *Conn // Connection that the request belongs to
|
||||
|
||||
status reqStatus
|
||||
flushreq *Req
|
||||
prev, next *Req
|
||||
flushreq *SrvReq
|
||||
prev, next *SrvReq
|
||||
}
|
||||
|
||||
// The Start method should be called once the file server implementor
|
||||
|
@ -226,23 +198,23 @@ type Req struct {
|
|||
// values to the fields that are not initialized and creates the goroutines
|
||||
// required for the server's operation. The method receives an empty
|
||||
// interface value, ops, that should implement the interfaces the file server is
|
||||
// interested in. Ops must implement the ReqOps interface.
|
||||
// interested in. Ops must implement the SrvReqOps interface.
|
||||
func (srv *Srv) Start(ops interface{}) bool {
|
||||
if _, ok := (ops).(ReqOps); !ok {
|
||||
if _, ok := (ops).(SrvReqOps); !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
srv.ops = ops
|
||||
if srv.Upool == nil {
|
||||
srv.Upool = p.OsUsers
|
||||
srv.Upool = OsUsers
|
||||
}
|
||||
|
||||
if srv.Msize < p.IOHDRSZ {
|
||||
srv.Msize = p.MSIZE
|
||||
if srv.Msize < IOHDRSZ {
|
||||
srv.Msize = MSIZE
|
||||
}
|
||||
|
||||
if srv.Log == nil {
|
||||
srv.Log = p.NewLogger(1024)
|
||||
srv.Log = NewLogger(1024)
|
||||
}
|
||||
|
||||
if sop, ok := (interface{}(srv)).(StatsOps); ok {
|
||||
|
@ -256,7 +228,7 @@ func (srv *Srv) String() string {
|
|||
return srv.Id
|
||||
}
|
||||
|
||||
func (req *Req) process() {
|
||||
func (req *SrvReq) process() {
|
||||
req.Lock()
|
||||
flushed := (req.status & reqFlush) != 0
|
||||
if !flushed {
|
||||
|
@ -268,8 +240,8 @@ func (req *Req) process() {
|
|||
req.Respond()
|
||||
}
|
||||
|
||||
if rop, ok := (req.Conn.Srv.ops).(ReqProcessOps); ok {
|
||||
rop.ReqProcess(req)
|
||||
if rop, ok := (req.Conn.Srv.ops).(SrvReqProcessOps); ok {
|
||||
rop.SrvReqProcess(req)
|
||||
} else {
|
||||
req.Process()
|
||||
}
|
||||
|
@ -283,16 +255,16 @@ func (req *Req) process() {
|
|||
}
|
||||
|
||||
// Performs the default processing of a request. Initializes
|
||||
// the Fid, Afid and Newfid fields and calls the appropriate
|
||||
// ReqOps operation for the message. The file server implementer
|
||||
// should call it only if the file server implements the ReqProcessOps
|
||||
// within the ReqProcess operation.
|
||||
func (req *Req) Process() {
|
||||
// the SrvFid, Afid and Newfid fields and calls the appropriate
|
||||
// SrvReqOps operation for the message. The file server implementer
|
||||
// should call it only if the file server implements the SrvReqProcessOps
|
||||
// within the SrvReqProcess operation.
|
||||
func (req *SrvReq) Process() {
|
||||
conn := req.Conn
|
||||
srv := conn.Srv
|
||||
tc := req.Tc
|
||||
|
||||
if tc.Fid != p.NOFID && tc.Type != p.Tattach {
|
||||
if tc.Fid != NOFID && tc.Type != Tattach {
|
||||
srv.Lock()
|
||||
req.Fid = conn.FidGet(tc.Fid)
|
||||
srv.Unlock()
|
||||
|
@ -304,83 +276,83 @@ func (req *Req) Process() {
|
|||
|
||||
switch req.Tc.Type {
|
||||
default:
|
||||
req.RespondError(&p.Error{"unknown message type", p.EINVAL})
|
||||
req.RespondError(&Error{"unknown message type", EINVAL})
|
||||
|
||||
case p.Tversion:
|
||||
case Tversion:
|
||||
srv.version(req)
|
||||
|
||||
case p.Tauth:
|
||||
case Tauth:
|
||||
if runtime.GOOS == "windows" {
|
||||
return
|
||||
}
|
||||
srv.auth(req)
|
||||
|
||||
case p.Tattach:
|
||||
case Tattach:
|
||||
srv.attach(req)
|
||||
|
||||
case p.Tflush:
|
||||
case Tflush:
|
||||
srv.flush(req)
|
||||
|
||||
case p.Twalk:
|
||||
case Twalk:
|
||||
srv.walk(req)
|
||||
|
||||
case p.Topen:
|
||||
case Topen:
|
||||
srv.open(req)
|
||||
|
||||
case p.Tcreate:
|
||||
case Tcreate:
|
||||
srv.create(req)
|
||||
|
||||
case p.Tread:
|
||||
case Tread:
|
||||
srv.read(req)
|
||||
|
||||
case p.Twrite:
|
||||
case Twrite:
|
||||
srv.write(req)
|
||||
|
||||
case p.Tclunk:
|
||||
case Tclunk:
|
||||
srv.clunk(req)
|
||||
|
||||
case p.Tremove:
|
||||
case Tremove:
|
||||
srv.remove(req)
|
||||
|
||||
case p.Tstat:
|
||||
case Tstat:
|
||||
srv.stat(req)
|
||||
|
||||
case p.Twstat:
|
||||
case Twstat:
|
||||
srv.wstat(req)
|
||||
}
|
||||
}
|
||||
|
||||
// Performs the post processing required if the (*Req) Process() method
|
||||
// Performs the post processing required if the (*SrvReq) Process() method
|
||||
// is called for a request. The file server implementer should call it
|
||||
// only if the file server implements the ReqProcessOps within the
|
||||
// ReqRespond operation.
|
||||
func (req *Req) PostProcess() {
|
||||
// only if the file server implements the SrvReqProcessOps within the
|
||||
// SrvReqRespond operation.
|
||||
func (req *SrvReq) PostProcess() {
|
||||
srv := req.Conn.Srv
|
||||
|
||||
/* call the post-handlers (if needed) */
|
||||
switch req.Tc.Type {
|
||||
case p.Tauth:
|
||||
case Tauth:
|
||||
srv.authPost(req)
|
||||
|
||||
case p.Tattach:
|
||||
case Tattach:
|
||||
srv.attachPost(req)
|
||||
|
||||
case p.Twalk:
|
||||
case Twalk:
|
||||
srv.walkPost(req)
|
||||
|
||||
case p.Topen:
|
||||
case Topen:
|
||||
srv.openPost(req)
|
||||
|
||||
case p.Tcreate:
|
||||
case Tcreate:
|
||||
srv.createPost(req)
|
||||
|
||||
case p.Tread:
|
||||
case Tread:
|
||||
srv.readPost(req)
|
||||
|
||||
case p.Tclunk:
|
||||
case Tclunk:
|
||||
srv.clunkPost(req)
|
||||
|
||||
case p.Tremove:
|
||||
case Tremove:
|
||||
srv.removePost(req)
|
||||
}
|
||||
|
||||
|
@ -404,8 +376,8 @@ func (req *Req) PostProcess() {
|
|||
// should be initialized and contain valid 9P2000 message. In most cases
|
||||
// the file server implementer shouldn't call this method directly. Instead
|
||||
// one of the RespondR* methods should be used.
|
||||
func (req *Req) Respond() {
|
||||
var flushreqs *Req
|
||||
func (req *SrvReq) Respond() {
|
||||
var flushreqs *SrvReq
|
||||
|
||||
conn := req.Conn
|
||||
req.Lock()
|
||||
|
@ -425,7 +397,7 @@ func (req *Req) Respond() {
|
|||
nextreq.next = nil
|
||||
// if there are flush requests, move them to the next request
|
||||
if req.flushreq != nil {
|
||||
var p *Req = nil
|
||||
var p *SrvReq = nil
|
||||
r := nextreq.flushreq
|
||||
for ; r != nil; p, r = r, r.flushreq {
|
||||
}
|
||||
|
@ -433,7 +405,7 @@ func (req *Req) Respond() {
|
|||
if p == nil {
|
||||
nextreq.flushreq = req.flushreq
|
||||
} else {
|
||||
p.next = req.flushreq
|
||||
nextreq = req.flushreq
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,8 +416,8 @@ func (req *Req) Respond() {
|
|||
}
|
||||
conn.Unlock()
|
||||
|
||||
if rop, ok := (req.Conn.Srv.ops).(ReqProcessOps); ok {
|
||||
rop.ReqRespond(req)
|
||||
if rop, ok := (req.Conn.Srv.ops).(SrvReqProcessOps); ok {
|
||||
rop.SrvReqRespond(req)
|
||||
} else {
|
||||
req.PostProcess()
|
||||
}
|
||||
|
@ -469,18 +441,18 @@ func (req *Req) Respond() {
|
|||
|
||||
// Should be called to cancel a request. Should only be called
|
||||
// from the Flush operation if the FlushOp is implemented.
|
||||
func (req *Req) Flush() {
|
||||
func (req *SrvReq) Flush() {
|
||||
req.Lock()
|
||||
req.status |= reqFlush
|
||||
req.Unlock()
|
||||
req.Respond()
|
||||
}
|
||||
|
||||
// Lookup a Fid struct based on the 32-bit identifier sent over the wire.
|
||||
// Lookup a SrvFid struct based on the 32-bit identifier sent over the wire.
|
||||
// Returns nil if the fid is not found. Increases the reference count of
|
||||
// the returned fid. The user is responsible to call DecRef once it no
|
||||
// longer needs it.
|
||||
func (conn *Conn) FidGet(fidno uint32) *Fid {
|
||||
func (conn *Conn) FidGet(fidno uint32) *SrvFid {
|
||||
conn.Lock()
|
||||
fid, present := conn.fidpool[fidno]
|
||||
conn.Unlock()
|
||||
|
@ -491,10 +463,10 @@ func (conn *Conn) FidGet(fidno uint32) *Fid {
|
|||
return fid
|
||||
}
|
||||
|
||||
// Creates a new Fid struct for the fidno integer. Returns nil
|
||||
// if the Fid for that number already exists. The returned fid
|
||||
// Creates a new SrvFid struct for the fidno integer. Returns nil
|
||||
// if the SrvFid for that number already exists. The returned fid
|
||||
// has reference count set to 1.
|
||||
func (conn *Conn) FidNew(fidno uint32) *Fid {
|
||||
func (conn *Conn) FidNew(fidno uint32) *SrvFid {
|
||||
conn.Lock()
|
||||
_, present := conn.fidpool[fidno]
|
||||
if present {
|
||||
|
@ -502,7 +474,7 @@ func (conn *Conn) FidNew(fidno uint32) *Fid {
|
|||
return nil
|
||||
}
|
||||
|
||||
fid := new(Fid)
|
||||
fid := new(SrvFid)
|
||||
fid.fid = fidno
|
||||
fid.refcount = 1
|
||||
fid.Fconn = conn
|
||||
|
@ -517,7 +489,7 @@ func (conn *Conn) String() string {
|
|||
}
|
||||
|
||||
// Increase the reference count for the fid.
|
||||
func (fid *Fid) IncRef() {
|
||||
func (fid *SrvFid) IncRef() {
|
||||
fid.Lock()
|
||||
fid.refcount++
|
||||
fid.Unlock()
|
||||
|
@ -525,7 +497,7 @@ func (fid *Fid) IncRef() {
|
|||
|
||||
// Decrease the reference count for the fid. When the
|
||||
// reference count reaches 0, the fid is no longer valid.
|
||||
func (fid *Fid) DecRef() {
|
||||
func (fid *SrvFid) DecRef() {
|
||||
fid.Lock()
|
||||
fid.refcount--
|
||||
n := fid.refcount
|
||||
|
@ -540,7 +512,7 @@ func (fid *Fid) DecRef() {
|
|||
delete(conn.fidpool, fid.fid)
|
||||
conn.Unlock()
|
||||
|
||||
if fop, ok := (conn.Srv.ops).(FidOps); ok {
|
||||
if fop, ok := (conn.Srv.ops).(SrvFidOps); ok {
|
||||
fop.FidDestroy(fid)
|
||||
}
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
// +build httpstats
|
||||
|
||||
package srv
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var mux sync.RWMutex
|
||||
var stat map[string]http.Handler
|
||||
var once sync.Once
|
||||
var httponce sync.Once
|
||||
|
||||
func register(s string, h http.Handler) {
|
||||
mux.Lock()
|
||||
|
@ -28,7 +27,7 @@ func register(s string, h http.Handler) {
|
|||
mux.Unlock()
|
||||
}
|
||||
func (srv *Srv) statsRegister() {
|
||||
once.Do(func() {
|
||||
httponce.Do(func() {
|
||||
http.HandleFunc("/go9p/", StatsHandler)
|
||||
go http.ListenAndServe(":6060", nil)
|
||||
})
|
||||
|
@ -85,7 +84,7 @@ func (conn *Conn) ServeHTTP(c http.ResponseWriter, r *http.Request) {
|
|||
fs := conn.Srv.Log.Filter(conn, DbgLogFcalls)
|
||||
io.WriteString(c, fmt.Sprintf("<h2>Last %d 9P messages</h2>", len(fs)))
|
||||
for i, l := range fs {
|
||||
fc := l.Data.(*p.Fcall)
|
||||
fc := l.Data.(*Fcall)
|
||||
if fc.Type == 0 {
|
||||
continue
|
||||
}
|
||||
|
@ -94,7 +93,7 @@ func (conn *Conn) ServeHTTP(c http.ResponseWriter, r *http.Request) {
|
|||
if fc.Type%2 == 0 {
|
||||
// try to find the response for the T message
|
||||
for j := i + 1; j < len(fs); j++ {
|
||||
rc := fs[j].Data.(*p.Fcall)
|
||||
rc := fs[j].Data.(*Fcall)
|
||||
if rc.Tag == fc.Tag {
|
||||
lbl = fmt.Sprintf("<a href='#fc%d'>➴</a>", j)
|
||||
break
|
||||
|
@ -103,7 +102,7 @@ func (conn *Conn) ServeHTTP(c http.ResponseWriter, r *http.Request) {
|
|||
} else {
|
||||
// try to find the request for the R message
|
||||
for j := i - 1; j >= 0; j-- {
|
||||
tc := fs[j].Data.(*p.Fcall)
|
||||
tc := fs[j].Data.(*Fcall)
|
||||
if tc.Tag == fc.Tag {
|
||||
lbl = fmt.Sprintf("<a href='#fc%d'>➶</a>", j)
|
||||
break
|
|
@ -0,0 +1,6 @@
|
|||
package go9p
|
||||
|
||||
type StatsOps interface {
|
||||
statsRegister()
|
||||
statsUnregister()
|
||||
}
|
|
@ -2,51 +2,49 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ufs
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
)
|
||||
|
||||
type Fid struct {
|
||||
path string
|
||||
file *os.File
|
||||
dirs []os.FileInfo
|
||||
diroffset uint64
|
||||
st os.FileInfo
|
||||
type ufsFid struct {
|
||||
path string
|
||||
file *os.File
|
||||
dirs []os.FileInfo
|
||||
direntends []int
|
||||
dirents []byte
|
||||
diroffset uint64
|
||||
st os.FileInfo
|
||||
}
|
||||
|
||||
type Ufs struct {
|
||||
srv.Srv
|
||||
Srv
|
||||
Root string
|
||||
}
|
||||
|
||||
var addr string
|
||||
var debug int
|
||||
var root string
|
||||
var Enoent = &p.Error{"file not found", p.ENOENT}
|
||||
|
||||
func toError(err error) *p.Error {
|
||||
func toError(err error) *Error {
|
||||
var ecode uint32
|
||||
|
||||
ename := err.Error()
|
||||
if e, ok := err.(syscall.Errno); ok {
|
||||
ecode = uint32(e)
|
||||
} else {
|
||||
ecode = p.EIO
|
||||
ecode = EIO
|
||||
}
|
||||
|
||||
return &p.Error{ename, ecode}
|
||||
return &Error{ename, ecode}
|
||||
}
|
||||
|
||||
func (fid *Fid) stat() *p.Error {
|
||||
func (fid *ufsFid) stat() *Error {
|
||||
var err error
|
||||
|
||||
fid.st, err = os.Lstat(fid.path)
|
||||
|
@ -60,24 +58,24 @@ func (fid *Fid) stat() *p.Error {
|
|||
func omode2uflags(mode uint8) int {
|
||||
ret := int(0)
|
||||
switch mode & 3 {
|
||||
case p.OREAD:
|
||||
case OREAD:
|
||||
ret = os.O_RDONLY
|
||||
break
|
||||
|
||||
case p.ORDWR:
|
||||
case ORDWR:
|
||||
ret = os.O_RDWR
|
||||
break
|
||||
|
||||
case p.OWRITE:
|
||||
case OWRITE:
|
||||
ret = os.O_WRONLY
|
||||
break
|
||||
|
||||
case p.OEXEC:
|
||||
case OEXEC:
|
||||
ret = os.O_RDONLY
|
||||
break
|
||||
}
|
||||
|
||||
if mode&p.OTRUNC != 0 {
|
||||
if mode&OTRUNC != 0 {
|
||||
ret |= os.O_TRUNC
|
||||
}
|
||||
|
||||
|
@ -87,11 +85,11 @@ func omode2uflags(mode uint8) int {
|
|||
func dir2QidType(d os.FileInfo) uint8 {
|
||||
ret := uint8(0)
|
||||
if d.IsDir() {
|
||||
ret |= p.QTDIR
|
||||
ret |= QTDIR
|
||||
}
|
||||
|
||||
if d.Mode()&os.ModeSymlink != 0 {
|
||||
ret |= p.QTSYMLINK
|
||||
ret |= QTSYMLINK
|
||||
}
|
||||
|
||||
return ret
|
||||
|
@ -100,33 +98,33 @@ func dir2QidType(d os.FileInfo) uint8 {
|
|||
func dir2Npmode(d os.FileInfo, dotu bool) uint32 {
|
||||
ret := uint32(d.Mode() & 0777)
|
||||
if d.IsDir() {
|
||||
ret |= p.DMDIR
|
||||
ret |= DMDIR
|
||||
}
|
||||
|
||||
if dotu {
|
||||
mode := d.Mode()
|
||||
if mode&os.ModeSymlink != 0 {
|
||||
ret |= p.DMSYMLINK
|
||||
ret |= DMSYMLINK
|
||||
}
|
||||
|
||||
if mode&os.ModeSocket != 0 {
|
||||
ret |= p.DMSOCKET
|
||||
ret |= DMSOCKET
|
||||
}
|
||||
|
||||
if mode&os.ModeNamedPipe != 0 {
|
||||
ret |= p.DMNAMEDPIPE
|
||||
ret |= DMNAMEDPIPE
|
||||
}
|
||||
|
||||
if mode&os.ModeDevice != 0 {
|
||||
ret |= p.DMDEVICE
|
||||
ret |= DMDEVICE
|
||||
}
|
||||
|
||||
if mode&os.ModeSetuid != 0 {
|
||||
ret |= p.DMSETUID
|
||||
ret |= DMSETUID
|
||||
}
|
||||
|
||||
if mode&os.ModeSetgid != 0 {
|
||||
ret |= p.DMSETGID
|
||||
ret |= DMSETGID
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,48 +133,47 @@ func dir2Npmode(d os.FileInfo, dotu bool) uint32 {
|
|||
|
||||
// Dir is an instantiation of the p.Dir structure
|
||||
// that can act as a receiver for local methods.
|
||||
type Dir struct {
|
||||
p.Dir
|
||||
type ufsDir struct {
|
||||
Dir
|
||||
}
|
||||
|
||||
func (*Ufs) ConnOpened(conn *srv.Conn) {
|
||||
func (*Ufs) ConnOpened(conn *Conn) {
|
||||
if conn.Srv.Debuglevel > 0 {
|
||||
log.Println("connected")
|
||||
}
|
||||
}
|
||||
|
||||
func (*Ufs) ConnClosed(conn *srv.Conn) {
|
||||
func (*Ufs) ConnClosed(conn *Conn) {
|
||||
if conn.Srv.Debuglevel > 0 {
|
||||
log.Println("disconnected")
|
||||
}
|
||||
}
|
||||
|
||||
func (*Ufs) FidDestroy(sfid *srv.Fid) {
|
||||
var fid *Fid
|
||||
func (*Ufs) FidDestroy(sfid *SrvFid) {
|
||||
var fid *ufsFid
|
||||
|
||||
if sfid.Aux == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fid = sfid.Aux.(*Fid)
|
||||
fid = sfid.Aux.(*ufsFid)
|
||||
if fid.file != nil {
|
||||
fid.file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (*Ufs) Attach(req *srv.Req) {
|
||||
func (ufs *Ufs) Attach(req *SrvReq) {
|
||||
if req.Afid != nil {
|
||||
req.RespondError(srv.Enoauth)
|
||||
req.RespondError(Enoauth)
|
||||
return
|
||||
}
|
||||
|
||||
tc := req.Tc
|
||||
fid := new(Fid)
|
||||
if len(tc.Aname) == 0 {
|
||||
fid.path = root
|
||||
} else {
|
||||
fid.path = tc.Aname
|
||||
}
|
||||
fid := new(ufsFid)
|
||||
// You can think of the ufs.Root as a 'chroot' of a sort.
|
||||
// clients attach are not allowed to go outside the
|
||||
// directory represented by ufs.Root
|
||||
fid.path = path.Join(ufs.Root, tc.Aname)
|
||||
|
||||
req.Fid.Aux = fid
|
||||
err := fid.stat()
|
||||
|
@ -189,10 +186,10 @@ func (*Ufs) Attach(req *srv.Req) {
|
|||
req.RespondRattach(qid)
|
||||
}
|
||||
|
||||
func (*Ufs) Flush(req *srv.Req) {}
|
||||
func (*Ufs) Flush(req *SrvReq) {}
|
||||
|
||||
func (*Ufs) Walk(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Walk(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
tc := req.Tc
|
||||
|
||||
err := fid.stat()
|
||||
|
@ -202,11 +199,11 @@ func (*Ufs) Walk(req *srv.Req) {
|
|||
}
|
||||
|
||||
if req.Newfid.Aux == nil {
|
||||
req.Newfid.Aux = new(Fid)
|
||||
req.Newfid.Aux = new(ufsFid)
|
||||
}
|
||||
|
||||
nfid := req.Newfid.Aux.(*Fid)
|
||||
wqids := make([]p.Qid, len(tc.Wname))
|
||||
nfid := req.Newfid.Aux.(*ufsFid)
|
||||
wqids := make([]Qid, len(tc.Wname))
|
||||
path := fid.path
|
||||
i := 0
|
||||
for ; i < len(tc.Wname); i++ {
|
||||
|
@ -229,8 +226,8 @@ func (*Ufs) Walk(req *srv.Req) {
|
|||
req.RespondRwalk(wqids[0:i])
|
||||
}
|
||||
|
||||
func (*Ufs) Open(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Open(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
|
@ -248,8 +245,8 @@ func (*Ufs) Open(req *srv.Req) {
|
|||
req.RespondRopen(dir2Qid(fid.st), 0)
|
||||
}
|
||||
|
||||
func (*Ufs) Create(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Create(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
|
@ -261,13 +258,13 @@ func (*Ufs) Create(req *srv.Req) {
|
|||
var e error = nil
|
||||
var file *os.File = nil
|
||||
switch {
|
||||
case tc.Perm&p.DMDIR != 0:
|
||||
case tc.Perm&DMDIR != 0:
|
||||
e = os.Mkdir(path, os.FileMode(tc.Perm&0777))
|
||||
|
||||
case tc.Perm&p.DMSYMLINK != 0:
|
||||
case tc.Perm&DMSYMLINK != 0:
|
||||
e = os.Symlink(tc.Ext, path)
|
||||
|
||||
case tc.Perm&p.DMLINK != 0:
|
||||
case tc.Perm&DMLINK != 0:
|
||||
n, e := strconv.ParseUint(tc.Ext, 10, 0)
|
||||
if e != nil {
|
||||
break
|
||||
|
@ -275,25 +272,25 @@ func (*Ufs) Create(req *srv.Req) {
|
|||
|
||||
ofid := req.Conn.FidGet(uint32(n))
|
||||
if ofid == nil {
|
||||
req.RespondError(srv.Eunknownfid)
|
||||
req.RespondError(Eunknownfid)
|
||||
return
|
||||
}
|
||||
|
||||
e = os.Link(ofid.Aux.(*Fid).path, path)
|
||||
e = os.Link(ofid.Aux.(*ufsFid).path, path)
|
||||
ofid.DecRef()
|
||||
|
||||
case tc.Perm&p.DMNAMEDPIPE != 0:
|
||||
case tc.Perm&p.DMDEVICE != 0:
|
||||
req.RespondError(&p.Error{"not implemented", p.EIO})
|
||||
case tc.Perm&DMNAMEDPIPE != 0:
|
||||
case tc.Perm&DMDEVICE != 0:
|
||||
req.RespondError(&Error{"not implemented", EIO})
|
||||
return
|
||||
|
||||
default:
|
||||
var mode uint32 = tc.Perm & 0777
|
||||
if req.Conn.Dotu {
|
||||
if tc.Perm&p.DMSETUID > 0 {
|
||||
if tc.Perm&DMSETUID > 0 {
|
||||
mode |= syscall.S_ISUID
|
||||
}
|
||||
if tc.Perm&p.DMSETGID > 0 {
|
||||
if tc.Perm&DMSETGID > 0 {
|
||||
mode |= syscall.S_ISGID
|
||||
}
|
||||
}
|
||||
|
@ -320,8 +317,8 @@ func (*Ufs) Create(req *srv.Req) {
|
|||
req.RespondRcreate(dir2Qid(fid.st), 0)
|
||||
}
|
||||
|
||||
func (*Ufs) Read(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Read(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
tc := req.Tc
|
||||
rc := req.Rc
|
||||
err := fid.stat()
|
||||
|
@ -330,67 +327,83 @@ func (*Ufs) Read(req *srv.Req) {
|
|||
return
|
||||
}
|
||||
|
||||
p.InitRread(rc, tc.Count)
|
||||
InitRread(rc, tc.Count)
|
||||
var count int
|
||||
var e error
|
||||
if fid.st.IsDir() {
|
||||
b := rc.Data
|
||||
if tc.Offset == 0 {
|
||||
var e error
|
||||
// If we got here, it was open. Can't really seek
|
||||
// in most cases, just close and reopen it.
|
||||
fid.file.Close()
|
||||
fid.file, e = os.OpenFile(fid.path, omode2uflags(req.Fid.Omode), 0)
|
||||
if e != nil {
|
||||
if fid.file, e = os.OpenFile(fid.path, omode2uflags(req.Fid.Omode), 0); e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
if fid.dirs, e = fid.file.Readdir(-1); e != nil {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
fid.dirents = nil
|
||||
fid.direntends = nil
|
||||
for i := 0; i < len(fid.dirs); i++ {
|
||||
path := fid.path + "/" + fid.dirs[i].Name()
|
||||
st, _ := dir2Dir(path, fid.dirs[i], req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
if st == nil {
|
||||
continue
|
||||
}
|
||||
b := PackDir(st, req.Conn.Dotu)
|
||||
fid.dirents = append(fid.dirents, b...)
|
||||
count += len(b)
|
||||
fid.direntends = append(fid.direntends, count)
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case tc.Offset > uint64(len(fid.dirents)):
|
||||
count = 0
|
||||
case len(fid.dirents[tc.Offset:]) > int(tc.Count):
|
||||
count = int(tc.Count)
|
||||
default:
|
||||
count = len(fid.dirents[tc.Offset:])
|
||||
}
|
||||
|
||||
if !*Akaros {
|
||||
nextend := sort.SearchInts(fid.direntends, int(tc.Offset)+count)
|
||||
if nextend < len(fid.direntends) {
|
||||
if fid.direntends[nextend] > int(tc.Offset)+count {
|
||||
if nextend > 0 {
|
||||
count = fid.direntends[nextend-1] - int(tc.Offset)
|
||||
} else {
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if count == 0 && int(tc.Offset) < len(fid.dirents) && len(fid.dirents) > 0 {
|
||||
req.RespondError(&Error{"too small read size for dir entry", EINVAL})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for len(b) > 0 {
|
||||
if fid.dirs == nil {
|
||||
fid.dirs, e = fid.file.Readdir(16)
|
||||
if e != nil && e != io.EOF {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
copy(rc.Data, fid.dirents[tc.Offset:int(tc.Offset)+count])
|
||||
|
||||
if len(fid.dirs) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var i int
|
||||
for i = 0; i < len(fid.dirs); i++ {
|
||||
path := fid.path + "/" + fid.dirs[i].Name()
|
||||
st := dir2Dir(path, fid.dirs[i], req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
sz := p.PackDir(st, b, req.Conn.Dotu)
|
||||
if sz == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
b = b[sz:]
|
||||
count += sz
|
||||
}
|
||||
|
||||
if i < len(fid.dirs) {
|
||||
fid.dirs = fid.dirs[i:]
|
||||
break
|
||||
} else {
|
||||
fid.dirs = nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
count, e = fid.file.ReadAt(rc.Data, int64(tc.Offset))
|
||||
if e != nil && e != io.EOF {
|
||||
req.RespondError(toError(e))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
p.SetRreadCount(rc, uint32(count))
|
||||
SetRreadCount(rc, uint32(count))
|
||||
req.Respond()
|
||||
}
|
||||
|
||||
func (*Ufs) Write(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Write(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
tc := req.Tc
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
|
@ -407,10 +420,10 @@ func (*Ufs) Write(req *srv.Req) {
|
|||
req.RespondRwrite(uint32(n))
|
||||
}
|
||||
|
||||
func (*Ufs) Clunk(req *srv.Req) { req.RespondRclunk() }
|
||||
func (*Ufs) Clunk(req *SrvReq) { req.RespondRclunk() }
|
||||
|
||||
func (*Ufs) Remove(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Remove(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -426,25 +439,30 @@ func (*Ufs) Remove(req *srv.Req) {
|
|||
req.RespondRremove()
|
||||
}
|
||||
|
||||
func (*Ufs) Stat(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (*Ufs) Stat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
return
|
||||
}
|
||||
|
||||
st := dir2Dir(fid.path, fid.st, req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
st, derr := dir2Dir(fid.path, fid.st, req.Conn.Dotu, req.Conn.Srv.Upool)
|
||||
if st == nil {
|
||||
req.RespondError(derr)
|
||||
return
|
||||
}
|
||||
|
||||
req.RespondRstat(st)
|
||||
}
|
||||
|
||||
func lookup(uid string, group bool) (uint32, *p.Error) {
|
||||
func lookup(uid string, group bool) (uint32, *Error) {
|
||||
if uid == "" {
|
||||
return p.NOUID, nil
|
||||
return NOUID, nil
|
||||
}
|
||||
usr, e := user.Lookup(uid)
|
||||
if e != nil {
|
||||
return p.NOUID, toError(e)
|
||||
return NOUID, toError(e)
|
||||
}
|
||||
conv := usr.Uid
|
||||
if group {
|
||||
|
@ -452,23 +470,12 @@ func lookup(uid string, group bool) (uint32, *p.Error) {
|
|||
}
|
||||
u, e := strconv.Atoi(conv)
|
||||
if e != nil {
|
||||
return p.NOUID, toError(e)
|
||||
return NOUID, toError(e)
|
||||
}
|
||||
return uint32(u), nil
|
||||
}
|
||||
|
||||
func StartServer(addrVal string, debugVal int, rootVal string) {
|
||||
addr = addrVal
|
||||
debug = debugVal
|
||||
root = rootVal
|
||||
ufs := new(Ufs)
|
||||
ufs.Dotu = true
|
||||
ufs.Id = "ufs"
|
||||
ufs.Debuglevel = debug
|
||||
ufs.Start(ufs)
|
||||
|
||||
err := ufs.StartNetListener("tcp", addr)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
/* enables "Akaros" capabilities, which right now means
|
||||
* a sane error message format.
|
||||
*/
|
||||
var Akaros = flag.Bool("akaros", false, "Akaros extensions")
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ufs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p"
|
||||
)
|
||||
|
||||
func StartServer(addrVal string, debugVal int, rootVal string) {
|
||||
ufs := new(go9p.Ufs)
|
||||
ufs.Dotu = true
|
||||
ufs.Id = "ufs"
|
||||
ufs.Root = rootVal
|
||||
ufs.Debuglevel = debugVal
|
||||
ufs.Start(ufs)
|
||||
|
||||
fmt.Print("ufs starting\n")
|
||||
// determined by build tags
|
||||
//extraFuncs()
|
||||
err := ufs.StartNetListener("tcp", addrVal)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
|
@ -1,20 +1,18 @@
|
|||
// Copyright 2012 The go9p Authors. All rights reserved.
|
||||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ufs
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
)
|
||||
|
||||
func atime(stat *syscall.Stat_t) time.Time {
|
||||
|
@ -25,16 +23,18 @@ func atime(stat *syscall.Stat_t) time.Time {
|
|||
func isBlock(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK
|
||||
return true
|
||||
}
|
||||
|
||||
// IsChar reports if the file is a character device
|
||||
func isChar(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFCHR
|
||||
return true
|
||||
}
|
||||
|
||||
func dir2Qid(d os.FileInfo) *p.Qid {
|
||||
var qid p.Qid
|
||||
func dir2Qid(d os.FileInfo) *Qid {
|
||||
var qid Qid
|
||||
|
||||
qid.Path = d.Sys().(*syscall.Stat_t).Ino
|
||||
qid.Version = uint32(d.ModTime().UnixNano() / 1000000)
|
||||
|
@ -43,27 +43,34 @@ func dir2Qid(d os.FileInfo) *p.Qid {
|
|||
return &qid
|
||||
}
|
||||
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
||||
sysMode := d.Sys().(*syscall.Stat_t)
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool Users) (*Dir, error) {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Print("stat failed: ", r)
|
||||
return nil, &os.PathError{"dir2Dir", path, nil}
|
||||
}
|
||||
sysif := d.Sys()
|
||||
if sysif == nil {
|
||||
return nil, &os.PathError{"dir2Dir: sysif is nil", path, nil}
|
||||
}
|
||||
sysMode := sysif.(*syscall.Stat_t)
|
||||
|
||||
dir := new(Dir)
|
||||
dir := new(ufsDir)
|
||||
dir.Qid = *dir2Qid(d)
|
||||
dir.Mode = dir2Npmode(d, dotu)
|
||||
dir.Atime = uint32(atime(sysMode).Unix())
|
||||
dir.Atime = uint32(0 /*atime(sysMode).Unix()*/)
|
||||
dir.Mtime = uint32(d.ModTime().Unix())
|
||||
dir.Length = uint64(d.Size())
|
||||
dir.Name = path[strings.LastIndex(path, "/")+1:]
|
||||
|
||||
if dotu {
|
||||
dir.dotu(path, d, upool, sysMode)
|
||||
return &dir.Dir
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
unixUid := int(sysMode.Uid)
|
||||
unixGid := int(sysMode.Gid)
|
||||
dir.Uid = strconv.Itoa(unixUid)
|
||||
dir.Gid = strconv.Itoa(unixGid)
|
||||
dir.Muid = "none"
|
||||
|
||||
// BUG(akumar): LookupId will never find names for
|
||||
// groups, as it only operates on user ids.
|
||||
|
@ -76,10 +83,17 @@ func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
|||
dir.Gid = g.Username
|
||||
}
|
||||
|
||||
return &dir.Dir
|
||||
/* For Akaros, we use the Muid as the link value. */
|
||||
if *Akaros && (d.Mode()&os.ModeSymlink != 0) {
|
||||
dir.Muid, err = os.Readlink(path)
|
||||
if err == nil {
|
||||
dir.Mode |= DMSYMLINK
|
||||
}
|
||||
}
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall.Stat_t) {
|
||||
func (dir *ufsDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Stat_t) {
|
||||
u := upool.Uid2User(int(sysMode.Uid))
|
||||
g := upool.Gid2Group(int(sysMode.Gid))
|
||||
dir.Uid = u.Name()
|
||||
|
@ -95,7 +109,7 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall
|
|||
dir.Ext = ""
|
||||
dir.Uidnum = uint32(u.Id())
|
||||
dir.Gidnum = uint32(g.Id())
|
||||
dir.Muidnum = p.NOUID
|
||||
dir.Muidnum = NOUID
|
||||
if d.Mode()&os.ModeSymlink != 0 {
|
||||
var err error
|
||||
dir.Ext, err = os.Readlink(path)
|
||||
|
@ -109,8 +123,8 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall
|
|||
}
|
||||
}
|
||||
|
||||
func (*Ufs) Wstat(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (u *Ufs) Wstat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -121,10 +135,10 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
if dir.Mode != 0xFFFFFFFF {
|
||||
mode := dir.Mode & 0777
|
||||
if req.Conn.Dotu {
|
||||
if dir.Mode&p.DMSETUID > 0 {
|
||||
if dir.Mode&DMSETUID > 0 {
|
||||
mode |= syscall.S_ISUID
|
||||
}
|
||||
if dir.Mode&p.DMSETGID > 0 {
|
||||
if dir.Mode&DMSETGID > 0 {
|
||||
mode |= syscall.S_ISGID
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +149,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
uid, gid := p.NOUID, p.NOUID
|
||||
uid, gid := NOUID, NOUID
|
||||
if req.Conn.Dotu {
|
||||
uid = dir.Uidnum
|
||||
gid = dir.Gidnum
|
||||
|
@ -159,7 +173,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
if uid != p.NOUID || gid != p.NOUID {
|
||||
if uid != NOUID || gid != NOUID {
|
||||
e := os.Chown(fid.path, int(uid), int(gid))
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
|
@ -168,13 +182,25 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
|
||||
if dir.Name != "" {
|
||||
path := fid.path[0:strings.LastIndex(fid.path, "/")+1] + "/" + dir.Name
|
||||
err := syscall.Rename(fid.path, path)
|
||||
fmt.Printf("Rename %s to %s\n", fid.path, dir.Name)
|
||||
// if first char is / it is relative to root, else relative to
|
||||
// cwd.
|
||||
var destpath string
|
||||
if dir.Name[0] == '/' {
|
||||
destpath = path.Join(u.Root, dir.Name)
|
||||
fmt.Printf("/ results in %s\n", destpath)
|
||||
} else {
|
||||
fiddir, _ := path.Split(fid.path)
|
||||
destpath = path.Join(fiddir, dir.Name)
|
||||
fmt.Printf("rel results in %s\n", destpath)
|
||||
}
|
||||
err := syscall.Rename(fid.path, destpath)
|
||||
fmt.Printf("rename %s to %s gets %v\n", fid.path, destpath, err)
|
||||
if err != nil {
|
||||
req.RespondError(toError(err))
|
||||
return
|
||||
}
|
||||
fid.path = path
|
||||
fid.path = destpath
|
||||
}
|
||||
|
||||
if dir.Length != 0xFFFFFFFFFFFFFFFF {
|
||||
|
@ -199,7 +225,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
case true:
|
||||
mt = st.ModTime()
|
||||
default:
|
||||
at = atime(st.Sys().(*syscall.Stat_t))
|
||||
//at = time.Time(0)//atime(st.Sys().(*syscall.Stat_t))
|
||||
}
|
||||
}
|
||||
e := os.Chtimes(fid.path, at, mt)
|
|
@ -1,20 +1,14 @@
|
|||
// Copyright 2012 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ufs
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
)
|
||||
|
||||
func atime(stat *syscall.Stat_t) time.Time {
|
||||
|
@ -25,16 +19,18 @@ func atime(stat *syscall.Stat_t) time.Time {
|
|||
func isBlock(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK
|
||||
return true
|
||||
}
|
||||
|
||||
// IsChar reports if the file is a character device
|
||||
func isChar(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFCHR
|
||||
return true
|
||||
}
|
||||
|
||||
func dir2Qid(d os.FileInfo) *p.Qid {
|
||||
var qid p.Qid
|
||||
func dir2Qid(d os.FileInfo) *Qid {
|
||||
var qid Qid
|
||||
|
||||
qid.Path = d.Sys().(*syscall.Stat_t).Ino
|
||||
qid.Version = uint32(d.ModTime().UnixNano() / 1000000)
|
||||
|
@ -43,27 +39,34 @@ func dir2Qid(d os.FileInfo) *p.Qid {
|
|||
return &qid
|
||||
}
|
||||
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
||||
sysMode := d.Sys().(*syscall.Stat_t)
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool Users) (*Dir, error) {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Print("stat failed: ", r)
|
||||
return nil, &os.PathError{"dir2Dir", path, nil}
|
||||
}
|
||||
sysif := d.Sys()
|
||||
if sysif == nil {
|
||||
return nil, &os.PathError{"dir2Dir: sysif is nil", path, nil}
|
||||
}
|
||||
sysMode := sysif.(*syscall.Stat_t)
|
||||
|
||||
dir := new(Dir)
|
||||
dir := new(ufsDir)
|
||||
dir.Qid = *dir2Qid(d)
|
||||
dir.Mode = dir2Npmode(d, dotu)
|
||||
dir.Atime = uint32(atime(sysMode).Unix())
|
||||
dir.Atime = uint32(0 /*atime(sysMode).Unix()*/)
|
||||
dir.Mtime = uint32(d.ModTime().Unix())
|
||||
dir.Length = uint64(d.Size())
|
||||
dir.Name = path[strings.LastIndex(path, "/")+1:]
|
||||
|
||||
if dotu {
|
||||
dir.dotu(path, d, upool, sysMode)
|
||||
return &dir.Dir
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
unixUid := int(sysMode.Uid)
|
||||
unixGid := int(sysMode.Gid)
|
||||
dir.Uid = strconv.Itoa(unixUid)
|
||||
dir.Gid = strconv.Itoa(unixGid)
|
||||
dir.Muid = "none"
|
||||
|
||||
// BUG(akumar): LookupId will never find names for
|
||||
// groups, as it only operates on user ids.
|
||||
|
@ -76,10 +79,17 @@ func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
|||
dir.Gid = g.Username
|
||||
}
|
||||
|
||||
return &dir.Dir
|
||||
/* For Akaros, we use the Muid as the link value. */
|
||||
if *Akaros && (d.Mode()&os.ModeSymlink != 0) {
|
||||
dir.Muid, err = os.Readlink(path)
|
||||
if err == nil {
|
||||
dir.Mode |= DMSYMLINK
|
||||
}
|
||||
}
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall.Stat_t) {
|
||||
func (dir *ufsDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Stat_t) {
|
||||
u := upool.Uid2User(int(sysMode.Uid))
|
||||
g := upool.Gid2Group(int(sysMode.Gid))
|
||||
dir.Uid = u.Name()
|
||||
|
@ -95,7 +105,7 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall
|
|||
dir.Ext = ""
|
||||
dir.Uidnum = uint32(u.Id())
|
||||
dir.Gidnum = uint32(g.Id())
|
||||
dir.Muidnum = p.NOUID
|
||||
dir.Muidnum = NOUID
|
||||
if d.Mode()&os.ModeSymlink != 0 {
|
||||
var err error
|
||||
dir.Ext, err = os.Readlink(path)
|
||||
|
@ -109,8 +119,8 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users, sysMode *syscall
|
|||
}
|
||||
}
|
||||
|
||||
func (*Ufs) Wstat(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (u *Ufs) Wstat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -121,10 +131,10 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
if dir.Mode != 0xFFFFFFFF {
|
||||
mode := dir.Mode & 0777
|
||||
if req.Conn.Dotu {
|
||||
if dir.Mode&p.DMSETUID > 0 {
|
||||
if dir.Mode&DMSETUID > 0 {
|
||||
mode |= syscall.S_ISUID
|
||||
}
|
||||
if dir.Mode&p.DMSETGID > 0 {
|
||||
if dir.Mode&DMSETGID > 0 {
|
||||
mode |= syscall.S_ISGID
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +145,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
uid, gid := p.NOUID, p.NOUID
|
||||
uid, gid := NOUID, NOUID
|
||||
if req.Conn.Dotu {
|
||||
uid = dir.Uidnum
|
||||
gid = dir.Gidnum
|
||||
|
@ -159,7 +169,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
if uid != p.NOUID || gid != p.NOUID {
|
||||
if uid != NOUID || gid != NOUID {
|
||||
e := os.Chown(fid.path, int(uid), int(gid))
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
|
@ -168,13 +178,25 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
|
||||
if dir.Name != "" {
|
||||
path := fid.path[0:strings.LastIndex(fid.path, "/")+1] + "/" + dir.Name
|
||||
err := syscall.Rename(fid.path, path)
|
||||
fmt.Printf("Rename %s to %s\n", fid.path, dir.Name)
|
||||
// if first char is / it is relative to root, else relative to
|
||||
// cwd.
|
||||
var destpath string
|
||||
if dir.Name[0] == '/' {
|
||||
destpath = path.Join(u.Root, dir.Name)
|
||||
fmt.Printf("/ results in %s\n", destpath)
|
||||
} else {
|
||||
fiddir, _ := path.Split(fid.path)
|
||||
destpath = path.Join(fiddir, dir.Name)
|
||||
fmt.Printf("rel results in %s\n", destpath)
|
||||
}
|
||||
err := syscall.Rename(fid.path, destpath)
|
||||
fmt.Printf("rename %s to %s gets %v\n", fid.path, destpath, err)
|
||||
if err != nil {
|
||||
req.RespondError(toError(err))
|
||||
return
|
||||
}
|
||||
fid.path = path
|
||||
fid.path = destpath
|
||||
}
|
||||
|
||||
if dir.Length != 0xFFFFFFFFFFFFFFFF {
|
||||
|
@ -199,7 +221,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
case true:
|
||||
mt = st.ModTime()
|
||||
default:
|
||||
at = atime(st.Sys().(*syscall.Stat_t))
|
||||
//at = time.Time(0)//atime(st.Sys().(*syscall.Stat_t))
|
||||
}
|
||||
}
|
||||
e := os.Chtimes(fid.path, at, mt)
|
|
@ -1,63 +1,39 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2009 The go9p Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// http://golang.org/src/os/stat_windows.go
|
||||
|
||||
package ufs
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"k8s.io/minikube/third_party/go9p/p"
|
||||
"k8s.io/minikube/third_party/go9p/p/srv"
|
||||
)
|
||||
|
||||
// type Win32FileAttributeData struct {
|
||||
// FileAttributes uint32
|
||||
// CreationTime Filetime
|
||||
// LastAccessTime Filetime
|
||||
// LastWriteTime Filetime
|
||||
// FileSizeHigh uint32
|
||||
// FileSizeLow uint32
|
||||
// }
|
||||
|
||||
// A FileInfo describes a file and is returned by Stat and Lstat.
|
||||
// type FileInfo interface {
|
||||
// Name() string // base name of the file
|
||||
// Size() int64 // length in bytes for regular files; system-dependent for others
|
||||
// Mode() FileMode // file mode bits
|
||||
// ModTime() time.Time // modification time
|
||||
// IsDir() bool // abbreviation for Mode().IsDir()
|
||||
// Sys() interface{} // underlying data source (can return nil)
|
||||
// }
|
||||
|
||||
func atime(fi os.FileInfo) time.Time {
|
||||
return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
|
||||
}
|
||||
|
||||
// IsBlock reports if the file is a block device
|
||||
func isBlock(d os.FileInfo) bool {
|
||||
// return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
|
||||
// stat := d.Sys().(os.FileInfo)
|
||||
// stat := d.Sys().(*syscall.Stat_t)
|
||||
// return (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK
|
||||
return true
|
||||
}
|
||||
|
||||
// IsChar reports if the file is a character device
|
||||
func isChar(d os.FileInfo) bool {
|
||||
// stat := d.Sys().(os.FileInfo)
|
||||
// stat := d.Sys().(*syscall.Stat_t)
|
||||
// return (stat.Mode & syscall.S_IFMT) == syscall.S_IFCHR
|
||||
return true
|
||||
}
|
||||
|
||||
func dir2Qid(d os.FileInfo) *p.Qid {
|
||||
var qid p.Qid
|
||||
func dir2Qid(d os.FileInfo) *Qid {
|
||||
var qid Qid
|
||||
|
||||
// d.Sys().(*syscall.Win32FileAttributeData)
|
||||
qid.Path = uint64(d.Sys().(*syscall.Win32FileAttributeData).FileSizeLow)
|
||||
qid.Version = uint32(d.ModTime().UnixNano() / 1000000)
|
||||
qid.Type = dir2QidType(d)
|
||||
|
@ -65,20 +41,28 @@ func dir2Qid(d os.FileInfo) *p.Qid {
|
|||
return &qid
|
||||
}
|
||||
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
||||
// sysMode := d.Sys().(os.FileInfo)
|
||||
func dir2Dir(path string, d os.FileInfo, dotu bool, upool Users) (*Dir, error) {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Print("stat failed: ", r)
|
||||
return nil, &os.PathError{"dir2Dir", path, nil}
|
||||
}
|
||||
sysif := d.Sys()
|
||||
if sysif == nil {
|
||||
return nil, &os.PathError{"dir2Dir: sysif is nil", path, nil}
|
||||
}
|
||||
sysMode := sysif.(*syscall.Win32FileAttributeData)
|
||||
|
||||
dir := new(Dir)
|
||||
dir := new(ufsDir)
|
||||
dir.Qid = *dir2Qid(d)
|
||||
dir.Mode = dir2Npmode(d, dotu)
|
||||
// dir.Atime = uint32(atime(sysMode).Unix())
|
||||
// dir.Atime = uint32(0 /*atime(sysMode).Unix()*/)
|
||||
// dir.Mtime = uint32(d.ModTime().Unix())
|
||||
dir.Length = uint64(d.Size())
|
||||
dir.Name = path[strings.LastIndex(path, "/")+1:]
|
||||
|
||||
if dotu {
|
||||
// dir.dotu(path, d, upool, sysMode)
|
||||
return &dir.Dir
|
||||
dir.dotu(path, d, upool, sysMode)
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
// unixUid := int(sysMode.Uid)
|
||||
|
@ -101,10 +85,18 @@ func dir2Dir(path string, d os.FileInfo, dotu bool, upool p.Users) *p.Dir {
|
|||
// dir.Gid = g.Username
|
||||
// }
|
||||
|
||||
return &dir.Dir
|
||||
var err error
|
||||
/* For Akaros, we use the Muid as the link value. */
|
||||
if *Akaros && (d.Mode()&os.ModeSymlink != 0) {
|
||||
dir.Muid, err = os.Readlink(path)
|
||||
if err == nil {
|
||||
dir.Mode |= DMSYMLINK
|
||||
}
|
||||
}
|
||||
return &dir.Dir, nil
|
||||
}
|
||||
|
||||
func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users) {
|
||||
func (dir *ufsDir) dotu(path string, d os.FileInfo, upool Users, sysMode *syscall.Win32FileAttributeData) {
|
||||
// u := upool.Uid2User(int(sysMode.Uid))
|
||||
// g := upool.Gid2Group(int(sysMode.Gid))
|
||||
// dir.Uid = u.Name()
|
||||
|
@ -120,7 +112,7 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users) {
|
|||
// dir.Ext = ""
|
||||
// dir.Uidnum = uint32(u.Id())
|
||||
// dir.Gidnum = uint32(g.Id())
|
||||
// dir.Muidnum = p.NOUID
|
||||
// dir.Muidnum = NOUID
|
||||
// if d.Mode()&os.ModeSymlink != 0 {
|
||||
// var err error
|
||||
// dir.Ext, err = os.Readlink(path)
|
||||
|
@ -137,12 +129,12 @@ func (dir *Dir) dotu(path string, d os.FileInfo, upool p.Users) {
|
|||
dir.Muid = "none"
|
||||
dir.Uidnum = 0
|
||||
dir.Gidnum = 0
|
||||
dir.Muidnum = p.NOUID
|
||||
dir.Muidnum = NOUID
|
||||
dir.Ext = ""
|
||||
}
|
||||
|
||||
func (*Ufs) Wstat(req *srv.Req) {
|
||||
fid := req.Fid.Aux.(*Fid)
|
||||
func (u *Ufs) Wstat(req *SrvReq) {
|
||||
fid := req.Fid.Aux.(*ufsFid)
|
||||
err := fid.stat()
|
||||
if err != nil {
|
||||
req.RespondError(err)
|
||||
|
@ -153,10 +145,10 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
if dir.Mode != 0xFFFFFFFF {
|
||||
mode := dir.Mode & 0777
|
||||
if req.Conn.Dotu {
|
||||
if dir.Mode&p.DMSETUID > 0 {
|
||||
if dir.Mode&DMSETUID > 0 {
|
||||
mode |= syscall.S_ISUID
|
||||
}
|
||||
if dir.Mode&p.DMSETGID > 0 {
|
||||
if dir.Mode&DMSETGID > 0 {
|
||||
mode |= syscall.S_ISGID
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +159,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
uid, gid := p.NOUID, p.NOUID
|
||||
uid, gid := NOUID, NOUID
|
||||
if req.Conn.Dotu {
|
||||
uid = dir.Uidnum
|
||||
gid = dir.Gidnum
|
||||
|
@ -191,7 +183,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
}
|
||||
|
||||
if uid != p.NOUID || gid != p.NOUID {
|
||||
if uid != NOUID || gid != NOUID {
|
||||
e := os.Chown(fid.path, int(uid), int(gid))
|
||||
if e != nil {
|
||||
req.RespondError(toError(e))
|
||||
|
@ -200,13 +192,25 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
}
|
||||
|
||||
if dir.Name != "" {
|
||||
path := fid.path[0:strings.LastIndex(fid.path, "/")+1] + "/" + dir.Name
|
||||
err := syscall.Rename(fid.path, path)
|
||||
fmt.Printf("Rename %s to %s\n", fid.path, dir.Name)
|
||||
// if first char is / it is relative to root, else relative to
|
||||
// cwd.
|
||||
var destpath string
|
||||
if dir.Name[0] == '/' {
|
||||
destpath = path.Join(u.Root, dir.Name)
|
||||
fmt.Printf("/ results in %s\n", destpath)
|
||||
} else {
|
||||
fiddir, _ := path.Split(fid.path)
|
||||
destpath = path.Join(fiddir, dir.Name)
|
||||
fmt.Printf("rel results in %s\n", destpath)
|
||||
}
|
||||
err := syscall.Rename(fid.path, destpath)
|
||||
fmt.Printf("rename %s to %s gets %v\n", fid.path, destpath, err)
|
||||
if err != nil {
|
||||
req.RespondError(toError(err))
|
||||
return
|
||||
}
|
||||
fid.path = path
|
||||
fid.path = destpath
|
||||
}
|
||||
|
||||
if dir.Length != 0xFFFFFFFFFFFFFFFF {
|
||||
|
@ -231,7 +235,7 @@ func (*Ufs) Wstat(req *srv.Req) {
|
|||
// case true:
|
||||
// mt = st.ModTime()
|
||||
// default:
|
||||
// at = atime(st.Sys().(os.FileInfo))
|
||||
// //at = time.Time(0)//atime(st.Sys().(*syscall.Stat_t))
|
||||
// }
|
||||
// }
|
||||
// e := os.Chtimes(fid.path, at, mt)
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
package go9p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -77,9 +77,14 @@ func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
|
|||
goto szerror
|
||||
}
|
||||
|
||||
fc.Unamenum = NOUID
|
||||
if dotu && len(p) > 0 {
|
||||
fc.Unamenum, p = gint32(p)
|
||||
if dotu {
|
||||
if len(p) > 0 {
|
||||
fc.Unamenum, p = gint32(p)
|
||||
} else {
|
||||
fc.Unamenum = NOUID
|
||||
}
|
||||
} else {
|
||||
fc.Unamenum = NOUID
|
||||
}
|
||||
|
||||
case Rauth, Rattach:
|
||||
|
@ -101,9 +106,12 @@ func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
|
|||
goto szerror
|
||||
}
|
||||
|
||||
fc.Unamenum = NOUID
|
||||
if dotu && len(p) > 0 {
|
||||
fc.Unamenum, p = gint32(p)
|
||||
if dotu {
|
||||
if len(p) > 0 {
|
||||
fc.Unamenum, p = gint32(p)
|
||||
} else {
|
||||
fc.Unamenum = NOUID
|
||||
}
|
||||
}
|
||||
|
||||
case Rerror:
|
||||
|
@ -193,15 +201,15 @@ func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
|
|||
|
||||
case Rstat:
|
||||
m, p = gint16(p)
|
||||
p = gstat(p, &fc.Dir, dotu)
|
||||
if p == nil {
|
||||
goto szerror
|
||||
p, err = gstat(p, &fc.Dir, dotu)
|
||||
if err != nil {
|
||||
return nil, err, 0
|
||||
}
|
||||
|
||||
case Twstat:
|
||||
fc.Fid, p = gint32(p)
|
||||
m, p = gint16(p)
|
||||
p = gstat(p, &fc.Dir, dotu)
|
||||
p, _ = gstat(p, &fc.Dir, dotu)
|
||||
|
||||
case Rflush, Rclunk, Rremove, Rwstat:
|
||||
}
|
Loading…
Reference in New Issue