comparison vendor/golang.org/x/sys/unix/syscall_solaris.go @ 68:4b79810863f6 draft

Ready to release 0.6.0 Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Wed, 13 Sep 2023 10:49:50 +0000
parents 787b5ee0289d
children
comparison
equal deleted inserted replaced
67:4edfa07d5fe0 68:4b79810863f6
748 // the user hasn't requested/received it yet. 748 // the user hasn't requested/received it yet.
749 // If the user wants to port_dissociate before the event has been processed, 749 // If the user wants to port_dissociate before the event has been processed,
750 // we should handle things gracefully. To do so, we need to keep an extra 750 // we should handle things gracefully. To do so, we need to keep an extra
751 // reference to the cookie around until the event is processed 751 // reference to the cookie around until the event is processed
752 // thus the otherwise seemingly extraneous "cookies" map 752 // thus the otherwise seemingly extraneous "cookies" map
753 // The key of this map is a pointer to the corresponding &fCookie.cookie 753 // The key of this map is a pointer to the corresponding fCookie
754 cookies map[*interface{}]*fileObjCookie 754 cookies map[*fileObjCookie]struct{}
755 } 755 }
756 756
757 // PortEvent is an abstraction of the port_event C struct. 757 // PortEvent is an abstraction of the port_event C struct.
758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD 758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
759 // to see if Path or Fd was the event source. The other will be 759 // to see if Path or Fd was the event source. The other will be
776 } 776 }
777 e := &EventPort{ 777 e := &EventPort{
778 port: port, 778 port: port,
779 fds: make(map[uintptr]*fileObjCookie), 779 fds: make(map[uintptr]*fileObjCookie),
780 paths: make(map[string]*fileObjCookie), 780 paths: make(map[string]*fileObjCookie),
781 cookies: make(map[*interface{}]*fileObjCookie), 781 cookies: make(map[*fileObjCookie]struct{}),
782 } 782 }
783 return e, nil 783 return e, nil
784 } 784 }
785 785
786 //sys port_create() (n int, err error) 786 //sys port_create() (n int, err error)
797 if err != nil { 797 if err != nil {
798 return err 798 return err
799 } 799 }
800 e.fds = nil 800 e.fds = nil
801 e.paths = nil 801 e.paths = nil
802 e.cookies = nil
802 return nil 803 return nil
803 } 804 }
804 805
805 // PathIsWatched checks to see if path is associated with this EventPort. 806 // PathIsWatched checks to see if path is associated with this EventPort.
806 func (e *EventPort) PathIsWatched(path string) bool { 807 func (e *EventPort) PathIsWatched(path string) bool {
824 e.mu.Lock() 825 e.mu.Lock()
825 defer e.mu.Unlock() 826 defer e.mu.Unlock()
826 if _, found := e.paths[path]; found { 827 if _, found := e.paths[path]; found {
827 return fmt.Errorf("%v is already associated with this Event Port", path) 828 return fmt.Errorf("%v is already associated with this Event Port", path)
828 } 829 }
829 fobj, err := createFileObj(path, stat) 830 fCookie, err := createFileObjCookie(path, stat, cookie)
830 if err != nil { 831 if err != nil {
831 return err 832 return err
832 } 833 }
833 fCookie := &fileObjCookie{fobj, cookie} 834 _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
834 _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
835 if err != nil { 835 if err != nil {
836 return err 836 return err
837 } 837 }
838 e.paths[path] = fCookie 838 e.paths[path] = fCookie
839 e.cookies[&fCookie.cookie] = fCookie 839 e.cookies[fCookie] = struct{}{}
840 return nil 840 return nil
841 } 841 }
842 842
843 // DissociatePath wraps port_dissociate(3c) for a filesystem path. 843 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
844 func (e *EventPort) DissociatePath(path string) error { 844 func (e *EventPort) DissociatePath(path string) error {
856 return err 856 return err
857 } 857 }
858 if err == nil { 858 if err == nil {
859 // dissociate was successful, safe to delete the cookie 859 // dissociate was successful, safe to delete the cookie
860 fCookie := e.paths[path] 860 fCookie := e.paths[path]
861 delete(e.cookies, &fCookie.cookie) 861 delete(e.cookies, fCookie)
862 } 862 }
863 delete(e.paths, path) 863 delete(e.paths, path)
864 return err 864 return err
865 } 865 }
866 866
869 e.mu.Lock() 869 e.mu.Lock()
870 defer e.mu.Unlock() 870 defer e.mu.Unlock()
871 if _, found := e.fds[fd]; found { 871 if _, found := e.fds[fd]; found {
872 return fmt.Errorf("%v is already associated with this Event Port", fd) 872 return fmt.Errorf("%v is already associated with this Event Port", fd)
873 } 873 }
874 fCookie := &fileObjCookie{nil, cookie} 874 fCookie, err := createFileObjCookie("", nil, cookie)
875 _, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
876 if err != nil { 875 if err != nil {
877 return err 876 return err
878 } 877 }
878 _, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
879 if err != nil {
880 return err
881 }
879 e.fds[fd] = fCookie 882 e.fds[fd] = fCookie
880 e.cookies[&fCookie.cookie] = fCookie 883 e.cookies[fCookie] = struct{}{}
881 return nil 884 return nil
882 } 885 }
883 886
884 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors. 887 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
885 func (e *EventPort) DissociateFd(fd uintptr) error { 888 func (e *EventPort) DissociateFd(fd uintptr) error {
894 return err 897 return err
895 } 898 }
896 if err == nil { 899 if err == nil {
897 // dissociate was successful, safe to delete the cookie 900 // dissociate was successful, safe to delete the cookie
898 fCookie := e.fds[fd] 901 fCookie := e.fds[fd]
899 delete(e.cookies, &fCookie.cookie) 902 delete(e.cookies, fCookie)
900 } 903 }
901 delete(e.fds, fd) 904 delete(e.fds, fd)
902 return err 905 return err
903 } 906 }
904 907
905 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) { 908 func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
906 fobj := new(fileObj) 909 fCookie := new(fileObjCookie)
907 bs, err := ByteSliceFromString(name) 910 fCookie.cookie = cookie
908 if err != nil { 911 if name != "" && stat != nil {
909 return nil, err 912 fCookie.fobj = new(fileObj)
910 } 913 bs, err := ByteSliceFromString(name)
911 fobj.Name = (*int8)(unsafe.Pointer(&bs[0])) 914 if err != nil {
912 s := stat.Sys().(*syscall.Stat_t) 915 return nil, err
913 fobj.Atim.Sec = s.Atim.Sec 916 }
914 fobj.Atim.Nsec = s.Atim.Nsec 917 fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
915 fobj.Mtim.Sec = s.Mtim.Sec 918 s := stat.Sys().(*syscall.Stat_t)
916 fobj.Mtim.Nsec = s.Mtim.Nsec 919 fCookie.fobj.Atim.Sec = s.Atim.Sec
917 fobj.Ctim.Sec = s.Ctim.Sec 920 fCookie.fobj.Atim.Nsec = s.Atim.Nsec
918 fobj.Ctim.Nsec = s.Ctim.Nsec 921 fCookie.fobj.Mtim.Sec = s.Mtim.Sec
919 return fobj, nil 922 fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
923 fCookie.fobj.Ctim.Sec = s.Ctim.Sec
924 fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
925 }
926 return fCookie, nil
920 } 927 }
921 928
922 // GetOne wraps port_get(3c) and returns a single PortEvent. 929 // GetOne wraps port_get(3c) and returns a single PortEvent.
923 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) { 930 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
924 pe := new(portEvent) 931 pe := new(portEvent)
927 return nil, err 934 return nil, err
928 } 935 }
929 p := new(PortEvent) 936 p := new(PortEvent)
930 e.mu.Lock() 937 e.mu.Lock()
931 defer e.mu.Unlock() 938 defer e.mu.Unlock()
932 e.peIntToExt(pe, p) 939 err = e.peIntToExt(pe, p)
940 if err != nil {
941 return nil, err
942 }
933 return p, nil 943 return p, nil
934 } 944 }
935 945
936 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent 946 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
937 // NOTE: Always call this function while holding the e.mu mutex 947 // NOTE: Always call this function while holding the e.mu mutex
938 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) { 948 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
949 if e.cookies == nil {
950 return fmt.Errorf("this EventPort is already closed")
951 }
939 peExt.Events = peInt.Events 952 peExt.Events = peInt.Events
940 peExt.Source = peInt.Source 953 peExt.Source = peInt.Source
941 cookie := (*interface{})(unsafe.Pointer(peInt.User)) 954 fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
942 peExt.Cookie = *cookie 955 _, found := e.cookies[fCookie]
956
957 if !found {
958 panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
959 }
960 peExt.Cookie = fCookie.cookie
961 delete(e.cookies, fCookie)
962
943 switch peInt.Source { 963 switch peInt.Source {
944 case PORT_SOURCE_FD: 964 case PORT_SOURCE_FD:
945 delete(e.cookies, cookie)
946 peExt.Fd = uintptr(peInt.Object) 965 peExt.Fd = uintptr(peInt.Object)
947 // Only remove the fds entry if it exists and this cookie matches 966 // Only remove the fds entry if it exists and this cookie matches
948 if fobj, ok := e.fds[peExt.Fd]; ok { 967 if fobj, ok := e.fds[peExt.Fd]; ok {
949 if &fobj.cookie == cookie { 968 if fobj == fCookie {
950 delete(e.fds, peExt.Fd) 969 delete(e.fds, peExt.Fd)
951 } 970 }
952 } 971 }
953 case PORT_SOURCE_FILE: 972 case PORT_SOURCE_FILE:
954 if fCookie, ok := e.cookies[cookie]; ok && uintptr(unsafe.Pointer(fCookie.fobj)) == uintptr(peInt.Object) { 973 peExt.fobj = fCookie.fobj
955 // Use our stashed reference rather than using unsafe on what we got back
956 // the unsafe version would be (*fileObj)(unsafe.Pointer(uintptr(peInt.Object)))
957 peExt.fobj = fCookie.fobj
958 } else {
959 panic("mismanaged memory")
960 }
961 delete(e.cookies, cookie)
962 peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name))) 974 peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
963 // Only remove the paths entry if it exists and this cookie matches 975 // Only remove the paths entry if it exists and this cookie matches
964 if fobj, ok := e.paths[peExt.Path]; ok { 976 if fobj, ok := e.paths[peExt.Path]; ok {
965 if &fobj.cookie == cookie { 977 if fobj == fCookie {
966 delete(e.paths, peExt.Path) 978 delete(e.paths, peExt.Path)
967 } 979 }
968 } 980 }
969 } 981 }
982 return nil
970 } 983 }
971 984
972 // Pending wraps port_getn(3c) and returns how many events are pending. 985 // Pending wraps port_getn(3c) and returns how many events are pending.
973 func (e *EventPort) Pending() (int, error) { 986 func (e *EventPort) Pending() (int, error) {
974 var n uint32 = 0 987 var n uint32 = 0
988 return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min) 1001 return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
989 } 1002 }
990 got := uint32(min) 1003 got := uint32(min)
991 max := uint32(len(s)) 1004 max := uint32(len(s))
992 var err error 1005 var err error
993 ps := make([]portEvent, max, max) 1006 ps := make([]portEvent, max)
994 _, err = port_getn(e.port, &ps[0], max, &got, timeout) 1007 _, err = port_getn(e.port, &ps[0], max, &got, timeout)
995 // got will be trustworthy with ETIME, but not any other error. 1008 // got will be trustworthy with ETIME, but not any other error.
996 if err != nil && err != ETIME { 1009 if err != nil && err != ETIME {
997 return 0, err 1010 return 0, err
998 } 1011 }
999 e.mu.Lock() 1012 e.mu.Lock()
1000 defer e.mu.Unlock() 1013 defer e.mu.Unlock()
1014 valid := 0
1001 for i := 0; i < int(got); i++ { 1015 for i := 0; i < int(got); i++ {
1002 e.peIntToExt(&ps[i], &s[i]) 1016 err2 := e.peIntToExt(&ps[i], &s[i])
1003 } 1017 if err2 != nil {
1004 return int(got), err 1018 if valid == 0 && err == nil {
1005 } 1019 // If err2 is the only error and there are no valid events
1020 // to return, return it to the caller.
1021 err = err2
1022 }
1023 break
1024 }
1025 valid = i + 1
1026 }
1027 return valid, err
1028 }
1029
1030 //sys putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
1031
1032 func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
1033 var clp, datap *strbuf
1034 if len(cl) > 0 {
1035 clp = &strbuf{
1036 Len: int32(len(cl)),
1037 Buf: (*int8)(unsafe.Pointer(&cl[0])),
1038 }
1039 }
1040 if len(data) > 0 {
1041 datap = &strbuf{
1042 Len: int32(len(data)),
1043 Buf: (*int8)(unsafe.Pointer(&data[0])),
1044 }
1045 }
1046 return putmsg(fd, clp, datap, flags)
1047 }
1048
1049 //sys getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
1050
1051 func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
1052 var clp, datap *strbuf
1053 if len(cl) > 0 {
1054 clp = &strbuf{
1055 Maxlen: int32(len(cl)),
1056 Buf: (*int8)(unsafe.Pointer(&cl[0])),
1057 }
1058 }
1059 if len(data) > 0 {
1060 datap = &strbuf{
1061 Maxlen: int32(len(data)),
1062 Buf: (*int8)(unsafe.Pointer(&data[0])),
1063 }
1064 }
1065
1066 if err = getmsg(fd, clp, datap, &flags); err != nil {
1067 return nil, nil, 0, err
1068 }
1069
1070 if len(cl) > 0 {
1071 retCl = cl[:clp.Len]
1072 }
1073 if len(data) > 0 {
1074 retData = data[:datap.Len]
1075 }
1076 return retCl, retData, flags, nil
1077 }
1078
1079 func IoctlSetIntRetInt(fd int, req uint, arg int) (int, error) {
1080 return ioctlRet(fd, req, uintptr(arg))
1081 }
1082
1083 func IoctlSetString(fd int, req uint, val string) error {
1084 bs := make([]byte, len(val)+1)
1085 copy(bs[:len(bs)-1], val)
1086 err := ioctl(fd, req, uintptr(unsafe.Pointer(&bs[0])))
1087 runtime.KeepAlive(&bs[0])
1088 return err
1089 }
1090
1091 // Lifreq Helpers
1092
1093 func (l *Lifreq) SetName(name string) error {
1094 if len(name) >= len(l.Name) {
1095 return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
1096 }
1097 for i := range name {
1098 l.Name[i] = int8(name[i])
1099 }
1100 return nil
1101 }
1102
1103 func (l *Lifreq) SetLifruInt(d int) {
1104 *(*int)(unsafe.Pointer(&l.Lifru[0])) = d
1105 }
1106
1107 func (l *Lifreq) GetLifruInt() int {
1108 return *(*int)(unsafe.Pointer(&l.Lifru[0]))
1109 }
1110
1111 func (l *Lifreq) SetLifruUint(d uint) {
1112 *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
1113 }
1114
1115 func (l *Lifreq) GetLifruUint() uint {
1116 return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
1117 }
1118
1119 func IoctlLifreq(fd int, req uint, l *Lifreq) error {
1120 return ioctl(fd, req, uintptr(unsafe.Pointer(l)))
1121 }
1122
1123 // Strioctl Helpers
1124
1125 func (s *Strioctl) SetInt(i int) {
1126 s.Len = int32(unsafe.Sizeof(i))
1127 s.Dp = (*int8)(unsafe.Pointer(&i))
1128 }
1129
1130 func IoctlSetStrioctlRetInt(fd int, req uint, s *Strioctl) (int, error) {
1131 return ioctlRet(fd, req, uintptr(unsafe.Pointer(s)))
1132 }