Mercurial > yakumo_izuru > aya
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 } |