1// +build linux
2
3package disk
4
5import (
6	"bufio"
7	"bytes"
8	"context"
9	"fmt"
10	"io/ioutil"
11	"os"
12	"path/filepath"
13	"strconv"
14	"strings"
15
16	"github.com/shirou/gopsutil/internal/common"
17	"golang.org/x/sys/unix"
18)
19
20const (
21	SectorSize = 512
22)
23const (
24	// man statfs
25	ADFS_SUPER_MAGIC      = 0xadf5
26	AFFS_SUPER_MAGIC      = 0xADFF
27	BDEVFS_MAGIC          = 0x62646576
28	BEFS_SUPER_MAGIC      = 0x42465331
29	BFS_MAGIC             = 0x1BADFACE
30	BINFMTFS_MAGIC        = 0x42494e4d
31	BTRFS_SUPER_MAGIC     = 0x9123683E
32	CGROUP_SUPER_MAGIC    = 0x27e0eb
33	CIFS_MAGIC_NUMBER     = 0xFF534D42
34	CODA_SUPER_MAGIC      = 0x73757245
35	COH_SUPER_MAGIC       = 0x012FF7B7
36	CRAMFS_MAGIC          = 0x28cd3d45
37	DEBUGFS_MAGIC         = 0x64626720
38	DEVFS_SUPER_MAGIC     = 0x1373
39	DEVPTS_SUPER_MAGIC    = 0x1cd1
40	EFIVARFS_MAGIC        = 0xde5e81e4
41	EFS_SUPER_MAGIC       = 0x00414A53
42	EXT_SUPER_MAGIC       = 0x137D
43	EXT2_OLD_SUPER_MAGIC  = 0xEF51
44	EXT2_SUPER_MAGIC      = 0xEF53
45	EXT3_SUPER_MAGIC      = 0xEF53
46	EXT4_SUPER_MAGIC      = 0xEF53
47	FUSE_SUPER_MAGIC      = 0x65735546
48	FUTEXFS_SUPER_MAGIC   = 0xBAD1DEA
49	HFS_SUPER_MAGIC       = 0x4244
50	HFSPLUS_SUPER_MAGIC   = 0x482b
51	HOSTFS_SUPER_MAGIC    = 0x00c0ffee
52	HPFS_SUPER_MAGIC      = 0xF995E849
53	HUGETLBFS_MAGIC       = 0x958458f6
54	ISOFS_SUPER_MAGIC     = 0x9660
55	JFFS2_SUPER_MAGIC     = 0x72b6
56	JFS_SUPER_MAGIC       = 0x3153464a
57	MINIX_SUPER_MAGIC     = 0x137F /* orig. minix */
58	MINIX_SUPER_MAGIC2    = 0x138F /* 30 char minix */
59	MINIX2_SUPER_MAGIC    = 0x2468 /* minix V2 */
60	MINIX2_SUPER_MAGIC2   = 0x2478 /* minix V2, 30 char names */
61	MINIX3_SUPER_MAGIC    = 0x4d5a /* minix V3 fs, 60 char names */
62	MQUEUE_MAGIC          = 0x19800202
63	MSDOS_SUPER_MAGIC     = 0x4d44
64	NCP_SUPER_MAGIC       = 0x564c
65	NFS_SUPER_MAGIC       = 0x6969
66	NILFS_SUPER_MAGIC     = 0x3434
67	NTFS_SB_MAGIC         = 0x5346544e
68	OCFS2_SUPER_MAGIC     = 0x7461636f
69	OPENPROM_SUPER_MAGIC  = 0x9fa1
70	PIPEFS_MAGIC          = 0x50495045
71	PROC_SUPER_MAGIC      = 0x9fa0
72	PSTOREFS_MAGIC        = 0x6165676C
73	QNX4_SUPER_MAGIC      = 0x002f
74	QNX6_SUPER_MAGIC      = 0x68191122
75	RAMFS_MAGIC           = 0x858458f6
76	REISERFS_SUPER_MAGIC  = 0x52654973
77	ROMFS_MAGIC           = 0x7275
78	SELINUX_MAGIC         = 0xf97cff8c
79	SMACK_MAGIC           = 0x43415d53
80	SMB_SUPER_MAGIC       = 0x517B
81	SOCKFS_MAGIC          = 0x534F434B
82	SQUASHFS_MAGIC        = 0x73717368
83	SYSFS_MAGIC           = 0x62656572
84	SYSV2_SUPER_MAGIC     = 0x012FF7B6
85	SYSV4_SUPER_MAGIC     = 0x012FF7B5
86	TMPFS_MAGIC           = 0x01021994
87	UDF_SUPER_MAGIC       = 0x15013346
88	UFS_MAGIC             = 0x00011954
89	USBDEVICE_SUPER_MAGIC = 0x9fa2
90	V9FS_MAGIC            = 0x01021997
91	VXFS_SUPER_MAGIC      = 0xa501FCF5
92	XENFS_SUPER_MAGIC     = 0xabba1974
93	XENIX_SUPER_MAGIC     = 0x012FF7B4
94	XFS_SUPER_MAGIC       = 0x58465342
95	_XIAFS_SUPER_MAGIC    = 0x012FD16D
96
97	AFS_SUPER_MAGIC             = 0x5346414F
98	AUFS_SUPER_MAGIC            = 0x61756673
99	ANON_INODE_FS_SUPER_MAGIC   = 0x09041934
100	CEPH_SUPER_MAGIC            = 0x00C36400
101	ECRYPTFS_SUPER_MAGIC        = 0xF15F
102	FAT_SUPER_MAGIC             = 0x4006
103	FHGFS_SUPER_MAGIC           = 0x19830326
104	FUSEBLK_SUPER_MAGIC         = 0x65735546
105	FUSECTL_SUPER_MAGIC         = 0x65735543
106	GFS_SUPER_MAGIC             = 0x1161970
107	GPFS_SUPER_MAGIC            = 0x47504653
108	MTD_INODE_FS_SUPER_MAGIC    = 0x11307854
109	INOTIFYFS_SUPER_MAGIC       = 0x2BAD1DEA
110	ISOFS_R_WIN_SUPER_MAGIC     = 0x4004
111	ISOFS_WIN_SUPER_MAGIC       = 0x4000
112	JFFS_SUPER_MAGIC            = 0x07C0
113	KAFS_SUPER_MAGIC            = 0x6B414653
114	LUSTRE_SUPER_MAGIC          = 0x0BD00BD0
115	NFSD_SUPER_MAGIC            = 0x6E667364
116	PANFS_SUPER_MAGIC           = 0xAAD7AAEA
117	RPC_PIPEFS_SUPER_MAGIC      = 0x67596969
118	SECURITYFS_SUPER_MAGIC      = 0x73636673
119	UFS_BYTESWAPPED_SUPER_MAGIC = 0x54190100
120	VMHGFS_SUPER_MAGIC          = 0xBACBACBC
121	VZFS_SUPER_MAGIC            = 0x565A4653
122	ZFS_SUPER_MAGIC             = 0x2FC12FC1
123)
124
125// coreutils/src/stat.c
126var fsTypeMap = map[int64]string{
127	ADFS_SUPER_MAGIC:          "adfs",          /* 0xADF5 local */
128	AFFS_SUPER_MAGIC:          "affs",          /* 0xADFF local */
129	AFS_SUPER_MAGIC:           "afs",           /* 0x5346414F remote */
130	ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */
131	AUFS_SUPER_MAGIC:          "aufs",          /* 0x61756673 remote */
132	//	AUTOFS_SUPER_MAGIC:          "autofs",              /* 0x0187 local */
133	BEFS_SUPER_MAGIC:            "befs",                /* 0x42465331 local */
134	BDEVFS_MAGIC:                "bdevfs",              /* 0x62646576 local */
135	BFS_MAGIC:                   "bfs",                 /* 0x1BADFACE local */
136	BINFMTFS_MAGIC:              "binfmt_misc",         /* 0x42494E4D local */
137	BTRFS_SUPER_MAGIC:           "btrfs",               /* 0x9123683E local */
138	CEPH_SUPER_MAGIC:            "ceph",                /* 0x00C36400 remote */
139	CGROUP_SUPER_MAGIC:          "cgroupfs",            /* 0x0027E0EB local */
140	CIFS_MAGIC_NUMBER:           "cifs",                /* 0xFF534D42 remote */
141	CODA_SUPER_MAGIC:            "coda",                /* 0x73757245 remote */
142	COH_SUPER_MAGIC:             "coh",                 /* 0x012FF7B7 local */
143	CRAMFS_MAGIC:                "cramfs",              /* 0x28CD3D45 local */
144	DEBUGFS_MAGIC:               "debugfs",             /* 0x64626720 local */
145	DEVFS_SUPER_MAGIC:           "devfs",               /* 0x1373 local */
146	DEVPTS_SUPER_MAGIC:          "devpts",              /* 0x1CD1 local */
147	ECRYPTFS_SUPER_MAGIC:        "ecryptfs",            /* 0xF15F local */
148	EFS_SUPER_MAGIC:             "efs",                 /* 0x00414A53 local */
149	EXT_SUPER_MAGIC:             "ext",                 /* 0x137D local */
150	EXT2_SUPER_MAGIC:            "ext2/ext3",           /* 0xEF53 local */
151	EXT2_OLD_SUPER_MAGIC:        "ext2",                /* 0xEF51 local */
152	FAT_SUPER_MAGIC:             "fat",                 /* 0x4006 local */
153	FHGFS_SUPER_MAGIC:           "fhgfs",               /* 0x19830326 remote */
154	FUSEBLK_SUPER_MAGIC:         "fuseblk",             /* 0x65735546 remote */
155	FUSECTL_SUPER_MAGIC:         "fusectl",             /* 0x65735543 remote */
156	FUTEXFS_SUPER_MAGIC:         "futexfs",             /* 0x0BAD1DEA local */
157	GFS_SUPER_MAGIC:             "gfs/gfs2",            /* 0x1161970 remote */
158	GPFS_SUPER_MAGIC:            "gpfs",                /* 0x47504653 remote */
159	HFS_SUPER_MAGIC:             "hfs",                 /* 0x4244 local */
160	HFSPLUS_SUPER_MAGIC:         "hfsplus",             /* 0x482b local */
161	HPFS_SUPER_MAGIC:            "hpfs",                /* 0xF995E849 local */
162	HUGETLBFS_MAGIC:             "hugetlbfs",           /* 0x958458F6 local */
163	MTD_INODE_FS_SUPER_MAGIC:    "inodefs",             /* 0x11307854 local */
164	INOTIFYFS_SUPER_MAGIC:       "inotifyfs",           /* 0x2BAD1DEA local */
165	ISOFS_SUPER_MAGIC:           "isofs",               /* 0x9660 local */
166	ISOFS_R_WIN_SUPER_MAGIC:     "isofs",               /* 0x4004 local */
167	ISOFS_WIN_SUPER_MAGIC:       "isofs",               /* 0x4000 local */
168	JFFS_SUPER_MAGIC:            "jffs",                /* 0x07C0 local */
169	JFFS2_SUPER_MAGIC:           "jffs2",               /* 0x72B6 local */
170	JFS_SUPER_MAGIC:             "jfs",                 /* 0x3153464A local */
171	KAFS_SUPER_MAGIC:            "k-afs",               /* 0x6B414653 remote */
172	LUSTRE_SUPER_MAGIC:          "lustre",              /* 0x0BD00BD0 remote */
173	MINIX_SUPER_MAGIC:           "minix",               /* 0x137F local */
174	MINIX_SUPER_MAGIC2:          "minix (30 char.)",    /* 0x138F local */
175	MINIX2_SUPER_MAGIC:          "minix v2",            /* 0x2468 local */
176	MINIX2_SUPER_MAGIC2:         "minix v2 (30 char.)", /* 0x2478 local */
177	MINIX3_SUPER_MAGIC:          "minix3",              /* 0x4D5A local */
178	MQUEUE_MAGIC:                "mqueue",              /* 0x19800202 local */
179	MSDOS_SUPER_MAGIC:           "msdos",               /* 0x4D44 local */
180	NCP_SUPER_MAGIC:             "novell",              /* 0x564C remote */
181	NFS_SUPER_MAGIC:             "nfs",                 /* 0x6969 remote */
182	NFSD_SUPER_MAGIC:            "nfsd",                /* 0x6E667364 remote */
183	NILFS_SUPER_MAGIC:           "nilfs",               /* 0x3434 local */
184	NTFS_SB_MAGIC:               "ntfs",                /* 0x5346544E local */
185	OPENPROM_SUPER_MAGIC:        "openprom",            /* 0x9FA1 local */
186	OCFS2_SUPER_MAGIC:           "ocfs2",               /* 0x7461636f remote */
187	PANFS_SUPER_MAGIC:           "panfs",               /* 0xAAD7AAEA remote */
188	PIPEFS_MAGIC:                "pipefs",              /* 0x50495045 remote */
189	PROC_SUPER_MAGIC:            "proc",                /* 0x9FA0 local */
190	PSTOREFS_MAGIC:              "pstorefs",            /* 0x6165676C local */
191	QNX4_SUPER_MAGIC:            "qnx4",                /* 0x002F local */
192	QNX6_SUPER_MAGIC:            "qnx6",                /* 0x68191122 local */
193	RAMFS_MAGIC:                 "ramfs",               /* 0x858458F6 local */
194	REISERFS_SUPER_MAGIC:        "reiserfs",            /* 0x52654973 local */
195	ROMFS_MAGIC:                 "romfs",               /* 0x7275 local */
196	RPC_PIPEFS_SUPER_MAGIC:      "rpc_pipefs",          /* 0x67596969 local */
197	SECURITYFS_SUPER_MAGIC:      "securityfs",          /* 0x73636673 local */
198	SELINUX_MAGIC:               "selinux",             /* 0xF97CFF8C local */
199	SMB_SUPER_MAGIC:             "smb",                 /* 0x517B remote */
200	SOCKFS_MAGIC:                "sockfs",              /* 0x534F434B local */
201	SQUASHFS_MAGIC:              "squashfs",            /* 0x73717368 local */
202	SYSFS_MAGIC:                 "sysfs",               /* 0x62656572 local */
203	SYSV2_SUPER_MAGIC:           "sysv2",               /* 0x012FF7B6 local */
204	SYSV4_SUPER_MAGIC:           "sysv4",               /* 0x012FF7B5 local */
205	TMPFS_MAGIC:                 "tmpfs",               /* 0x01021994 local */
206	UDF_SUPER_MAGIC:             "udf",                 /* 0x15013346 local */
207	UFS_MAGIC:                   "ufs",                 /* 0x00011954 local */
208	UFS_BYTESWAPPED_SUPER_MAGIC: "ufs",                 /* 0x54190100 local */
209	USBDEVICE_SUPER_MAGIC:       "usbdevfs",            /* 0x9FA2 local */
210	V9FS_MAGIC:                  "v9fs",                /* 0x01021997 local */
211	VMHGFS_SUPER_MAGIC:          "vmhgfs",              /* 0xBACBACBC remote */
212	VXFS_SUPER_MAGIC:            "vxfs",                /* 0xA501FCF5 local */
213	VZFS_SUPER_MAGIC:            "vzfs",                /* 0x565A4653 local */
214	XENFS_SUPER_MAGIC:           "xenfs",               /* 0xABBA1974 local */
215	XENIX_SUPER_MAGIC:           "xenix",               /* 0x012FF7B4 local */
216	XFS_SUPER_MAGIC:             "xfs",                 /* 0x58465342 local */
217	_XIAFS_SUPER_MAGIC:          "xia",                 /* 0x012FD16D local */
218	ZFS_SUPER_MAGIC:             "zfs",                 /* 0x2FC12FC1 local */
219}
220
221func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
222	useMounts := false
223
224	filename := common.HostProc("self/mountinfo")
225	lines, err := common.ReadLines(filename)
226	if err != nil {
227		if err != err.(*os.PathError) {
228			return nil, err
229		}
230		// if kernel does not support self/mountinfo, fallback to self/mounts (<2.6.26)
231		useMounts = true
232		filename = common.HostProc("self/mounts")
233		lines, err = common.ReadLines(filename)
234		if err != nil {
235			return nil, err
236		}
237	}
238
239	fs, err := getFileSystems()
240	if err != nil && !all {
241		return nil, err
242	}
243
244	ret := make([]PartitionStat, 0, len(lines))
245
246	for _, line := range lines {
247		var d PartitionStat
248		if useMounts {
249			fields := strings.Fields(line)
250
251			d = PartitionStat{
252				Device:     fields[0],
253				Mountpoint: unescapeFstab(fields[1]),
254				Fstype:     fields[2],
255				Opts:       fields[3],
256			}
257
258			if !all {
259				if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
260					continue
261				}
262			}
263		} else {
264			// a line of self/mountinfo has the following structure:
265			// 36  35  98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
266			// (1) (2) (3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
267
268			// split the mountinfo line by the separator hyphen
269			parts := strings.Split(line, " - ")
270			if len(parts) != 2 {
271				return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", filename, line)
272			}
273
274			fields := strings.Fields(parts[0])
275			blockDeviceID := fields[2]
276			mountPoint := fields[4]
277			mountOpts := fields[5]
278
279			if rootDir := fields[3]; rootDir != "" && rootDir != "/" {
280				if len(mountOpts) == 0 {
281					mountOpts = "bind"
282				} else {
283					mountOpts = "bind," + mountOpts
284				}
285			}
286
287			fields = strings.Fields(parts[1])
288			fstype := fields[0]
289			device := fields[1]
290
291			d = PartitionStat{
292				Device:     device,
293				Mountpoint: unescapeFstab(mountPoint),
294				Fstype:     fstype,
295				Opts:       mountOpts,
296			}
297
298			if !all {
299				if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
300					continue
301				}
302			}
303
304			if strings.HasPrefix(d.Device, "/dev/mapper/") {
305				devpath, err := filepath.EvalSymlinks(common.HostDev(strings.Replace(d.Device, "/dev", "", -1)))
306				if err == nil {
307					d.Device = devpath
308				}
309			}
310
311			// /dev/root is not the real device name
312			// so we get the real device name from its major/minor number
313			if d.Device == "/dev/root" {
314				devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID))
315				if err != nil {
316					return nil, err
317				}
318				d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1)
319			}
320		}
321		ret = append(ret, d)
322	}
323
324	return ret, nil
325}
326
327// getFileSystems returns supported filesystems from /proc/filesystems
328func getFileSystems() ([]string, error) {
329	filename := common.HostProc("filesystems")
330	lines, err := common.ReadLines(filename)
331	if err != nil {
332		return nil, err
333	}
334	var ret []string
335	for _, line := range lines {
336		if !strings.HasPrefix(line, "nodev") {
337			ret = append(ret, strings.TrimSpace(line))
338			continue
339		}
340		t := strings.Split(line, "\t")
341		if len(t) != 2 || t[1] != "zfs" {
342			continue
343		}
344		ret = append(ret, strings.TrimSpace(t[1]))
345	}
346
347	return ret, nil
348}
349
350func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
351	filename := common.HostProc("diskstats")
352	lines, err := common.ReadLines(filename)
353	if err != nil {
354		return nil, err
355	}
356	ret := make(map[string]IOCountersStat, 0)
357	empty := IOCountersStat{}
358
359	// use only basename such as "/dev/sda1" to "sda1"
360	for i, name := range names {
361		names[i] = filepath.Base(name)
362	}
363
364	for _, line := range lines {
365		fields := strings.Fields(line)
366		if len(fields) < 14 {
367			// malformed line in /proc/diskstats, avoid panic by ignoring.
368			continue
369		}
370		name := fields[2]
371
372		if len(names) > 0 && !common.StringsHas(names, name) {
373			continue
374		}
375
376		reads, err := strconv.ParseUint((fields[3]), 10, 64)
377		if err != nil {
378			return ret, err
379		}
380		mergedReads, err := strconv.ParseUint((fields[4]), 10, 64)
381		if err != nil {
382			return ret, err
383		}
384		rbytes, err := strconv.ParseUint((fields[5]), 10, 64)
385		if err != nil {
386			return ret, err
387		}
388		rtime, err := strconv.ParseUint((fields[6]), 10, 64)
389		if err != nil {
390			return ret, err
391		}
392		writes, err := strconv.ParseUint((fields[7]), 10, 64)
393		if err != nil {
394			return ret, err
395		}
396		mergedWrites, err := strconv.ParseUint((fields[8]), 10, 64)
397		if err != nil {
398			return ret, err
399		}
400		wbytes, err := strconv.ParseUint((fields[9]), 10, 64)
401		if err != nil {
402			return ret, err
403		}
404		wtime, err := strconv.ParseUint((fields[10]), 10, 64)
405		if err != nil {
406			return ret, err
407		}
408		iopsInProgress, err := strconv.ParseUint((fields[11]), 10, 64)
409		if err != nil {
410			return ret, err
411		}
412		iotime, err := strconv.ParseUint((fields[12]), 10, 64)
413		if err != nil {
414			return ret, err
415		}
416		weightedIO, err := strconv.ParseUint((fields[13]), 10, 64)
417		if err != nil {
418			return ret, err
419		}
420		d := IOCountersStat{
421			ReadBytes:        rbytes * SectorSize,
422			WriteBytes:       wbytes * SectorSize,
423			ReadCount:        reads,
424			WriteCount:       writes,
425			MergedReadCount:  mergedReads,
426			MergedWriteCount: mergedWrites,
427			ReadTime:         rtime,
428			WriteTime:        wtime,
429			IopsInProgress:   iopsInProgress,
430			IoTime:           iotime,
431			WeightedIO:       weightedIO,
432		}
433		if d == empty {
434			continue
435		}
436		d.Name = name
437
438		d.SerialNumber = GetDiskSerialNumber(name)
439		d.Label = GetLabel(name)
440
441		ret[name] = d
442	}
443	return ret, nil
444}
445
446// GetDiskSerialNumber returns Serial Number of given device or empty string
447// on error. Name of device is expected, eg. /dev/sda
448func GetDiskSerialNumber(name string) string {
449	return GetDiskSerialNumberWithContext(context.Background(), name)
450}
451
452func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
453	var stat unix.Stat_t
454	err := unix.Stat(name, &stat)
455	if err != nil {
456		return ""
457	}
458	major := unix.Major(uint64(stat.Rdev))
459	minor := unix.Minor(uint64(stat.Rdev))
460
461	// Try to get the serial from udev data
462	udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor))
463	if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
464		scanner := bufio.NewScanner(bytes.NewReader(udevdata))
465		for scanner.Scan() {
466			values := strings.Split(scanner.Text(), "=")
467			if len(values) == 2 && values[0] == "E:ID_SERIAL" {
468				return values[1]
469			}
470		}
471	}
472
473	// Try to get the serial from sysfs, look at the disk device (minor 0) directly
474	// because if it is a partition it is not going to contain any device information
475	devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major))
476	model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
477	serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
478	if len(model) > 0 && len(serial) > 0 {
479		return fmt.Sprintf("%s_%s", string(model), string(serial))
480	}
481	return ""
482}
483
484// GetLabel returns label of given device or empty string on error.
485// Name of device is expected, eg. /dev/sda
486// Supports label based on devicemapper name
487// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
488func GetLabel(name string) string {
489	// Try label based on devicemapper name
490	dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
491
492	if !common.PathExists(dmname_filename) {
493		return ""
494	}
495
496	dmname, err := ioutil.ReadFile(dmname_filename)
497	if err != nil {
498		return ""
499	} else {
500		return strings.TrimSpace(string(dmname))
501	}
502}
503
504func getFsType(stat unix.Statfs_t) string {
505	t := int64(stat.Type)
506	ret, ok := fsTypeMap[t]
507	if !ok {
508		return ""
509	}
510	return ret
511}
512