1// Copyright 2020 The Go Authors. All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5//go:build zos && s390x
  6// +build zos,s390x
  7
  8package unix
  9
 10import (
 11	"unsafe"
 12)
 13
 14// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
 15
 16func Fstatfs(fd int, stat *Statfs_t) (err error) {
 17	var stat_v Statvfs_t
 18	err = Fstatvfs(fd, &stat_v)
 19	if err == nil {
 20		// populate stat
 21		stat.Type = 0
 22		stat.Bsize = stat_v.Bsize
 23		stat.Blocks = stat_v.Blocks
 24		stat.Bfree = stat_v.Bfree
 25		stat.Bavail = stat_v.Bavail
 26		stat.Files = stat_v.Files
 27		stat.Ffree = stat_v.Ffree
 28		stat.Fsid = stat_v.Fsid
 29		stat.Namelen = stat_v.Namemax
 30		stat.Frsize = stat_v.Frsize
 31		stat.Flags = stat_v.Flag
 32		for passn := 0; passn < 5; passn++ {
 33			switch passn {
 34			case 0:
 35				err = tryGetmntent64(stat)
 36				break
 37			case 1:
 38				err = tryGetmntent128(stat)
 39				break
 40			case 2:
 41				err = tryGetmntent256(stat)
 42				break
 43			case 3:
 44				err = tryGetmntent512(stat)
 45				break
 46			case 4:
 47				err = tryGetmntent1024(stat)
 48				break
 49			default:
 50				break
 51			}
 52			//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
 53			if err == nil || err != nil && err != ERANGE {
 54				break
 55			}
 56		}
 57	}
 58	return err
 59}
 60
 61func tryGetmntent64(stat *Statfs_t) (err error) {
 62	var mnt_ent_buffer struct {
 63		header       W_Mnth
 64		filesys_info [64]W_Mntent
 65	}
 66	var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
 67	fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
 68	if err != nil {
 69		return err
 70	}
 71	err = ERANGE //return ERANGE if no match is found in this batch
 72	for i := 0; i < fs_count; i++ {
 73		if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
 74			stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
 75			err = nil
 76			break
 77		}
 78	}
 79	return err
 80}
 81
 82func tryGetmntent128(stat *Statfs_t) (err error) {
 83	var mnt_ent_buffer struct {
 84		header       W_Mnth
 85		filesys_info [128]W_Mntent
 86	}
 87	var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
 88	fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
 89	if err != nil {
 90		return err
 91	}
 92	err = ERANGE //return ERANGE if no match is found in this batch
 93	for i := 0; i < fs_count; i++ {
 94		if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
 95			stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
 96			err = nil
 97			break
 98		}
 99	}
100	return err
101}
102
103func tryGetmntent256(stat *Statfs_t) (err error) {
104	var mnt_ent_buffer struct {
105		header       W_Mnth
106		filesys_info [256]W_Mntent
107	}
108	var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
109	fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
110	if err != nil {
111		return err
112	}
113	err = ERANGE //return ERANGE if no match is found in this batch
114	for i := 0; i < fs_count; i++ {
115		if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
116			stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
117			err = nil
118			break
119		}
120	}
121	return err
122}
123
124func tryGetmntent512(stat *Statfs_t) (err error) {
125	var mnt_ent_buffer struct {
126		header       W_Mnth
127		filesys_info [512]W_Mntent
128	}
129	var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
130	fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
131	if err != nil {
132		return err
133	}
134	err = ERANGE //return ERANGE if no match is found in this batch
135	for i := 0; i < fs_count; i++ {
136		if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
137			stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
138			err = nil
139			break
140		}
141	}
142	return err
143}
144
145func tryGetmntent1024(stat *Statfs_t) (err error) {
146	var mnt_ent_buffer struct {
147		header       W_Mnth
148		filesys_info [1024]W_Mntent
149	}
150	var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
151	fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
152	if err != nil {
153		return err
154	}
155	err = ERANGE //return ERANGE if no match is found in this batch
156	for i := 0; i < fs_count; i++ {
157		if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
158			stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
159			err = nil
160			break
161		}
162	}
163	return err
164}