Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions client/cpio9p.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
package client

import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"syscall"

"github.com/hugelgupf/p9/fsimpl/templatefs"
"github.com/hugelgupf/p9/p9"
Expand Down Expand Up @@ -59,6 +59,9 @@ func NewCPIO9P(c string) (*CPIO9P, error) {
return NewCPIO9PReaderAt(f)
}

// ErrNosys is the kernel-independent ENOSYS
var ErrNosys = errors.New("function not implemented")

// NewCPIO9PReaderAt returns a CPIO9P, properly initialized, from an io.ReaderAt.
func NewCPIO9PReaderAt(r io.ReaderAt) (*CPIO9P, error) {
archive, err := cpio.Format("newc")
Expand Down Expand Up @@ -351,25 +354,25 @@ func (l *CPIO9PFID) UnlinkAt(name string, flags uint32) error {

// Mknod implements p9.File.Mknod.
func (*CPIO9PFID) Mknod(name string, mode p9.FileMode, major uint32, minor uint32, _ p9.UID, _ p9.GID) (p9.QID, error) {
return p9.QID{}, syscall.ENOSYS
return p9.QID{}, ErrNosys
}

// Rename implements p9.File.Rename.
func (*CPIO9PFID) Rename(directory p9.File, name string) error {
return syscall.ENOSYS
return ErrNosys
}

// RenameAt implements p9.File.RenameAt.
// There is no guarantee that there is not a zipslip issue.
func (l *CPIO9PFID) RenameAt(oldName string, newDir p9.File, newName string) error {
return syscall.ENOSYS
return ErrNosys
}

// StatFS implements p9.File.StatFS.
//
// Not implemented.
func (*CPIO9PFID) StatFS() (p9.FSStat, error) {
return p9.FSStat{}, syscall.ENOSYS
return p9.FSStat{}, ErrNosys
}

// SetAttr implements SetAttr.
Expand Down
56 changes: 3 additions & 53 deletions client/cpu9p.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ import (
"path"
"path/filepath"
"strings"
"syscall"

"github.com/hugelgupf/p9/fsimpl/xattr"
"github.com/hugelgupf/p9/p9"
"golang.org/x/sys/unix"
)

// CPU9P is a p9.Attacher.
Expand All @@ -50,53 +47,6 @@ var (
_ p9.Attacher = &CPU9P{}
)

// info constructs a QID for this file.
func (l *CPU9P) info() (p9.QID, os.FileInfo, error) {
var (
qid p9.QID
fi os.FileInfo
err error
)

// Stat the file.
if l.file != nil {
fi, err = l.file.Stat()
} else {
fi, err = os.Lstat(l.path)
}
if err != nil {
//log.Printf("error stating %#v: %v", l, err)
return qid, nil, err
}

// Construct the QID type.
qid.Type = p9.ModeFromOS(fi.Mode()).QIDType()

// Save the path from the Ino.
qid.Path = fi.Sys().(*syscall.Stat_t).Ino
return qid, fi, nil
}

// SetXattr implements p9.File.SetXattr
func (l *CPU9P) SetXattr(attr string, data []byte, flags p9.XattrFlags) error {
return unix.Setxattr(l.path, attr, data, int(flags))
}

// ListXattrs implements p9.File.ListXattrs
func (l *CPU9P) ListXattrs() ([]string, error) {
return xattr.List(l.path)
}

// GetXattr implements p9.File.GetXattr
func (l *CPU9P) GetXattr(attr string) ([]byte, error) {
return xattr.Get(l.path, attr)
}

// RemoveXattr implements p9.File.RemoveXattr
func (l *CPU9P) RemoveXattr(attr string) error {
return unix.Removexattr(l.path, attr)
}

// Walk implements p9.File.Walk.
func (l *CPU9P) Walk(names []string) ([]p9.QID, p9.File, error) {
var qids []p9.QID
Expand Down Expand Up @@ -303,13 +253,13 @@ func (l *CPU9P) UnlinkAt(name string, flags uint32) error {
// Mknod implements p9.File.Mknod.
func (*CPU9P) Mknod(name string, mode p9.FileMode, major uint32, minor uint32, _ p9.UID, _ p9.GID) (p9.QID, error) {
verbose("Mknod: not implemented")
return p9.QID{}, syscall.ENOSYS
return p9.QID{}, ErrNosys
}

// Rename implements p9.File.Rename.
func (*CPU9P) Rename(directory p9.File, name string) error {
verbose("Rename: not implemented")
return syscall.ENOSYS
return ErrNosys
}

// RenameAt implements p9.File.RenameAt.
Expand All @@ -333,5 +283,5 @@ func (l *CPU9P) RenameAt(oldName string, newDir p9.File, newName string) error {
// Not implemented.
func (*CPU9P) StatFS() (p9.FSStat, error) {
verbose("StatFS: not implemented")
return p9.FSStat{}, syscall.ENOSYS
return p9.FSStat{}, ErrNosys
}
129 changes: 129 additions & 0 deletions client/cpu9p_plan9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright 2022 the u-root 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 client

import (
"errors"
"fmt"
"os"
"syscall"
"time"

"github.com/hugelgupf/p9/p9"
)

// ErrNoDirInfo means Sys() was empty after a Stat()
var ErrNoDirInfo = errors.New("no Sys() after a Stat()")

// SetAttr implements p9.File.SetAttr.
func (l *CPU9P) SetAttr(mask p9.SetAttrMask, attr p9.SetAttr) error {
var err error
// Any or ALL can be set.
// A setattr could include things to set,
// and a permission value that makes setting those
// things impossible. Therefore, do these
// permission-y things last:
// Permissions
// GID
// UID
// Since changing, e.g., UID or GID might make
// changing permissions impossible.
//
// The test actually caught this ...

if mask.Size {
if e := os.Truncate(l.path, int64(attr.Size)); e != nil {
err = errors.Join(err, fmt.Errorf("truncate:%w", err))
}
}
if mask.ATime || mask.MTime {
atime, mtime := time.Now(), time.Now()
if mask.ATimeNotSystemTime {
atime = time.Unix(int64(attr.ATimeSeconds), int64(attr.ATimeNanoSeconds))
}
if mask.MTimeNotSystemTime {
mtime = time.Unix(int64(attr.MTimeSeconds), int64(attr.MTimeNanoSeconds))
}
if e := os.Chtimes(l.path, atime, mtime); e != nil {
err = errors.Join(err, e)
}
}

if mask.CTime {
// The Linux client sets CTime. I did not even know that was allowed.
// if e := errors.New("Can not set CTime on Unix"); e != nil { err = errors.Join(e)}
verbose("mask.CTime is set by client; ignoring")
}
if mask.Permissions {
perm := uint32(attr.Permissions)
if e := os.Chmod(l.path, os.FileMode(perm)); e != nil {
err = errors.Join(err, fmt.Errorf("%q:%o:%w", l.path, perm, err))
}
}

if mask.GID {
err = errors.Join(err, os.ErrPermission)
}
if mask.UID {
err = errors.Join(err, os.ErrPermission)
}
return err
}

// Lock implements p9.File.Lock.
// No such thing on Plan 9. Just say ok.
func (l *CPU9P) Lock(pid int, locktype p9.LockType, flags p9.LockFlags, start, length uint64, client string) (p9.LockStatus, error) {
return p9.LockStatusOK, nil
}

// info constructs a QID for this file.
func (l *CPU9P) info() (p9.QID, os.FileInfo, error) {
var (
qid p9.QID
fi os.FileInfo
err error
)

// Stat the file.
if l.file != nil {
fi, err = l.file.Stat()
}

if err != nil {
return qid, nil, err
}

d, ok := fi.Sys().(*syscall.Dir)
if !ok {
return qid, fi, fmt.Errorf("%q:%v", l.file.Name(), ErrNoDirInfo)

}

qid.Path, qid.Version, qid.Type = d.Qid.Path, d.Qid.Vers, p9.QIDType(d.Qid.Type)

return qid, fi, nil
}

// SetXattr implements p9.File.SetXattr
func (l *CPU9P) SetXattr(attr string, data []byte, flags p9.XattrFlags) error {
return ErrNosys
}

// ListXattrs implements p9.File.ListXattrs
// Since there technically are none, return an empty []string and
// no error.
func (l *CPU9P) ListXattrs() ([]string, error) {
return []string{}, nil
}

// GetXattr implements p9.File.GetXattr
func (l *CPU9P) GetXattr(attr string) ([]byte, error) {
return nil, nil
}

// RemoveXattr implements p9.File.RemoveXattr
func (l *CPU9P) RemoveXattr(attr string) error {
return ErrNosys
}
49 changes: 49 additions & 0 deletions client/cpu9p_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import (
"errors"
"fmt"
"os"
"syscall"
"time"

"github.com/hugelgupf/p9/fsimpl/xattr"
"github.com/hugelgupf/p9/p9"
"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -112,3 +114,50 @@ func (l *CPU9P) Lock(pid int, locktype p9.LockType, flags p9.LockFlags, start, l
}
return p9.LockStatusOK, nil
}

// info constructs a QID for this file.
func (l *CPU9P) info() (p9.QID, os.FileInfo, error) {
var (
qid p9.QID
fi os.FileInfo
err error
)

// Stat the file.
if l.file != nil {
fi, err = l.file.Stat()
} else {
fi, err = os.Lstat(l.path)
}
if err != nil {
//log.Printf("error stating %#v: %v", l, err)
return qid, nil, err
}

// Construct the QID type.
qid.Type = p9.ModeFromOS(fi.Mode()).QIDType()

// Save the path from the Ino.
qid.Path = fi.Sys().(*syscall.Stat_t).Ino
return qid, fi, nil
}

// SetXattr implements p9.File.SetXattr
func (l *CPU9P) SetXattr(attr string, data []byte, flags p9.XattrFlags) error {
return unix.Setxattr(l.path, attr, data, int(flags))
}

// ListXattrs implements p9.File.ListXattrs
func (l *CPU9P) ListXattrs() ([]string, error) {
return xattr.List(l.path)
}

// GetXattr implements p9.File.GetXattr
func (l *CPU9P) GetXattr(attr string) ([]byte, error) {
return xattr.Get(l.path, attr)
}

// RemoveXattr implements p9.File.RemoveXattr
func (l *CPU9P) RemoveXattr(attr string) error {
return unix.Removexattr(l.path, attr)
}
19 changes: 19 additions & 0 deletions client/cpu_plan9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018-2019 the u-root 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 client

import (
"os"

"github.com/hugelgupf/p9/p9"
)

func osflags(fi os.FileInfo, mode p9.OpenFlags) int {
flags := int(mode)

// special processing goes here.

return flags
}
20 changes: 18 additions & 2 deletions client/fns.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"io"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"

Expand Down Expand Up @@ -118,7 +119,20 @@ func (c *Cmd) SetEnv(envs ...string) error {
if len(env) == 1 {
env = append(env, "")
}
if err := c.session.Setenv(env[0], env[1]); err != nil {
// Plan 9 rc shell adds a NUL to environment variables.
// This will cause go exec to fail, due to a security
// mitigation, see
// Reject NUL in environment variables to prevent security issues (#56284)
// If we are on Plan 9, trim trailing NUL.
v := env[1]
if runtime.GOOS == "plan9" {
v = strings.TrimRight(v, "\x00")
if strings.Contains(v, "\x00") {
continue
}
}
verbose("c.session.Setenv(%q,%q)", env[0], v)
if err := c.session.Setenv(env[0], v); err != nil {
err = errors.Join(fmt.Errorf("Warning: c.session.Setenv(%q, %q): %v", v, os.Getenv(v), err))
}
}
Expand Down Expand Up @@ -324,7 +338,9 @@ func ParseBinds(s string) (string, error) {
// The convention is that the remote side is relative to filepath.Join(tmpMnt, "cpu")
// and the left side is taken exactly as written. Further, recall that in bind mounts, the
// remote side is the "device", and the local side is the "target."
fstab = fstab + fmt.Sprintf("%s %s none defaults,bind 0 0\n", filepath.Join(tmpMnt, "cpu", remote), local)
el := fmt.Sprintf("%s %s none defaults,bind 0 0\n", filepath.Join(tmpMnt, "cpu", remote), local)
verbose("Set up fstab element %s", el)
fstab = fstab + el
}
return fstab, nil
}
Expand Down
Loading
Loading