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
221// Partitions returns disk partitions. If all is false, returns
222// physical devices only (e.g. hard disks, cd-rom drives, USB keys)
223// and ignore all others (e.g. memory partitions such as /dev/shm)
224func Partitions(all bool) ([]PartitionStat, error) {
225	return PartitionsWithContext(context.Background(), all)
226}
227
228func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
229	useMounts := false
230
231	filename := common.HostProc("self/mountinfo")
232	lines, err := common.ReadLines(filename)
233	if err != nil {
234		if err != err.(*os.PathError) {
235			return nil, err
236		}
237		// if kernel does not support self/mountinfo, fallback to self/mounts (<2.6.26)
238		useMounts = true
239		filename = common.HostProc("self/mounts")
240		lines, err = common.ReadLines(filename)
241		if err != nil {
242			return nil, err
243		}
244	}
245
246	fs, err := getFileSystems()
247	if err != nil && !all {
248		return nil, err
249	}
250
251	ret := make([]PartitionStat, 0, len(lines))
252
253	for _, line := range lines {
254		var d PartitionStat
255		if useMounts {
256			fields := strings.Fields(line)
257
258			d = PartitionStat{
259				Device:     fields[0],
260				Mountpoint: unescapeFstab(fields[1]),
261				Fstype:     fields[2],
262				Opts:       fields[3],
263			}
264
265			if !all {
266				if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
267					continue
268				}
269			}
270		} else {
271			// a line of self/mountinfo has the following structure:
272			// 36  35  98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
273			// (1) (2) (3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
274
275			// split the mountinfo line by the separator hyphen
276			parts := strings.Split(line, " - ")
277			if len(parts) != 2 {
278				return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", filename, line)
279			}
280
281			fields := strings.Fields(parts[0])
282			blockDeviceID := fields[2]
283			mountPoint := fields[4]
284			mountOpts := fields[5]
285
286			fields = strings.Fields(parts[1])
287			fstype := fields[0]
288			device := fields[1]
289
290			d = PartitionStat{
291				Device:     device,
292				Mountpoint: unescapeFstab(mountPoint),
293				Fstype:     fstype,
294				Opts:       mountOpts,
295			}
296
297			if !all {
298				if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
299					continue
300				}
301			}
302
303			if strings.HasPrefix(d.Device, "/dev/mapper/") {
304				devpath, err := filepath.EvalSymlinks(d.Device)
305				if err == nil {
306					d.Device = devpath
307				}
308			}
309
310			// /dev/root is not the real device name
311			// so we get the real device name from its major/minor number
312			if d.Device == "/dev/root" {
313				devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID))
314				if err != nil {
315					return nil, err
316				}
317				d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1)
318			}
319		}
320		ret = append(ret, d)
321	}
322
323	return ret, nil
324}
325
326// getFileSystems returns supported filesystems from /proc/filesystems
327func getFileSystems() ([]string, error) {
328	filename := common.HostProc("filesystems")
329	lines, err := common.ReadLines(filename)
330	if err != nil {
331		return nil, err
332	}
333	var ret []string
334	for _, line := range lines {
335		if !strings.HasPrefix(line, "nodev") {
336			ret = append(ret, strings.TrimSpace(line))
337			continue
338		}
339		t := strings.Split(line, "\t")
340		if len(t) != 2 || t[1] != "zfs" {
341			continue
342		}
343		ret = append(ret, strings.TrimSpace(t[1]))
344	}
345
346	return ret, nil
347}
348
349func IOCounters(names ...string) (map[string]IOCountersStat, error) {
350	return IOCountersWithContext(context.Background(), names...)
351}
352
353func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
354	filename := common.HostProc("diskstats")
355	lines, err := common.ReadLines(filename)
356	if err != nil {
357		return nil, err
358	}
359	ret := make(map[string]IOCountersStat, 0)
360	empty := IOCountersStat{}
361
362	// use only basename such as "/dev/sda1" to "sda1"
363	for i, name := range names {
364		names[i] = filepath.Base(name)
365	}
366
367	for _, line := range lines {
368		fields := strings.Fields(line)
369		if len(fields) < 14 {
370			// malformed line in /proc/diskstats, avoid panic by ignoring.
371			continue
372		}
373		name := fields[2]
374
375		if len(names) > 0 && !common.StringsHas(names, name) {
376			continue
377		}
378
379		reads, err := strconv.ParseUint((fields[3]), 10, 64)
380		if err != nil {
381			return ret, err
382		}
383		mergedReads, err := strconv.ParseUint((fields[4]), 10, 64)
384		if err != nil {
385			return ret, err
386		}
387		rbytes, err := strconv.ParseUint((fields[5]), 10, 64)
388		if err != nil {
389			return ret, err
390		}
391		rtime, err := strconv.ParseUint((fields[6]), 10, 64)
392		if err != nil {
393			return ret, err
394		}
395		writes, err := strconv.ParseUint((fields[7]), 10, 64)
396		if err != nil {
397			return ret, err
398		}
399		mergedWrites, err := strconv.ParseUint((fields[8]), 10, 64)
400		if err != nil {
401			return ret, err
402		}
403		wbytes, err := strconv.ParseUint((fields[9]), 10, 64)
404		if err != nil {
405			return ret, err
406		}
407		wtime, err := strconv.ParseUint((fields[10]), 10, 64)
408		if err != nil {
409			return ret, err
410		}
411		iopsInProgress, err := strconv.ParseUint((fields[11]), 10, 64)
412		if err != nil {
413			return ret, err
414		}
415		iotime, err := strconv.ParseUint((fields[12]), 10, 64)
416		if err != nil {
417			return ret, err
418		}
419		weightedIO, err := strconv.ParseUint((fields[13]), 10, 64)
420		if err != nil {
421			return ret, err
422		}
423		d := IOCountersStat{
424			ReadBytes:        rbytes * SectorSize,
425			WriteBytes:       wbytes * SectorSize,
426			ReadCount:        reads,
427			WriteCount:       writes,
428			MergedReadCount:  mergedReads,
429			MergedWriteCount: mergedWrites,
430			ReadTime:         rtime,
431			WriteTime:        wtime,
432			IopsInProgress:   iopsInProgress,
433			IoTime:           iotime,
434			WeightedIO:       weightedIO,
435		}
436		if d == empty {
437			continue
438		}
439		d.Name = name
440
441		d.SerialNumber = GetDiskSerialNumber(name)
442		d.Label = GetLabel(name)
443
444		ret[name] = d
445	}
446	return ret, nil
447}
448
449// GetDiskSerialNumber returns Serial Number of given device or empty string
450// on error. Name of device is expected, eg. /dev/sda
451func GetDiskSerialNumber(name string) string {
452	return GetDiskSerialNumberWithContext(context.Background(), name)
453}
454
455func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
456	var stat unix.Stat_t
457	err := unix.Stat(name, &stat)
458	if err != nil {
459		return ""
460	}
461	major := unix.Major(uint64(stat.Rdev))
462	minor := unix.Minor(uint64(stat.Rdev))
463
464	// Try to get the serial from udev data
465	udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor))
466	if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
467		scanner := bufio.NewScanner(bytes.NewReader(udevdata))
468		for scanner.Scan() {
469			values := strings.Split(scanner.Text(), "=")
470			if len(values) == 2 && values[0] == "E:ID_SERIAL" {
471				return values[1]
472			}
473		}
474	}
475
476	// Try to get the serial from sysfs, look at the disk device (minor 0) directly
477	// because if it is a partition it is not going to contain any device information
478	devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major))
479	model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
480	serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
481	if len(model) > 0 && len(serial) > 0 {
482		return fmt.Sprintf("%s_%s", string(model), string(serial))
483	}
484	return ""
485}
486
487// GetLabel returns label of given device or empty string on error.
488// Name of device is expected, eg. /dev/sda
489// Supports label based on devicemapper name
490// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
491func GetLabel(name string) string {
492	// Try label based on devicemapper name
493	dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
494
495	if !common.PathExists(dmname_filename) {
496		return ""
497	}
498
499	dmname, err := ioutil.ReadFile(dmname_filename)
500	if err != nil {
501		return ""
502	} else {
503		return strings.TrimSpace(string(dmname))
504	}
505}
506
507func getFsType(stat unix.Statfs_t) string {
508	t := int64(stat.Type)
509	ret, ok := fsTypeMap[t]
510	if !ok {
511		return ""
512	}
513	return ret
514}
515