blob: e40a5337912380ae9b9123ead1f85ccb77b71586 [file] [log] [blame]
Lorenz Brun1d801752020-04-02 09:24:51 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package fsquota
18
19import (
20 "fmt"
21 "os"
22 "unsafe"
23
24 "golang.org/x/sys/unix"
25)
26
27// This requires fsinfo() support, which is not yet in any stable kernel.
28// Our kernel has that syscall backported. This would otherwise be an extremely expensive
29// operation and also involve lots of logic from our side.
30
31// From syscall_64.tbl
32const sys_fsinfo = 441
33
34// From uapi/linux/fsinfo.h
35const fsinfo_attr_source = 0x09
36const fsinfo_flags_query_path = 0x0000
37const fsinfo_flags_query_fd = 0x0001
38
39type fsinfoParams struct {
40 resolveFlags uint64
41 atFlags uint32
42 flags uint32
43 request uint32
44 nth uint32
45 mth uint32
46}
47
48func fsinfoGetSource(dir *os.File) (string, error) {
49 buf := make([]byte, 256)
50 params := fsinfoParams{
51 flags: fsinfo_flags_query_fd,
52 request: fsinfo_attr_source,
53 }
54 n, _, err := unix.Syscall6(sys_fsinfo, dir.Fd(), 0, uintptr(unsafe.Pointer(&params)), unsafe.Sizeof(params), uintptr(unsafe.Pointer(&buf[0])), 128)
55 if err != unix.Errno(0) {
56 return "", fmt.Errorf("failed to call fsinfo: %w", err)
57 }
58 return string(buf[:n]), nil
59}