How do I check a file's permissions in linux using Go

huangapple go评论121阅读模式
英文:

How do I check a file's permissions in linux using Go

问题

我正在学习Go语言,我想做的第一个项目是编写一个替代Linux find shell程序的程序。我在不到一个小时的时间内用Python写了一个替代程序。这是一个更大的挑战。

我遇到的问题是,当filepath.Walk遍历我的文件系统时,它会在屏幕上输出一堆权限被拒绝的消息。我需要一种在filepath.Walk操作文件之前检查文件权限的方法。

英文:

I'm learning Go and the first project I want to do is to write a replacement for the Linux find shell program. I wrote a replacement for it in python in less than an hour. This is a much bigger challenge.

The problem I'm having is as Goes filepath.Walk traverses my file system it spits out a bunch of permission denied messages to the screen.
I need a way of checking the files permissions before filepath.Walk touches them.

答案1

得分: 9

go中,文件权限是在os.FileMode中定义的,底层类型是uint32。根据文档:

FileMode表示文件的模式和权限位...
...
定义的文件模式位是FileMode的最高有效位。最低有效的九位是标准的Unix rwxrwxrwx权限。这些位的值应被视为公共API的一部分,并可用于线路协议或磁盘表示:它们不得更改,尽管可能会添加新的位。

您可以通过os.Statos.LStat函数检索FileMode,它返回一个FileInfo,例如:

info, err := os.Stat("文件/目录名称")

然后可以通过调用info.Mode()来获取FileMode。要检查权限,请对模式位执行按位操作,例如:

//检查“其他”权限
m := info.Mode()
if m&(1<<2) != 0 {
    //其他用户具有读权限
} else {
    //其他用户没有读权限
}

如果您使用filepath.Walk函数访问目录/文件,由于WalkFuncWalk的第二个参数)定义为

type WalkFunc func(path string, info os.FileInfo, err error) error

对于特定路径WalkFunc的第二个参数可用作FileInfo,因此您可以直接使用info.Mode()在传递给filepath.Walk的闭包或函数的主体中检查权限,而无需调用os.Statos.Lstat

英文:

In go the file permission is defined in os.FileMode in which the underlying type is an uint32. From documentation:

> A FileMode represents a file's mode and permission bits...
...
The defined file mode bits are the most significant bits of the FileMode. The nine least-significant bits are the standard Unix rwxrwxrwx permissions. The values of these bits should be considered part of the public API and may be used in wire protocols or disk representations: they must not be changed, although new bits might be added.

You can retrieve the FileMode through os.Stat or os.LStat function which returns a FileInfo, e.g.

info, err := os.Stat(&quot;file/directory name&quot;)

then the FileMode can be obtained by calling info.Mode(). To check the permission, performs bitwise operation to the mode bits, e.g.

//Check &#39;others&#39; permission
m := info.Mode()
if m&amp;(1&lt;&lt;2) != 0 {
	//other users have read permission
} else {
	//other users don&#39;t have read permission
}

If you're visiting directory/file(s) using filepath.Walk function, since the WalkFunc (the second argument of Walk) is defined as

type WalkFunc func(path string, info os.FileInfo, err error) error

the FileInfo for certain path is available as the second argument of WalkFunc, thus you can check the permission directly using info.Mode() without calling os.Stat or os.Lstat inside the body of the closure or function passed to filepath.Walk.

答案2

得分: 5

你可以以字符串形式检索权限,例如:r,w,x。像这样:

func printPermissions(filename string) {
    info, err := os.Stat(filename)
    if err != nil {
        panic(err)
    }

    mode := info.Mode()

    fmt.Print("Owner: ")
    for i := 1; i < 4; i++ {
        fmt.Print(string(mode.String()[i]))
    }

    fmt.Print("\nGroup: ")
    for i := 4; i < 7; i++ {
        fmt.Print(string(mode.String()[i]))
    }

    fmt.Print("\nOther: ")
    for i := 7; i < 10; i++ {
        fmt.Print(string(mode.String()[i]))
    }
}
英文:

You can retrieve the permissions in string form e.i: r, w, x. Like this:

func printPermissions(filename string) {
	info, err := os.Stat(filename)
	if err != nil {
		panic(err)
	}

	mode := info.Mode()

	fmt.Print(&quot;Owner: &quot;)
	for i := 1; i &lt; 4; i++ {
		fmt.Print(string(mode.String()[i]))
	}

	fmt.Print(&quot;\nGroup: &quot;)
	for i := 4; i &lt; 7; i++ {
		fmt.Print(string(mode.String()[i]))
	}

	fmt.Print(&quot;\nOther: &quot;)
	for i := 7; i &lt; 10; i++ {
		fmt.Print(string(mode.String()[i]))
	}
}

答案3

得分: 0

对于Unix权限和现代Go语言,您可以使用字面量。

filePath := "/tmp/testfile"
fileStats, err := os.Stat(filePath)
if err != nil {
	log.Fatalf("文件不存在:%v", err)
}

permissions := fileStats.Mode().Perm()
if permissions != 0o600 {
	log.Fatalf("权限不正确 %s (0%o),必须为0600:%s", permissions, permissions, filePath)
}

// 检查特定权限:用户读取、用户写入
if permissions&0b110000000 == 0b110000000 {
	fmt.Printf("用户具有读取和写入权限\n")
}

// 检查特定权限:用户写入
if permissions&0b010000000 == 0b010000000 {
	fmt.Printf("用户具有写入权限\n")
}

// 检查特定权限:用户读取
// 为了更好的可读性,进行分解
if permissions&0b100_000_000 == 0b100_000_000 {
	fmt.Printf("用户具有读取权限\n")
}

关于权限的位和八进制的详细解释
https://codereview.stackexchange.com/a/79100

英文:

For unix permissions and modern go you can use literals.

filePath := &quot;/tmp/testfile&quot;
fileStats, err := os.Stat(filePath)
if err != nil {
	log.Fatalf(&quot;file does not exist: %v&quot;, err)
}

permissions := fileStats.Mode().Perm()
if permissions != 0o600 {
	log.Fatalf(&quot;incorrect permisisons %s (0%o), must be 0600 for &#39;%s&#39;&quot;, permissions, permissions, filePath)
}

// check for specific permissions: user read, user write
if permissions&amp;0b110000000 == 0b110000000 {
	fmt.Printf(&quot;user has read and write permission\n&quot;)
}

// check for specific permission: user write
if permissions&amp;0b010000000 == 0b010000000 {
	fmt.Printf(&quot;user has write permission\n&quot;)
}

// check for specific permission: user read
// breakup for better readability
if permissions&amp;0b100_000_000 == 0b100_000_000 {
	fmt.Printf(&quot;user has read permission\n&quot;)
}

A nice explaination on permissions as bits and octal
https://codereview.stackexchange.com/a/79100

huangapple
  • 本文由 发表于 2017年8月1日 12:54:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/45429210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定