1 Star 0 Fork 1

mysnapcore / mysnapd

forked from tupelo-shen / mysnapd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mountentry.go 10.04 KB
一键复制 编辑 原始数据 按行查看 历史
tupelo-shen 提交于 2022-11-06 23:46 . fix: osutil 1 commit
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package osutil
import (
"fmt"
"math"
"os"
"regexp"
"strings"
)
// MountEntry describes an /etc/fstab-like mount entry.
//
// Fields are named after names in struct returned by getmntent(3).
//
// struct mntent {
// char *mnt_fsname; /* name of mounted filesystem */
// char *mnt_dir; /* filesystem path prefix */
// char *mnt_type; /* mount type (see Mntent.h) */
// char *mnt_opts; /* mount options (see Mntent.h) */
// int mnt_freq; /* dump frequency in days */
// int mnt_passno; /* pass number on parallel fsck */
// };
type MountEntry struct {
Name string
Dir string
Type string
Options []string
DumpFrequency int
CheckPassNumber int
}
func equalStrings(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
// Equal checks if one entry is equal to another
func (e *MountEntry) Equal(o *MountEntry) bool {
return (e.Name == o.Name && e.Dir == o.Dir && e.Type == o.Type &&
equalStrings(e.Options, o.Options) && e.DumpFrequency == o.DumpFrequency &&
e.CheckPassNumber == o.CheckPassNumber)
}
// escape replaces whitespace characters so that getmntent can parse it correctly.
var escape = strings.NewReplacer(
" ", `\040`,
"\t", `\011`,
"\n", `\012`,
"\\", `\134`,
).Replace
// unescape replaces escape sequences used by setmnt with whitespace characters.
var unescape = strings.NewReplacer(
`\040`, " ",
`\011`, "\t",
`\012`, "\n",
`\134`, "\\",
).Replace
// Escape returns the given path with space, tab, newline and forward slash escaped.
func Escape(path string) string {
return escape(path)
}
// Unescape returns the given path with space, tab, newline and forward slash unescaped.
func Unescape(path string) string {
return unescape(path)
}
func (e MountEntry) String() string {
// Name represents name of the device in a mount entry.
name := "none"
if e.Name != "" {
name = escape(e.Name)
}
// Dir represents mount directory in a mount entry.
dir := "none"
if e.Dir != "" {
dir = escape(e.Dir)
}
// Type represents file system type in a mount entry.
fsType := "none"
if e.Type != "" {
fsType = escape(e.Type)
}
// Options represents mount options in a mount entry.
options := "defaults"
if len(e.Options) != 0 {
options = escape(strings.Join(e.Options, ","))
}
return fmt.Sprintf("%s %s %s %s %d %d",
name, dir, fsType, options, e.DumpFrequency, e.CheckPassNumber)
}
// OptStr returns the value part of a key=value mount option.
// The name of the option must not contain the trailing "=" character.
func (e *MountEntry) OptStr(name string) (string, bool) {
prefix := name + "="
for _, opt := range e.Options {
if strings.HasPrefix(opt, prefix) {
kv := strings.SplitN(opt, "=", 2)
return kv[1], true
}
}
return "", false
}
// OptBool returns true if a given mount option is present.
func (e *MountEntry) OptBool(name string) bool {
for _, opt := range e.Options {
if opt == name {
return true
}
}
return false
}
var (
validModeRe = regexp.MustCompile("^0[0-7]{3}$")
validUserGroupRe = regexp.MustCompile("(^[0-9]+$)")
)
// XSnapdMode returns the file mode associated with x-snapd.mode mount option.
// If the mode is not specified explicitly then a default mode of 0755 is assumed.
func (e *MountEntry) XSnapdMode() (os.FileMode, error) {
if opt, ok := e.OptStr("x-snapd.mode"); ok {
if !validModeRe.MatchString(opt) {
return 0, fmt.Errorf("cannot parse octal file mode from %q", opt)
}
var mode os.FileMode
n, err := fmt.Sscanf(opt, "%o", &mode)
if err != nil || n != 1 {
return 0, fmt.Errorf("cannot parse octal file mode from %q", opt)
}
return mode, nil
}
return 0755, nil
}
// XSnapdUID returns the user associated with x-snapd-user mount option. If
// the mode is not specified explicitly then a default "root" use is
// returned.
func (e *MountEntry) XSnapdUID() (uid uint64, err error) {
if opt, ok := e.OptStr("x-snapd.uid"); ok {
if !validUserGroupRe.MatchString(opt) {
return math.MaxUint64, fmt.Errorf("cannot parse user name %q", opt)
}
// Try to parse a numeric ID first.
if n, err := fmt.Sscanf(opt, "%d", &uid); n == 1 && err == nil {
return uid, nil
}
return uid, nil
}
return 0, nil
}
// XSnapdGID returns the user associated with x-snapd-user mount option. If
// the mode is not specified explicitly then a default "root" use is
// returned.
func (e *MountEntry) XSnapdGID() (gid uint64, err error) {
if opt, ok := e.OptStr("x-snapd.gid"); ok {
if !validUserGroupRe.MatchString(opt) {
return math.MaxUint64, fmt.Errorf("cannot parse group name %q", opt)
}
// Try to parse a numeric ID first.
if n, err := fmt.Sscanf(opt, "%d", &gid); n == 1 && err == nil {
return gid, nil
}
return gid, nil
}
return 0, nil
}
// XSnapdEntryID returns the identifier of a given mount enrty.
//
// Identifiers are kept in the x-snapd.id mount option. The value is a string
// that identifies a mount entry and is stable across invocations of snapd. In
// absence of that identifier the entry mount point is returned.
func (e *MountEntry) XSnapdEntryID() string {
if val, ok := e.OptStr("x-snapd.id"); ok {
return val
}
return e.Dir
}
// XSnapdNeededBy the identifier of an entry which needs this entry to function.
//
// The "needed by" identifiers are kept in the x-snapd.needed-by mount option.
// The value is a string that identifies another mount entry which, in order to
// be feasible, has spawned one or more additional support entries. Each such
// entry contains the needed-by attribute.
func (e *MountEntry) XSnapdNeededBy() string {
val, _ := e.OptStr("x-snapd.needed-by")
return val
}
// XSnapdOrigin returns the origin of a given mount entry.
//
// Currently only "layout" entries are identified with a unique origin string.
func (e *MountEntry) XSnapdOrigin() string {
val, _ := e.OptStr("x-snapd.origin")
return val
}
// XSnapdSynthetic returns true of a given mount entry is synthetic.
//
// Synthetic mount entries are created by snap-update-ns itself, separately
// from what snapd instructed. Such entries are needed to make other things
// possible. They are identified by having the "x-snapd.synthetic" mount
// option.
func (e *MountEntry) XSnapdSynthetic() bool {
return e.OptBool("x-snapd.synthetic")
}
// XSnapdKind returns the kind of a given mount entry.
//
// There are three kinds of mount entries today: one for directories, one for
// files and one for symlinks. The values are "", "file" and "symlink" respectively.
//
// Directories use the empty string (in fact they don't need the option at
// all) as this was the default and is retained for backwards compatibility.
func (e *MountEntry) XSnapdKind() string {
val, _ := e.OptStr("x-snapd.kind")
return val
}
// XSnapdDetach returns true if a mount entry should be detached rather than unmounted.
//
// Whenever we create a recursive bind mount we don't want to just unmount it
// as it may have replicated additional mount entries. For simplicity and
// race-free behavior we just detach such mount entries and let the kernel do
// the rest.
func (e *MountEntry) XSnapdDetach() bool {
return e.OptBool("x-snapd.detach")
}
// XSnapdSymlink returns the target for a symlink mount entry.
//
// For non-symlinks an empty string is returned.
func (e *MountEntry) XSnapdSymlink() string {
val, _ := e.OptStr("x-snapd.symlink")
return val
}
// XSnapdIgnoreMissing returns true if a mount entry should be ignored
// if the source or target are missing.
//
// By default, snap-update-ns will try to create missing source and
// target paths when processing a mount entry. In some cases, this
// behaviour is not desired and it would be better to ignore the mount
// entry when the source or target are missing.
func (e *MountEntry) XSnapdIgnoreMissing() bool {
return e.OptBool("x-snapd.ignore-missing")
}
// XSnapdNeededBy returns the string "x-snapd.needed-by=..." with the given path appended.
func XSnapdNeededBy(path string) string {
return fmt.Sprintf("x-snapd.needed-by=%s", path)
}
// XSnapdSynthetic returns the string "x-snapd.synthetic".
func XSnapdSynthetic() string {
return "x-snapd.synthetic"
}
// XSnapdDetach returns the string "x-snapd.detach".
func XSnapdDetach() string {
return "x-snapd.detach"
}
// XSnapdKindSymlink returns the string "x-snapd.kind=symlink".
func XSnapdKindSymlink() string {
return "x-snapd.kind=symlink"
}
// XSnapdKindFile returns the string "x-snapd.kind=file".
func XSnapdKindFile() string {
return "x-snapd.kind=file"
}
// XSnapdOriginLayout returns the string "x-snapd.origin=layout"
func XSnapdOriginLayout() string {
return "x-snapd.origin=layout"
}
// XSnapdOriginOvername returns the string "x-snapd.origin=overname"
func XSnapdOriginOvername() string {
return "x-snapd.origin=overname"
}
// XSnapdUser returns the string "x-snapd.user=%d".
func XSnapdUser(uid uint32) string {
return fmt.Sprintf("x-snapd.user=%d", uid)
}
// XSnapdGroup returns the string "x-snapd.group=%d".
func XSnapdGroup(gid uint32) string {
return fmt.Sprintf("x-snapd.group=%d", gid)
}
// XSnapdMode returns the string "x-snapd.mode=%#o".
func XSnapdMode(mode uint32) string {
return fmt.Sprintf("x-snapd.mode=%#o", mode)
}
// XSnapdSymlink returns the string "x-snapd.symlink=%s".
func XSnapdSymlink(oldname string) string {
return fmt.Sprintf("x-snapd.symlink=%s", oldname)
}
// XSnapdIgnoreMissing returns the string "x-snapd.ignore-missing".
func XSnapdIgnoreMissing() string {
return "x-snapd.ignore-missing"
}
Go
1
https://gitee.com/mysnapcore/mysnapd.git
git@gitee.com:mysnapcore/mysnapd.git
mysnapcore
mysnapd
mysnapd
v0.0.1

搜索帮助

53164aa7 5694891 3bd8fe86 5694891