libc_unix.go 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. // Copyright 2020 The Libc 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. //go:build unix && !(linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm))
  5. package libc // import "modernc.org/libc"
  6. import (
  7. "bufio"
  8. // "encoding/hex"
  9. "math"
  10. "math/rand"
  11. "os"
  12. gosignal "os/signal"
  13. "reflect"
  14. "runtime"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "time"
  19. "unsafe"
  20. guuid "github.com/google/uuid"
  21. "github.com/ncruces/go-strftime"
  22. "golang.org/x/sys/unix"
  23. "modernc.org/libc/errno"
  24. "modernc.org/libc/grp"
  25. "modernc.org/libc/limits"
  26. "modernc.org/libc/poll"
  27. "modernc.org/libc/pwd"
  28. "modernc.org/libc/signal"
  29. "modernc.org/libc/stdio"
  30. "modernc.org/libc/stdlib"
  31. "modernc.org/libc/sys/types"
  32. ctime "modernc.org/libc/time"
  33. )
  34. var staticGetpwnam pwd.Passwd
  35. func init() {
  36. atExit = append(atExit, func() { closePasswd(&staticGetpwnam) })
  37. }
  38. // sighandler_t signal(int signum, sighandler_t handler);
  39. func Xsignal(t *TLS, signum int32, handler uintptr) uintptr { //TODO use sigaction?
  40. if __ccgo_strace {
  41. trc("t=%v signum=%v handler=%v, (%v:)", t, signum, handler, origin(2))
  42. }
  43. signalsMu.Lock()
  44. defer signalsMu.Unlock()
  45. r := signals[signum]
  46. signals[signum] = handler
  47. switch handler {
  48. case signal.SIG_DFL:
  49. panic(todo("%v %#x", unix.Signal(signum), handler))
  50. case signal.SIG_IGN:
  51. switch r {
  52. case signal.SIG_DFL:
  53. gosignal.Ignore(unix.Signal(signum)) //TODO
  54. case signal.SIG_IGN:
  55. gosignal.Ignore(unix.Signal(signum))
  56. default:
  57. panic(todo("%v %#x", unix.Signal(signum), handler))
  58. }
  59. default:
  60. switch r {
  61. case signal.SIG_DFL:
  62. c := make(chan os.Signal, 1)
  63. gosignal.Notify(c, unix.Signal(signum))
  64. go func() { //TODO mechanism to stop/cancel
  65. for {
  66. <-c
  67. var f func(*TLS, int32)
  68. *(*uintptr)(unsafe.Pointer(&f)) = handler
  69. tls := NewTLS()
  70. f(tls, signum)
  71. tls.Close()
  72. }
  73. }()
  74. case signal.SIG_IGN:
  75. panic(todo("%v %#x", unix.Signal(signum), handler))
  76. default:
  77. panic(todo("%v %#x", unix.Signal(signum), handler))
  78. }
  79. }
  80. return r
  81. }
  82. // void rewind(FILE *stream);
  83. func Xrewind(t *TLS, stream uintptr) {
  84. if __ccgo_strace {
  85. trc("t=%v stream=%v, (%v:)", t, stream, origin(2))
  86. }
  87. Xfseek(t, stream, 0, stdio.SEEK_SET)
  88. }
  89. // int putchar(int c);
  90. func Xputchar(t *TLS, c int32) int32 {
  91. if __ccgo_strace {
  92. trc("t=%v c=%v, (%v:)", t, c, origin(2))
  93. }
  94. if _, err := write([]byte{byte(c)}); err != nil {
  95. return stdio.EOF
  96. }
  97. return int32(c)
  98. }
  99. // int gethostname(char *name, size_t len);
  100. func Xgethostname(t *TLS, name uintptr, slen types.Size_t) int32 {
  101. if __ccgo_strace {
  102. trc("t=%v name=%v slen=%v, (%v:)", t, name, slen, origin(2))
  103. }
  104. if slen == 0 {
  105. return 0
  106. }
  107. s, err := os.Hostname()
  108. if err != nil {
  109. panic(todo(""))
  110. }
  111. n := len(s)
  112. if len(s) >= int(slen) {
  113. n = int(slen) - 1
  114. }
  115. sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
  116. copy((*RawMem)(unsafe.Pointer(name))[:n:n], (*RawMem)(unsafe.Pointer(sh.Data))[:n:n])
  117. *(*byte)(unsafe.Pointer(name + uintptr(n))) = 0
  118. return 0
  119. }
  120. // int remove(const char *pathname);
  121. func Xremove(t *TLS, pathname uintptr) int32 {
  122. if __ccgo_strace {
  123. trc("t=%v pathname=%v, (%v:)", t, pathname, origin(2))
  124. }
  125. if err := os.Remove(GoString(pathname)); err != nil {
  126. t.setErrno(err)
  127. return -1
  128. }
  129. return 0
  130. }
  131. // long pathconf(const char *path, int name);
  132. func Xpathconf(t *TLS, path uintptr, name int32) long {
  133. if __ccgo_strace {
  134. trc("t=%v path=%v name=%v, (%v:)", t, path, name, origin(2))
  135. }
  136. panic(todo(""))
  137. }
  138. // ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
  139. func Xrecvfrom(t *TLS, sockfd int32, buf uintptr, len types.Size_t, flags int32, src_addr, addrlen uintptr) types.Ssize_t {
  140. if __ccgo_strace {
  141. trc("t=%v sockfd=%v buf=%v len=%v flags=%v addrlen=%v, (%v:)", t, sockfd, buf, len, flags, addrlen, origin(2))
  142. }
  143. panic(todo(""))
  144. }
  145. // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
  146. func Xsendto(t *TLS, sockfd int32, buf uintptr, len types.Size_t, flags int32, src_addr uintptr, addrlen socklen_t) types.Ssize_t {
  147. if __ccgo_strace {
  148. trc("t=%v sockfd=%v buf=%v len=%v flags=%v src_addr=%v addrlen=%v, (%v:)", t, sockfd, buf, len, flags, src_addr, addrlen, origin(2))
  149. }
  150. panic(todo(""))
  151. }
  152. // void srand48(long int seedval);
  153. func Xsrand48(t *TLS, seedval long) {
  154. if __ccgo_strace {
  155. trc("t=%v seedval=%v, (%v:)", t, seedval, origin(2))
  156. }
  157. panic(todo(""))
  158. }
  159. // long int lrand48(void);
  160. func Xlrand48(t *TLS) long {
  161. if __ccgo_strace {
  162. trc("t=%v, (%v:)", t, origin(2))
  163. }
  164. panic(todo(""))
  165. }
  166. // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
  167. func Xsendmsg(t *TLS, sockfd int32, msg uintptr, flags int32) types.Ssize_t {
  168. if __ccgo_strace {
  169. trc("t=%v sockfd=%v msg=%v flags=%v, (%v:)", t, sockfd, msg, flags, origin(2))
  170. }
  171. panic(todo(""))
  172. }
  173. // int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  174. func Xpoll(t *TLS, fds uintptr, nfds poll.Nfds_t, timeout int32) int32 {
  175. if __ccgo_strace {
  176. trc("t=%v fds=%v nfds=%v timeout=%v, (%v:)", t, fds, nfds, timeout, origin(2))
  177. }
  178. if nfds == 0 {
  179. panic(todo(""))
  180. }
  181. // if dmesgs {
  182. // dmesg("%v: %#x %v %v, %+v", origin(1), fds, nfds, timeout, (*[1000]unix.PollFd)(unsafe.Pointer(fds))[:nfds:nfds])
  183. // }
  184. n, err := unix.Poll((*[1000]unix.PollFd)(unsafe.Pointer(fds))[:nfds:nfds], int(timeout))
  185. // if dmesgs {
  186. // dmesg("%v: %v %v", origin(1), n, err)
  187. // }
  188. if err != nil {
  189. t.setErrno(err)
  190. return -1
  191. }
  192. return int32(n)
  193. }
  194. // struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg);
  195. func X__cmsg_nxthdr(t *TLS, msgh, cmsg uintptr) uintptr {
  196. if __ccgo_strace {
  197. trc("t=%v cmsg=%v, (%v:)", t, cmsg, origin(2))
  198. }
  199. panic(todo(""))
  200. }
  201. // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
  202. func Xwcschr(t *TLS, wcs uintptr, wc wchar_t) wchar_t {
  203. if __ccgo_strace {
  204. trc("t=%v wcs=%v wc=%v, (%v:)", t, wcs, wc, origin(2))
  205. }
  206. panic(todo(""))
  207. }
  208. // gid_t getegid(void);
  209. func Xgetegid(t *TLS) types.Gid_t {
  210. if __ccgo_strace {
  211. trc("t=%v, (%v:)", t, origin(2))
  212. }
  213. panic(todo(""))
  214. }
  215. // gid_t getgid(void);
  216. func Xgetgid(t *TLS) types.Gid_t {
  217. if __ccgo_strace {
  218. trc("t=%v, (%v:)", t, origin(2))
  219. }
  220. panic(todo(""))
  221. }
  222. // void *shmat(int shmid, const void *shmaddr, int shmflg);
  223. func Xshmat(t *TLS, shmid int32, shmaddr uintptr, shmflg int32) uintptr {
  224. if __ccgo_strace {
  225. trc("t=%v shmid=%v shmaddr=%v shmflg=%v, (%v:)", t, shmid, shmaddr, shmflg, origin(2))
  226. }
  227. panic(todo(""))
  228. }
  229. // int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  230. func Xshmctl(t *TLS, shmid, cmd int32, buf uintptr) int32 {
  231. if __ccgo_strace {
  232. trc("t=%v cmd=%v buf=%v, (%v:)", t, cmd, buf, origin(2))
  233. }
  234. panic(todo(""))
  235. }
  236. // int shmdt(const void *shmaddr);
  237. func Xshmdt(t *TLS, shmaddr uintptr) int32 {
  238. if __ccgo_strace {
  239. trc("t=%v shmaddr=%v, (%v:)", t, shmaddr, origin(2))
  240. }
  241. panic(todo(""))
  242. }
  243. // int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
  244. func Xgetresuid(t *TLS, ruid, euid, suid uintptr) int32 {
  245. if __ccgo_strace {
  246. trc("t=%v suid=%v, (%v:)", t, suid, origin(2))
  247. }
  248. panic(todo(""))
  249. }
  250. // int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
  251. func Xgetresgid(t *TLS, rgid, egid, sgid uintptr) int32 {
  252. if __ccgo_strace {
  253. trc("t=%v sgid=%v, (%v:)", t, sgid, origin(2))
  254. }
  255. panic(todo(""))
  256. }
  257. // FILE *tmpfile(void);
  258. func Xtmpfile(t *TLS) uintptr {
  259. if __ccgo_strace {
  260. trc("t=%v, (%v:)", t, origin(2))
  261. }
  262. f, err := os.CreateTemp("", "tmpfile-")
  263. if err != nil {
  264. t.setErrno(err)
  265. return 0
  266. }
  267. cf := newFile(t, int32(f.Fd()))
  268. AtExit(func() {
  269. nm := f.Name()
  270. file(cf).close(t)
  271. os.Remove(nm)
  272. })
  273. return cf
  274. }
  275. // FILE *fdopen(int fd, const char *mode);
  276. func Xfdopen(t *TLS, fd int32, mode uintptr) uintptr {
  277. if __ccgo_strace {
  278. trc("t=%v fd=%v mode=%v, (%v:)", t, fd, GoString(mode), origin(2))
  279. }
  280. m := strings.ReplaceAll(GoString(mode), "b", "")
  281. switch m {
  282. case
  283. "a",
  284. "a+",
  285. "r",
  286. "r+",
  287. "w",
  288. "w+":
  289. default:
  290. t.setErrno(errno.EINVAL)
  291. return 0
  292. }
  293. p := newFile(t, fd)
  294. if p == 0 {
  295. t.setErrno(errno.EINVAL)
  296. return 0
  297. }
  298. return p
  299. }
  300. // struct passwd *getpwnam(const char *name);
  301. func Xgetpwnam(t *TLS, name uintptr) uintptr {
  302. if __ccgo_strace {
  303. trc("t=%v name=%v, (%v:)", t, name, origin(2))
  304. }
  305. f, err := os.Open("/etc/passwd")
  306. if err != nil {
  307. panic(todo("", err))
  308. }
  309. defer f.Close()
  310. sname := GoString(name)
  311. sc := bufio.NewScanner(f)
  312. for sc.Scan() {
  313. s := strings.TrimSpace(sc.Text())
  314. if s == "" || strings.HasPrefix(s, "#") {
  315. continue
  316. }
  317. // eg. "root:x:0:0:root:/root:/bin/bash"
  318. a := strings.Split(s, ":")
  319. if len(a) < 7 {
  320. panic(todo(""))
  321. }
  322. if a[0] == sname {
  323. uid, err := strconv.Atoi(a[2])
  324. if err != nil {
  325. panic(todo(""))
  326. }
  327. gid, err := strconv.Atoi(a[3])
  328. if err != nil {
  329. panic(todo(""))
  330. }
  331. closePasswd(&staticGetpwnam)
  332. gecos := a[4]
  333. if strings.Contains(gecos, ",") {
  334. a := strings.Split(gecos, ",")
  335. gecos = a[0]
  336. }
  337. initPasswd(t, &staticGetpwnam, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6])
  338. return uintptr(unsafe.Pointer(&staticGetpwnam))
  339. }
  340. }
  341. if sc.Err() != nil {
  342. panic(todo(""))
  343. }
  344. return 0
  345. }
  346. // int getpwnam_r(char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
  347. func Xgetpwnam_r(t *TLS, name, cpwd, buf uintptr, buflen types.Size_t, result uintptr) int32 {
  348. if __ccgo_strace {
  349. trc("t=%v buf=%v buflen=%v result=%v, (%v:)", t, buf, buflen, result, origin(2))
  350. }
  351. f, err := os.Open("/etc/passwd")
  352. if err != nil {
  353. panic(todo("", err))
  354. }
  355. defer f.Close()
  356. sname := GoString(name)
  357. sc := bufio.NewScanner(f)
  358. for sc.Scan() {
  359. s := strings.TrimSpace(sc.Text())
  360. if s == "" || strings.HasPrefix(s, "#") {
  361. continue
  362. }
  363. // eg. "root:x:0:0:root:/root:/bin/bash"
  364. a := strings.Split(s, ":")
  365. if len(a) < 7 {
  366. panic(todo("%q", s))
  367. }
  368. if a[0] == sname {
  369. uid, err := strconv.Atoi(a[2])
  370. if err != nil {
  371. panic(todo(""))
  372. }
  373. gid, err := strconv.Atoi(a[3])
  374. if err != nil {
  375. panic(todo(""))
  376. }
  377. gecos := a[4]
  378. if strings.Contains(gecos, ",") {
  379. a := strings.Split(gecos, ",")
  380. gecos = a[0]
  381. }
  382. var v pwd.Passwd
  383. if initPasswd2(t, buf, buflen, &v, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) {
  384. *(*pwd.Passwd)(unsafe.Pointer(cpwd)) = v
  385. *(*uintptr)(unsafe.Pointer(result)) = cpwd
  386. return 0
  387. }
  388. *(*uintptr)(unsafe.Pointer(result)) = 0
  389. return errno.ERANGE
  390. }
  391. }
  392. if sc.Err() != nil {
  393. panic(todo(""))
  394. }
  395. *(*uintptr)(unsafe.Pointer(result)) = 0
  396. return 0
  397. }
  398. func init() {
  399. atExit = append(atExit, func() { closeGroup(&staticGetgrgid) })
  400. }
  401. var staticGetgrgid grp.Group
  402. // struct group *getgrgid(gid_t gid);
  403. func Xgetgrgid(t *TLS, gid uint32) uintptr {
  404. if __ccgo_strace {
  405. trc("t=%v gid=%v, (%v:)", t, gid, origin(2))
  406. }
  407. f, err := os.Open("/etc/group")
  408. if err != nil {
  409. panic(todo(""))
  410. }
  411. defer f.Close()
  412. sid := strconv.Itoa(int(gid))
  413. sc := bufio.NewScanner(f)
  414. for sc.Scan() {
  415. s := strings.TrimSpace(sc.Text())
  416. if s == "" || strings.HasPrefix(s, "#") {
  417. continue
  418. }
  419. // eg. "root:x:0:"
  420. a := strings.Split(s, ":")
  421. if len(a) < 4 {
  422. panic(todo("%q", s))
  423. }
  424. if a[2] == sid {
  425. closeGroup(&staticGetgrgid)
  426. var names []string
  427. if a[3] != "" {
  428. names = strings.Split(a[3], ",")
  429. }
  430. initGroup(t, &staticGetgrgid, a[0], a[1], gid, names)
  431. return uintptr(unsafe.Pointer(&staticGetgrgid))
  432. }
  433. }
  434. if sc.Err() != nil {
  435. panic(todo(""))
  436. }
  437. return 0
  438. }
  439. // int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
  440. func Xgetgrgid_r(t *TLS, gid uint32, pGrp, buf uintptr, buflen types.Size_t, result uintptr) int32 {
  441. if __ccgo_strace {
  442. trc("t=%v gid=%v buf=%v buflen=%v result=%v, (%v:)", t, gid, buf, buflen, result, origin(2))
  443. }
  444. f, err := os.Open("/etc/group")
  445. if err != nil {
  446. panic(todo(""))
  447. }
  448. defer f.Close()
  449. sid := strconv.Itoa(int(gid))
  450. sc := bufio.NewScanner(f)
  451. for sc.Scan() {
  452. s := strings.TrimSpace(sc.Text())
  453. if s == "" || strings.HasPrefix(s, "#") {
  454. continue
  455. }
  456. // eg. "root:x:0:"
  457. a := strings.Split(s, ":")
  458. if len(a) < 4 {
  459. panic(todo("%q", s))
  460. }
  461. if a[2] == sid {
  462. var names []string
  463. if a[3] != "" {
  464. names = strings.Split(a[3], ",")
  465. }
  466. var x grp.Group
  467. if initGroup2(buf, buflen, &x, a[0], a[1], gid, names) {
  468. *(*grp.Group)(unsafe.Pointer(pGrp)) = x
  469. *(*uintptr)(unsafe.Pointer(result)) = pGrp
  470. return 0
  471. }
  472. *(*uintptr)(unsafe.Pointer(result)) = 0
  473. return 0
  474. }
  475. }
  476. if sc.Err() != nil {
  477. panic(todo(""))
  478. }
  479. *(*uintptr)(unsafe.Pointer(result)) = 0
  480. return 0
  481. }
  482. func initPasswd2(t *TLS, buf uintptr, buflen types.Size_t, p *pwd.Passwd, name, pwd string, uid, gid uint32, gecos, dir, shell string) bool {
  483. p.Fpw_name, buf, buflen = bufString(buf, buflen, name)
  484. if buf == 0 {
  485. return false
  486. }
  487. p.Fpw_passwd, buf, buflen = bufString(buf, buflen, pwd)
  488. if buf == 0 {
  489. return false
  490. }
  491. p.Fpw_uid = uid
  492. p.Fpw_gid = gid
  493. if buf == 0 {
  494. return false
  495. }
  496. p.Fpw_gecos, buf, buflen = bufString(buf, buflen, gecos)
  497. if buf == 0 {
  498. return false
  499. }
  500. p.Fpw_dir, buf, buflen = bufString(buf, buflen, dir)
  501. if buf == 0 {
  502. return false
  503. }
  504. p.Fpw_shell, buf, buflen = bufString(buf, buflen, shell)
  505. return buf != 0
  506. }
  507. func bufString(buf uintptr, buflen types.Size_t, s string) (uintptr, uintptr, types.Size_t) {
  508. buf0 := buf
  509. rq := len(s) + 1
  510. if rq > int(buflen) {
  511. return 0, 0, 0
  512. }
  513. copy((*RawMem)(unsafe.Pointer(buf))[:len(s):len(s)], s)
  514. buf += uintptr(len(s))
  515. *(*byte)(unsafe.Pointer(buf)) = 0
  516. return buf0, buf + 1, buflen - types.Size_t(rq)
  517. }
  518. func closeGroup(p *grp.Group) {
  519. Xfree(nil, p.Fgr_name)
  520. Xfree(nil, p.Fgr_passwd)
  521. if p := p.Fgr_mem; p != 0 {
  522. for {
  523. q := *(*uintptr)(unsafe.Pointer(p))
  524. if q == 0 {
  525. break
  526. }
  527. Xfree(nil, q)
  528. p += unsafe.Sizeof(uintptr(0))
  529. }
  530. }
  531. *p = grp.Group{}
  532. }
  533. func initGroup(t *TLS, p *grp.Group, name, pwd string, gid uint32, names []string) {
  534. p.Fgr_name = cString(t, name)
  535. p.Fgr_passwd = cString(t, pwd)
  536. p.Fgr_gid = gid
  537. a := Xcalloc(t, 1, types.Size_t(unsafe.Sizeof(uintptr(0)))*types.Size_t((len(names)+1)))
  538. if a == 0 {
  539. panic("OOM")
  540. }
  541. for p := a; len(names) != 0; p += unsafe.Sizeof(uintptr(0)) {
  542. *(*uintptr)(unsafe.Pointer(p)) = cString(t, names[0])
  543. names = names[1:]
  544. }
  545. p.Fgr_mem = a
  546. }
  547. func initGroup2(buf uintptr, buflen types.Size_t, p *grp.Group, name, pwd string, gid uint32, names []string) bool {
  548. p.Fgr_name, buf, buflen = bufString(buf, buflen, name)
  549. if buf == 0 {
  550. return false
  551. }
  552. p.Fgr_passwd, buf, buflen = bufString(buf, buflen, pwd)
  553. if buf == 0 {
  554. return false
  555. }
  556. p.Fgr_gid = gid
  557. rq := unsafe.Sizeof(uintptr(0)) * uintptr(len(names)+1)
  558. if rq > uintptr(buflen) {
  559. return false
  560. }
  561. a := buf
  562. buf += rq
  563. for ; len(names) != 0; buf += unsafe.Sizeof(uintptr(0)) {
  564. if len(names[0])+1 > int(buflen) {
  565. return false
  566. }
  567. *(*uintptr)(unsafe.Pointer(buf)), buf, buflen = bufString(buf, buflen, names[0])
  568. names = names[1:]
  569. }
  570. *(*uintptr)(unsafe.Pointer(buf)) = 0
  571. p.Fgr_mem = a
  572. return true
  573. }
  574. func init() {
  575. atExit = append(atExit, func() { closeGroup(&staticGetgrgid) })
  576. }
  577. var staticGetpwuid pwd.Passwd
  578. func init() {
  579. atExit = append(atExit, func() { closePasswd(&staticGetpwuid) })
  580. }
  581. func closePasswd(p *pwd.Passwd) {
  582. Xfree(nil, p.Fpw_name)
  583. Xfree(nil, p.Fpw_passwd)
  584. Xfree(nil, p.Fpw_gecos)
  585. Xfree(nil, p.Fpw_dir)
  586. Xfree(nil, p.Fpw_shell)
  587. *p = pwd.Passwd{}
  588. }
  589. var staticGetgrnam grp.Group
  590. func init() {
  591. atExit = append(atExit, func() { closeGroup(&staticGetgrnam) })
  592. }
  593. // struct passwd *getpwuid(uid_t uid);
  594. func Xgetpwuid(t *TLS, uid uint32) uintptr {
  595. if __ccgo_strace {
  596. trc("t=%v uid=%v, (%v:)", t, uid, origin(2))
  597. }
  598. f, err := os.Open("/etc/passwd")
  599. if err != nil {
  600. panic(todo("", err))
  601. }
  602. defer f.Close()
  603. sid := strconv.Itoa(int(uid))
  604. sc := bufio.NewScanner(f)
  605. for sc.Scan() {
  606. s := strings.TrimSpace(sc.Text())
  607. if len(s) == 0 || strings.HasPrefix(s, "#") {
  608. continue
  609. }
  610. // eg. "root:x:0:0:root:/root:/bin/bash"
  611. a := strings.Split(s, ":")
  612. if len(a) < 7 {
  613. panic(todo("%q", s))
  614. }
  615. if a[2] == sid {
  616. uid, err := strconv.Atoi(a[2])
  617. if err != nil {
  618. panic(todo(""))
  619. }
  620. gid, err := strconv.Atoi(a[3])
  621. if err != nil {
  622. panic(todo(""))
  623. }
  624. closePasswd(&staticGetpwuid)
  625. gecos := a[4]
  626. if strings.Contains(gecos, ",") {
  627. a := strings.Split(gecos, ",")
  628. gecos = a[0]
  629. }
  630. initPasswd(t, &staticGetpwuid, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6])
  631. return uintptr(unsafe.Pointer(&staticGetpwuid))
  632. }
  633. }
  634. if sc.Err() != nil {
  635. panic(todo(""))
  636. }
  637. return 0
  638. }
  639. func initPasswd(t *TLS, p *pwd.Passwd, name, pwd string, uid, gid uint32, gecos, dir, shell string) {
  640. p.Fpw_name = cString(t, name)
  641. p.Fpw_passwd = cString(t, pwd)
  642. p.Fpw_uid = uid
  643. p.Fpw_gid = gid
  644. p.Fpw_gecos = cString(t, gecos)
  645. p.Fpw_dir = cString(t, dir)
  646. p.Fpw_shell = cString(t, shell)
  647. }
  648. // struct group *getgrnam(const char *name);
  649. func Xgetgrnam(t *TLS, name uintptr) uintptr {
  650. if __ccgo_strace {
  651. trc("t=%v name=%v, (%v:)", t, name, origin(2))
  652. }
  653. f, err := os.Open("/etc/group")
  654. if err != nil {
  655. panic(todo(""))
  656. }
  657. defer f.Close()
  658. sname := GoString(name)
  659. sc := bufio.NewScanner(f)
  660. for sc.Scan() {
  661. s := strings.TrimSpace(sc.Text())
  662. if len(s) == 0 || strings.HasPrefix(s, "#") {
  663. continue
  664. }
  665. // eg. "root:x:0:"
  666. a := strings.Split(s, ":")
  667. if len(a) < 4 {
  668. panic(todo("%q", s))
  669. }
  670. if a[0] == sname {
  671. closeGroup(&staticGetgrnam)
  672. gid, err := strconv.Atoi(a[2])
  673. if err != nil {
  674. panic(todo(""))
  675. }
  676. var names []string
  677. if a[3] != "" {
  678. names = strings.Split(a[3], ",")
  679. }
  680. initGroup(t, &staticGetgrnam, a[0], a[1], uint32(gid), names)
  681. return uintptr(unsafe.Pointer(&staticGetgrnam))
  682. }
  683. }
  684. if sc.Err() != nil {
  685. panic(todo(""))
  686. }
  687. return 0
  688. }
  689. // int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
  690. func Xgetgrnam_r(t *TLS, name, pGrp, buf uintptr, buflen types.Size_t, result uintptr) int32 {
  691. if __ccgo_strace {
  692. trc("t=%v buf=%v buflen=%v result=%v, (%v:)", t, buf, buflen, result, origin(2))
  693. }
  694. f, err := os.Open("/etc/group")
  695. if err != nil {
  696. panic(todo(""))
  697. }
  698. defer f.Close()
  699. sname := GoString(name)
  700. sc := bufio.NewScanner(f)
  701. for sc.Scan() {
  702. s := strings.TrimSpace(sc.Text())
  703. if len(s) == 0 || strings.HasPrefix(s, "#") {
  704. continue
  705. }
  706. // eg. "root:x:0:"
  707. a := strings.Split(s, ":")
  708. if len(a) < 4 {
  709. panic(todo("%q", s))
  710. }
  711. if a[0] == sname {
  712. gid, err := strconv.Atoi(a[2])
  713. if err != nil {
  714. panic(todo(""))
  715. }
  716. var names []string
  717. if a[3] != "" {
  718. names = strings.Split(a[3], ",")
  719. }
  720. var x grp.Group
  721. if initGroup2(buf, buflen, &x, a[0], a[1], uint32(gid), names) {
  722. *(*grp.Group)(unsafe.Pointer(pGrp)) = x
  723. *(*uintptr)(unsafe.Pointer(result)) = pGrp
  724. return 0
  725. }
  726. *(*uintptr)(unsafe.Pointer(result)) = 0
  727. return 0
  728. }
  729. }
  730. if sc.Err() != nil {
  731. panic(todo(""))
  732. }
  733. *(*uintptr)(unsafe.Pointer(result)) = 0
  734. return 0
  735. }
  736. // int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
  737. func Xgetpwuid_r(t *TLS, uid types.Uid_t, cpwd, buf uintptr, buflen types.Size_t, result uintptr) int32 {
  738. if __ccgo_strace {
  739. trc("t=%v uid=%v buf=%v buflen=%v result=%v, (%v:)", t, uid, buf, buflen, result, origin(2))
  740. }
  741. f, err := os.Open("/etc/passwd")
  742. if err != nil {
  743. panic(todo("", err))
  744. }
  745. defer f.Close()
  746. sid := strconv.Itoa(int(uid))
  747. sc := bufio.NewScanner(f)
  748. for sc.Scan() {
  749. s := strings.TrimSpace(sc.Text())
  750. if len(s) == 0 || strings.HasPrefix(s, "#") {
  751. continue
  752. }
  753. // eg. "root:x:0:0:root:/root:/bin/bash"
  754. a := strings.Split(s, ":")
  755. if len(a) < 7 {
  756. panic(todo("%q", s))
  757. }
  758. if a[2] == sid {
  759. uid, err := strconv.Atoi(a[2])
  760. if err != nil {
  761. panic(todo(""))
  762. }
  763. gid, err := strconv.Atoi(a[3])
  764. if err != nil {
  765. panic(todo(""))
  766. }
  767. gecos := a[4]
  768. if strings.Contains(gecos, ",") {
  769. a := strings.Split(gecos, ",")
  770. gecos = a[0]
  771. }
  772. var v pwd.Passwd
  773. if initPasswd2(t, buf, buflen, &v, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) {
  774. *(*pwd.Passwd)(unsafe.Pointer(cpwd)) = v
  775. *(*uintptr)(unsafe.Pointer(result)) = cpwd
  776. return 0
  777. }
  778. *(*uintptr)(unsafe.Pointer(result)) = 0
  779. return errno.ERANGE
  780. }
  781. }
  782. if sc.Err() != nil {
  783. panic(todo(""))
  784. }
  785. *(*uintptr)(unsafe.Pointer(result)) = 0
  786. return 0
  787. }
  788. // int mkostemp(char *template, int flags);
  789. func Xmkostemp(t *TLS, template uintptr, flags int32) int32 {
  790. if __ccgo_strace {
  791. trc("t=%v template=%v flags=%v, (%v:)", t, template, flags, origin(2))
  792. }
  793. len := uintptr(Xstrlen(t, template))
  794. x := template + uintptr(len-6)
  795. for i := uintptr(0); i < 6; i++ {
  796. if *(*byte)(unsafe.Pointer(x + i)) != 'X' {
  797. t.setErrno(errno.EINVAL)
  798. return -1
  799. }
  800. }
  801. fd, err := tempFile(template, x, flags)
  802. if err != nil {
  803. t.setErrno(err)
  804. return -1
  805. }
  806. return int32(fd)
  807. }
  808. // void uuid_generate_random(uuid_t out);
  809. func Xuuid_generate_random(t *TLS, out uintptr) {
  810. if __ccgo_strace {
  811. trc("t=%v out=%v, (%v:)", t, out, origin(2))
  812. }
  813. x := guuid.New()
  814. copy((*RawMem)(unsafe.Pointer(out))[:], x[:])
  815. }
  816. // void uuid_unparse(uuid_t uu, char *out);
  817. func Xuuid_unparse(t *TLS, uu, out uintptr) {
  818. if __ccgo_strace {
  819. trc("t=%v out=%v, (%v:)", t, out, origin(2))
  820. }
  821. s := (*guuid.UUID)(unsafe.Pointer(uu)).String()
  822. copy((*RawMem)(unsafe.Pointer(out))[:], s)
  823. *(*byte)(unsafe.Pointer(out + uintptr(len(s)))) = 0
  824. }
  825. // no longer used?
  826. // var staticRandomData = &rand.Rand{}
  827. // char *initstate(unsigned seed, char *state, size_t size);
  828. func Xinitstate(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t) uintptr {
  829. if __ccgo_strace {
  830. trc("t=%v seed=%v statebuf=%v statelen=%v, (%v:)", t, seed, statebuf, statelen, origin(2))
  831. }
  832. // staticRandomData = rand.New(rand.NewSource(int64(seed)))
  833. _ = rand.New(rand.NewSource(int64(seed)))
  834. return 0
  835. }
  836. // char *setstate(const char *state);
  837. func Xsetstate(t *TLS, state uintptr) uintptr {
  838. if __ccgo_strace {
  839. trc("t=%v state=%v, (%v:)", t, state, origin(2))
  840. }
  841. t.setErrno(errno.EINVAL) //TODO
  842. return 0
  843. }
  844. // The initstate_r() function is like initstate(3) except that it initializes
  845. // the state in the object pointed to by buf, rather than initializing the
  846. // global state variable. Before calling this function, the buf.state field
  847. // must be initialized to NULL. The initstate_r() function records a pointer
  848. // to the statebuf argument inside the structure pointed to by buf. Thus,
  849. // state‐ buf should not be deallocated so long as buf is still in use. (So,
  850. // statebuf should typically be allocated as a static variable, or allocated on
  851. // the heap using malloc(3) or similar.)
  852. //
  853. // char *initstate_r(unsigned int seed, char *statebuf, size_t statelen, struct random_data *buf);
  854. func Xinitstate_r(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t, buf uintptr) int32 {
  855. if __ccgo_strace {
  856. trc("t=%v seed=%v statebuf=%v statelen=%v buf=%v, (%v:)", t, seed, statebuf, statelen, buf, origin(2))
  857. }
  858. if buf == 0 {
  859. panic(todo(""))
  860. }
  861. randomDataMu.Lock()
  862. defer randomDataMu.Unlock()
  863. randomData[buf] = rand.New(rand.NewSource(int64(seed)))
  864. return 0
  865. }
  866. var (
  867. randomData = map[uintptr]*rand.Rand{}
  868. randomDataMu sync.Mutex
  869. )
  870. // int mkstemps(char *template, int suffixlen);
  871. func Xmkstemps(t *TLS, template uintptr, suffixlen int32) int32 {
  872. if __ccgo_strace {
  873. trc("t=%v template=%v suffixlen=%v, (%v:)", t, template, suffixlen, origin(2))
  874. }
  875. return Xmkstemps64(t, template, suffixlen)
  876. }
  877. // int mkstemps(char *template, int suffixlen);
  878. func Xmkstemps64(t *TLS, template uintptr, suffixlen int32) int32 {
  879. if __ccgo_strace {
  880. trc("t=%v template=%v suffixlen=%v, (%v:)", t, template, suffixlen, origin(2))
  881. }
  882. len := uintptr(Xstrlen(t, template))
  883. x := template + uintptr(len-6) - uintptr(suffixlen)
  884. for i := uintptr(0); i < 6; i++ {
  885. if *(*byte)(unsafe.Pointer(x + i)) != 'X' {
  886. t.setErrno(errno.EINVAL)
  887. return -1
  888. }
  889. }
  890. fd, err := tempFile(template, x, 0)
  891. if err != nil {
  892. t.setErrno(err)
  893. return -1
  894. }
  895. return int32(fd)
  896. }
  897. // int mkstemp(char *template);
  898. func Xmkstemp(t *TLS, template uintptr) int32 {
  899. if __ccgo_strace {
  900. trc("t=%v template=%v, (%v:)", t, template, origin(2))
  901. }
  902. return Xmkstemp64(t, template)
  903. }
  904. // int mkstemp(char *template);
  905. func Xmkstemp64(t *TLS, template uintptr) int32 {
  906. if __ccgo_strace {
  907. trc("t=%v template=%v, (%v:)", t, template, origin(2))
  908. }
  909. return Xmkstemps64(t, template, 0)
  910. }
  911. // int random_r(struct random_data *buf, int32_t *result);
  912. func Xrandom_r(t *TLS, buf, result uintptr) int32 {
  913. if __ccgo_strace {
  914. trc("t=%v result=%v, (%v:)", t, result, origin(2))
  915. }
  916. randomDataMu.Lock()
  917. defer randomDataMu.Unlock()
  918. mr := randomData[buf]
  919. if stdlib.RAND_MAX != math.MaxInt32 {
  920. panic(todo(""))
  921. }
  922. *(*int32)(unsafe.Pointer(result)) = mr.Int31()
  923. return 0
  924. }
  925. // int strerror_r(int errnum, char *buf, size_t buflen);
  926. func Xstrerror_r(t *TLS, errnum int32, buf uintptr, buflen size_t) int32 {
  927. if __ccgo_strace {
  928. trc("t=%v errnum=%v buf=%v buflen=%v, (%v:)", t, errnum, buf, buflen, origin(2))
  929. }
  930. panic(todo(""))
  931. }
  932. // void endpwent(void);
  933. func Xendpwent(t *TLS) {
  934. if __ccgo_strace {
  935. trc("t=%v, (%v:)", t, origin(2))
  936. }
  937. // nop
  938. }
  939. var ctimeStaticBuf [32]byte
  940. // char *ctime(const time_t *timep);
  941. func Xctime(t *TLS, timep uintptr) uintptr {
  942. if __ccgo_strace {
  943. trc("t=%v timep=%v, (%v:)", t, timep, origin(2))
  944. }
  945. return Xctime_r(t, timep, uintptr(unsafe.Pointer(&ctimeStaticBuf[0])))
  946. }
  947. // char *ctime_r(const time_t *timep, char *buf);
  948. func Xctime_r(t *TLS, timep, buf uintptr) uintptr {
  949. if __ccgo_strace {
  950. trc("t=%v buf=%v, (%v:)", t, buf, origin(2))
  951. }
  952. ut := *(*ctime.Time_t)(unsafe.Pointer(timep))
  953. tm := time.Unix(int64(ut), 0).Local()
  954. s := tm.Format(time.ANSIC) + "\n\x00"
  955. copy((*RawMem)(unsafe.Pointer(buf))[:26:26], s)
  956. return buf
  957. }
  958. // ssize_t pread(int fd, void *buf, size_t count, off_t offset);
  959. func Xpread(t *TLS, fd int32, buf uintptr, count types.Size_t, offset types.Off_t) types.Ssize_t {
  960. if __ccgo_strace {
  961. trc("t=%v fd=%v buf=%v count=%v offset=%v, (%v:)", t, fd, buf, count, offset, origin(2))
  962. }
  963. var n int
  964. var err error
  965. switch {
  966. case count == 0:
  967. n, err = unix.Pread(int(fd), nil, int64(offset))
  968. default:
  969. n, err = unix.Pread(int(fd), (*RawMem)(unsafe.Pointer(buf))[:count:count], int64(offset))
  970. // if dmesgs && err == nil {
  971. // dmesg("%v: fd %v, off %#x, count %#x, n %#x\n%s", origin(1), fd, offset, count, n, hex.Dump((*RawMem)(unsafe.Pointer(buf))[:n:n]))
  972. // }
  973. }
  974. if err != nil {
  975. // if dmesgs {
  976. // dmesg("%v: %v FAIL", origin(1), err)
  977. // }
  978. t.setErrno(err)
  979. return -1
  980. }
  981. // if dmesgs {
  982. // dmesg("%v: ok", origin(1))
  983. // }
  984. return types.Ssize_t(n)
  985. }
  986. // // malloc_zone_t * malloc_create_zone(vm_size_t start_size, unsigned flags);
  987. // func Xmalloc_create_zone(t *TLS, start_size types.Size_t, flags uint32) uintptr {
  988. // if __ccgo_strace {
  989. // trc("t=%v start_size=%v flags=%v, (%v:)", t, start_size, flags, origin(2))
  990. // }
  991. // panic(todo(""))
  992. // }
  993. //
  994. // // void * malloc_zone_malloc(malloc_zone_t *zone, size_t size);
  995. // func Xmalloc_zone_malloc(t *TLS, zone uintptr, size types.Size_t) uintptr {
  996. // if __ccgo_strace {
  997. // trc("t=%v zone=%v size=%v, (%v:)", t, zone, size, origin(2))
  998. // }
  999. // if zone == defaultZone {
  1000. // return Xmalloc(t, size)
  1001. // }
  1002. //
  1003. // panic(todo(""))
  1004. // }
  1005. //
  1006. // // malloc_zone_t * malloc_default_zone(void);
  1007. // func Xmalloc_default_zone(t *TLS) uintptr {
  1008. // if __ccgo_strace {
  1009. // trc("t=%v (%v:)", t, origin(2))
  1010. // }
  1011. // return defaultZone
  1012. // }
  1013. //
  1014. // // void malloc_zone_free(malloc_zone_t *zone, void *ptr);
  1015. // func Xmalloc_zone_free(t *TLS, zone, ptr uintptr) {
  1016. // if __ccgo_strace {
  1017. // trc("t=%v zone=%v ptr=%v, (%v:)", t, zone, ptr, origin(2))
  1018. // }
  1019. //
  1020. // if zone == defaultZone {
  1021. // Xfree(t, ptr)
  1022. // return
  1023. // }
  1024. //
  1025. // panic(todo(""))
  1026. // }
  1027. //
  1028. // // void * malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
  1029. // func Xmalloc_zone_realloc(t *TLS, zone, ptr uintptr, size types.Size_t) uintptr {
  1030. // if __ccgo_strace {
  1031. // trc("t=%v zone=%v ptr=%v size=%v, (%v:)", t, zone, ptr, size, origin(2))
  1032. // }
  1033. // panic(todo(""))
  1034. // }
  1035. // int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
  1036. func Xsysctlbyname(t *TLS, name, oldp, oldlenp, newp uintptr, newlen types.Size_t) int32 {
  1037. if __ccgo_strace {
  1038. trc("t=%v name=%q oldp=%#0x oldlenp=%v newp=%v newlen=%v, (%v:)", t, GoString(name), oldp, *(*types.Size_t)(unsafe.Pointer(oldlenp)), newp, newlen, origin(2))
  1039. }
  1040. oldlen := *(*types.Size_t)(unsafe.Pointer(oldlenp))
  1041. switch GoString(name) {
  1042. case "hw.ncpu":
  1043. if oldlen != 4 {
  1044. panic(todo(""))
  1045. }
  1046. *(*int32)(unsafe.Pointer(oldp)) = int32(runtime.GOMAXPROCS(-1))
  1047. return 0
  1048. default:
  1049. t.setErrno(errno.ENOENT)
  1050. return -1
  1051. }
  1052. }
  1053. // type mallocZone struct {
  1054. // a memory.Allocator
  1055. // mu sync.Mutex
  1056. //
  1057. // isDefault bool
  1058. // }
  1059. //
  1060. // func newMallocZone(isDefault bool) *mallocZone {
  1061. // return &mallocZone{isDefault: isDefault}
  1062. // }
  1063. //
  1064. // var (
  1065. // defaultZone uintptr
  1066. // )
  1067. //
  1068. // func init() {
  1069. // defaultZone = addObject(newMallocZone(true))
  1070. // }
  1071. // /tmp/libc/musl-master/src/time/gmtime.c:6:19:
  1072. var _tm ctime.Tm
  1073. // /tmp/libc/musl-master/src/time/gmtime.c:4:11:
  1074. func Xgmtime(tls *TLS, t uintptr) (r uintptr) { // /tmp/libc/musl-master/src/time/gmtime.c:7:2:
  1075. if __ccgo_strace {
  1076. trc("tls=%v t=%v, (%v:)", tls, t, origin(2))
  1077. defer func() { trc("-> %v", r) }()
  1078. }
  1079. return Xgmtime_r(tls, t, uintptr(unsafe.Pointer(&_tm)))
  1080. }
  1081. var _days_in_month = [12]int8{
  1082. 0: int8(31),
  1083. 1: int8(30),
  1084. 2: int8(31),
  1085. 3: int8(30),
  1086. 4: int8(31),
  1087. 5: int8(31),
  1088. 6: int8(30),
  1089. 7: int8(31),
  1090. 8: int8(30),
  1091. 9: int8(31),
  1092. 10: int8(31),
  1093. 11: int8(29),
  1094. }
  1095. var x___utc = [4]int8{'U', 'T', 'C'}
  1096. func Xstrftime(tls *TLS, s uintptr, n size_t, f uintptr, tm uintptr) (r size_t) {
  1097. if __ccgo_strace {
  1098. trc("tls=%v s=%v n=%v f=%v tm=%v, (%v:)", tls, s, n, f, tm, origin(2))
  1099. defer func() { trc("-> %v", r) }()
  1100. }
  1101. tt := time.Date(
  1102. int((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_year+1900),
  1103. time.Month((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_mon+1),
  1104. int((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_mday),
  1105. int((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_hour),
  1106. int((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_min),
  1107. int((*ctime.Tm)(unsafe.Pointer(tm)).Ftm_sec),
  1108. 0,
  1109. time.UTC,
  1110. )
  1111. fmt := GoString(f)
  1112. var result string
  1113. if fmt != "" {
  1114. result = strftime.Format(fmt, tt)
  1115. }
  1116. switch r = size_t(len(result)); {
  1117. case r > n:
  1118. r = 0
  1119. default:
  1120. copy((*RawMem)(unsafe.Pointer(s))[:r:r], result)
  1121. *(*byte)(unsafe.Pointer(s + uintptr(r))) = 0
  1122. }
  1123. return r
  1124. }
  1125. func Xgmtime_r(tls *TLS, t uintptr, tm uintptr) (r uintptr) {
  1126. if __ccgo_strace {
  1127. trc("tls=%v t=%v tm=%v, (%v:)", tls, t, tm, origin(2))
  1128. defer func() { trc("-> %v", r) }()
  1129. }
  1130. if x___secs_to_tm(tls, int64(*(*time_t)(unsafe.Pointer(t))), tm) < 0 {
  1131. *(*int32)(unsafe.Pointer(X__errno_location(tls))) = int32(errno.EOVERFLOW)
  1132. return uintptr(0)
  1133. }
  1134. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_isdst = 0
  1135. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_gmtoff = 0
  1136. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_zone = uintptr(unsafe.Pointer(&x___utc))
  1137. return tm
  1138. }
  1139. func x___secs_to_tm(tls *TLS, t int64, tm uintptr) (r int32) {
  1140. var c_cycles, leap, months, q_cycles, qc_cycles, remdays, remsecs, remyears, wday, yday int32
  1141. var days, secs, years int64
  1142. _, _, _, _, _, _, _, _, _, _, _, _, _ = c_cycles, days, leap, months, q_cycles, qc_cycles, remdays, remsecs, remyears, secs, wday, yday, years
  1143. /* Reject time_t values whose year would overflow int */
  1144. if t < int64(-Int32FromInt32(1)-Int32FromInt32(0x7fffffff))*Int64FromInt64(31622400) || t > Int64FromInt32(limits.INT_MAX)*Int64FromInt64(31622400) {
  1145. return -int32(1)
  1146. }
  1147. secs = t - (Int64FromInt64(946684800) + int64(Int32FromInt32(86400)*(Int32FromInt32(31)+Int32FromInt32(29))))
  1148. days = secs / int64(86400)
  1149. remsecs = int32(secs % int64(86400))
  1150. if remsecs < 0 {
  1151. remsecs += int32(86400)
  1152. days--
  1153. }
  1154. wday = int32((int64(3) + days) % int64(7))
  1155. if wday < 0 {
  1156. wday += int32(7)
  1157. }
  1158. qc_cycles = int32(days / int64(Int32FromInt32(365)*Int32FromInt32(400)+Int32FromInt32(97)))
  1159. remdays = int32(days % int64(Int32FromInt32(365)*Int32FromInt32(400)+Int32FromInt32(97)))
  1160. if remdays < 0 {
  1161. remdays += Int32FromInt32(365)*Int32FromInt32(400) + Int32FromInt32(97)
  1162. qc_cycles--
  1163. }
  1164. c_cycles = remdays / (Int32FromInt32(365)*Int32FromInt32(100) + Int32FromInt32(24))
  1165. if c_cycles == int32(4) {
  1166. c_cycles--
  1167. }
  1168. remdays -= c_cycles * (Int32FromInt32(365)*Int32FromInt32(100) + Int32FromInt32(24))
  1169. q_cycles = remdays / (Int32FromInt32(365)*Int32FromInt32(4) + Int32FromInt32(1))
  1170. if q_cycles == int32(25) {
  1171. q_cycles--
  1172. }
  1173. remdays -= q_cycles * (Int32FromInt32(365)*Int32FromInt32(4) + Int32FromInt32(1))
  1174. remyears = remdays / int32(365)
  1175. if remyears == int32(4) {
  1176. remyears--
  1177. }
  1178. remdays -= remyears * int32(365)
  1179. leap = BoolInt32(!(remyears != 0) && (q_cycles != 0 || !(c_cycles != 0)))
  1180. yday = remdays + int32(31) + int32(28) + leap
  1181. if yday >= int32(365)+leap {
  1182. yday -= int32(365) + leap
  1183. }
  1184. years = int64(remyears+int32(4)*q_cycles+int32(100)*c_cycles) + int64(400)*int64(int64(qc_cycles))
  1185. months = 0
  1186. for {
  1187. if !(int32(_days_in_month[months]) <= remdays) {
  1188. break
  1189. }
  1190. remdays -= int32(_days_in_month[months])
  1191. goto _1
  1192. _1:
  1193. months++
  1194. }
  1195. if months >= int32(10) {
  1196. months -= int32(12)
  1197. years++
  1198. }
  1199. if years+int64(100) > int64(limits.INT_MAX) || years+int64(100) < int64(-Int32FromInt32(1)-Int32FromInt32(0x7fffffff)) {
  1200. return -int32(1)
  1201. }
  1202. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_year = int32(years + int64(100))
  1203. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_mon = months + int32(2)
  1204. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_mday = remdays + int32(1)
  1205. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_wday = wday
  1206. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_yday = yday
  1207. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_hour = remsecs / int32(3600)
  1208. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_min = remsecs / int32(60) % int32(60)
  1209. (*ctime.Tm)(unsafe.Pointer(tm)).Ftm_sec = remsecs % int32(60)
  1210. return 0
  1211. }
  1212. // int clock_gettime(clockid_t clk_id, struct timespec *tp);
  1213. func Xclock_gettime(t *TLS, clk_id int32, tp uintptr) int32 {
  1214. if __ccgo_strace {
  1215. trc("t=%v clk_id=%v tp=%v, (%v:)", t, clk_id, tp, origin(2))
  1216. }
  1217. var ts unix.Timespec
  1218. if err := unix.ClockGettime(clk_id, &ts); err != nil {
  1219. t.setErrno(err)
  1220. trc("FAIL: %v", err)
  1221. return -1
  1222. }
  1223. *(*unix.Timespec)(unsafe.Pointer(tp)) = ts
  1224. return 0
  1225. }