Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

694 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dllio.c
  5. Abstract:
  6. Client implementation of Input and Output Primitives for POSIX
  7. Author:
  8. Mark Lucovsky 21-Feb-1989
  9. Revision History:
  10. --*/
  11. #include <sys/types.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <stdarg.h>
  15. #include "psxdll.h"
  16. int
  17. __cdecl
  18. close(int fildes)
  19. {
  20. PSX_API_MSG m;
  21. NTSTATUS st;
  22. PPSX_CLOSE_MSG args;
  23. args = &m.u.Close;
  24. PSX_FORMAT_API_MSG(m, PsxCloseApi, sizeof(*args));
  25. args->FileDes = fildes;
  26. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  27. (PPORT_MESSAGE)&m);
  28. #ifdef PSX_MORE_ERRORS
  29. ASSERT(NT_SUCCESS(st));
  30. #endif
  31. if (m.Error) {
  32. errno = (int)m.Error;
  33. return -1;
  34. }
  35. return m.ReturnValue;
  36. }
  37. int
  38. __cdecl
  39. creat(const char *path, mode_t mode)
  40. {
  41. return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
  42. }
  43. off_t
  44. __cdecl
  45. lseek(int fildes, off_t offset, int whence)
  46. {
  47. PSX_API_MSG m;
  48. NTSTATUS st;
  49. PPSX_LSEEK_MSG args;
  50. args = &m.u.Lseek;
  51. PSX_FORMAT_API_MSG(m, PsxLseekApi, sizeof(*args));
  52. args->FileDes = fildes;
  53. args->Whence = whence;
  54. args->Offset = offset;
  55. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  56. (PPORT_MESSAGE)&m);
  57. #ifdef PSX_MORE_ERRORS
  58. ASSERT(NT_SUCCESS(st));
  59. #endif
  60. if (m.Error) {
  61. errno = (int)m.Error;
  62. return -1;
  63. }
  64. return args->Offset;
  65. }
  66. int
  67. __cdecl
  68. open(const char *path, int oflag, ...)
  69. {
  70. PSX_API_MSG m;
  71. NTSTATUS st;
  72. PPSX_OPEN_MSG args;
  73. int i;
  74. va_list va_arg;
  75. va_start(va_arg, oflag);
  76. args = &m.u.Open;
  77. PSX_FORMAT_API_MSG(m, PsxOpenApi, sizeof(*args));
  78. args->Flags = oflag;
  79. if (oflag & O_CREAT) {
  80. //
  81. // Create requires a third parameter of type mode_t
  82. // which supplies the mode for a file being created
  83. //
  84. args->Mode = va_arg(va_arg, mode_t);
  85. }
  86. va_end(va_arg);
  87. if (!PdxCanonicalize((PSZ)path, &args->Path_U, PdxPortHeap)) {
  88. return -1;
  89. }
  90. ASSERT(NULL != wcschr(args->Path_U.Buffer, L'\\'));
  91. m.DataBlock = args->Path_U.Buffer;
  92. args->Path_U.Buffer = (PWSTR)((PCHAR)m.DataBlock +
  93. PsxPortMemoryRemoteDelta);
  94. for (;;) {
  95. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  96. (PPORT_MESSAGE)&m);
  97. #ifdef PSX_MORE_ERRORS
  98. ASSERT(NT_SUCCESS(st));
  99. #endif
  100. if (EINTR == m.Error && SIGCONT == m.Signal) {
  101. //
  102. // The syscall was stopped and continued. Call again
  103. // instead of returning EINTR.
  104. //
  105. PSX_FORMAT_API_MSG(m, PsxOpenApi, sizeof(*args));
  106. continue;
  107. }
  108. if (m.Error) {
  109. args->Path_U.Buffer = m.DataBlock;
  110. RtlFreeHeap(PdxPortHeap, 0, (PVOID)args->Path_U.Buffer);
  111. errno = (int)m.Error;
  112. return -1;
  113. }
  114. // successful return
  115. break;
  116. }
  117. args->Path_U.Buffer = m.DataBlock;
  118. RtlFreeHeap(PdxPortHeap, 0, (PVOID)args->Path_U.Buffer);
  119. return m.ReturnValue;
  120. }
  121. int
  122. __cdecl
  123. pipe(int *fildes)
  124. {
  125. PSX_API_MSG m;
  126. NTSTATUS st;
  127. PPSX_PIPE_MSG args;
  128. args = &m.u.Pipe;
  129. PSX_FORMAT_API_MSG(m, PsxPipeApi, sizeof(*args));
  130. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  131. (PPORT_MESSAGE)&m);
  132. #ifdef PSX_MORE_ERRORS
  133. ASSERT(NT_SUCCESS(st));
  134. #endif
  135. if (m.Error) {
  136. errno = (int)m.Error;
  137. return -1;
  138. }
  139. try {
  140. fildes[0] = args->FileDes0;
  141. fildes[1] = args->FileDes1;
  142. } except (EXCEPTION_EXECUTE_HANDLER) {
  143. st = STATUS_UNSUCCESSFUL;
  144. }
  145. if (!NT_SUCCESS(st)) {
  146. errno = EFAULT;
  147. return -1;
  148. }
  149. return 0;
  150. }
  151. int
  152. __cdecl
  153. read(int fildes, void *buf, unsigned int nbyte)
  154. {
  155. PSX_API_MSG m;
  156. PPSX_READ_MSG args;
  157. NTSTATUS Status;
  158. PVOID SesBuf;
  159. SCREQUESTMSG Request;
  160. int flags;
  161. args = &m.u.Read;
  162. PSX_FORMAT_API_MSG(m, PsxReadApi, sizeof(*args));
  163. for (;;) {
  164. args->FileDes = fildes;
  165. args->Buf = buf;
  166. args->Nbytes = nbyte;
  167. args->Command = IO_COMMAND_DONE;
  168. Status = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  169. (PPORT_MESSAGE)&m);
  170. #ifdef PSX_MORE_ERRORS
  171. ASSERT(NT_SUCCESS(Status));
  172. #endif
  173. if (EINTR == m.Error && SIGCONT == m.Signal) {
  174. //
  175. // The system call was stopped and continued. Call again
  176. // instead of returning EINTR.
  177. //
  178. PSX_FORMAT_API_MSG(m, PsxReadApi, sizeof(*args));
  179. continue;
  180. }
  181. if (m.Error) {
  182. errno = (int)m.Error;
  183. return -1;
  184. }
  185. break;
  186. }
  187. if (IO_COMMAND_DONE == args->Command) {
  188. return m.ReturnValue;
  189. }
  190. ASSERT(IO_COMMAND_DO_CONSIO == args->Command);
  191. flags = args->Scratch1; // do nonblocking io?
  192. //
  193. // The server says we should read data from the console.
  194. //
  195. if (nbyte > PSX_CON_PORT_DATA_SIZE) {
  196. nbyte = PSX_CON_PORT_DATA_SIZE;
  197. }
  198. SesBuf = ((PPEB_PSX_DATA)NtCurrentPeb()->SubSystemData)->SessionDataBaseAddress;
  199. Request.Request = ConRequest;
  200. Request.d.Con.Request = ScReadFile;
  201. Request.d.Con.d.IoBuf.Handle = (HANDLE)args->FileDes;
  202. Request.d.Con.d.IoBuf.Len = nbyte;
  203. if (flags & O_NONBLOCK) {
  204. Request.d.Con.d.IoBuf.Flags = PSXSES_NONBLOCK;
  205. } else {
  206. Request.d.Con.d.IoBuf.Flags = 0;
  207. }
  208. Status = SendConsoleRequest(&Request);
  209. //
  210. // Want to handle any signals generated as a result of console
  211. // operations.
  212. //
  213. PdxNullPosixApi();
  214. if (0 != Status) {
  215. errno = Status;
  216. return -1;
  217. }
  218. nbyte = Request.d.Con.d.IoBuf.Len;
  219. if (-1 == nbyte) {
  220. KdPrint(("PSXDLL: Didn't expect to get here\n"));
  221. errno = EINTR;
  222. return -1;
  223. }
  224. memcpy(buf, SesBuf, nbyte);
  225. return nbyte;
  226. }
  227. ssize_t
  228. __cdecl
  229. write(int fildes, const void *buf, unsigned int nbyte)
  230. {
  231. PSX_API_MSG m;
  232. PPSX_WRITE_MSG args;
  233. NTSTATUS Status;
  234. PVOID SesBuf;
  235. SCREQUESTMSG Request;
  236. int flags;
  237. args = &m.u.Write;
  238. PSX_FORMAT_API_MSG(m, PsxWriteApi, sizeof(*args));
  239. args->FileDes = fildes;
  240. args->Buf = (void *)buf;
  241. args->Nbytes = nbyte;
  242. args->Command = IO_COMMAND_DONE;
  243. for (;;) {
  244. Status = NtRequestWaitReplyPort(PsxPortHandle,
  245. (PPORT_MESSAGE)&m, (PPORT_MESSAGE)&m);
  246. if (!NT_SUCCESS(Status)) {
  247. #ifdef PSX_MORE_ERRORS
  248. KdPrint(("PSXDLL: write: NtRequestWaitReplyPort: 0x%x\n", Status));
  249. #endif
  250. _exit(0);
  251. }
  252. if (m.Error == EINTR && m.Signal == SIGCONT) {
  253. //
  254. // The system call was stopped and continued. Call
  255. // again instead of returning EINTR.
  256. //
  257. PSX_FORMAT_API_MSG(m, PsxWriteApi, sizeof(*args));
  258. continue;
  259. }
  260. if (m.Error) {
  261. errno = (int)m.Error;
  262. return -1;
  263. }
  264. break;
  265. }
  266. if (IO_COMMAND_DONE == args->Command) {
  267. return m.ReturnValue;
  268. }
  269. ASSERT(IO_COMMAND_DO_CONSIO == args->Command);
  270. flags = args->Scratch1;
  271. if (nbyte > PSX_CON_PORT_DATA_SIZE) {
  272. nbyte = PSX_CON_PORT_DATA_SIZE;
  273. }
  274. SesBuf = ((PPEB_PSX_DATA)(NtCurrentPeb()->SubSystemData))->SessionDataBaseAddress;
  275. Request.Request = ConRequest;
  276. Request.d.Con.Request = ScWriteFile;
  277. Request.d.Con.d.IoBuf.Handle = (HANDLE)args->FileDes;
  278. Request.d.Con.d.IoBuf.Len = nbyte;
  279. if (flags & O_NONBLOCK) {
  280. Request.d.Con.d.IoBuf.Flags = PSXSES_NONBLOCK;
  281. }
  282. memcpy(SesBuf, buf, nbyte);
  283. Status = SendConsoleRequest(&Request);
  284. if (!NT_SUCCESS(Status)) {
  285. errno = PdxStatusToErrno(Status);
  286. return -1;
  287. }
  288. //
  289. // Want to handle any signals generated as a result of console
  290. // operations.
  291. //
  292. PdxNullPosixApi();
  293. if (-1 == Request.d.Con.d.IoBuf.Len) {
  294. errno = EBADF;
  295. }
  296. return Request.d.Con.d.IoBuf.Len;
  297. }
  298. int
  299. __cdecl
  300. dup(int fildes)
  301. {
  302. return fcntl(fildes, F_DUPFD, 0);
  303. }
  304. int
  305. __cdecl
  306. dup2(int fd, int fd2)
  307. {
  308. PSX_API_MSG m;
  309. NTSTATUS st;
  310. PPSX_DUP2_MSG args;
  311. args = &m.u.Dup2;
  312. PSX_FORMAT_API_MSG(m, PsxDup2Api, sizeof(*args));
  313. args->FileDes = fd;
  314. args->FileDes2 = fd2;
  315. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  316. (PPORT_MESSAGE)&m);
  317. #ifdef PSX_MORE_ERRORS
  318. ASSERT(NT_SUCCESS(st));
  319. #endif
  320. if (m.Error) {
  321. errno = (int)m.Error;
  322. return -1;
  323. }
  324. return (int)m.ReturnValue;
  325. }
  326. int
  327. __cdecl
  328. fcntl(int fildes, int cmd, ...)
  329. {
  330. PSX_API_MSG m;
  331. NTSTATUS Status;
  332. PPSX_FCNTL_MSG args;
  333. struct flock *pf, **ppf, *tpf = NULL;
  334. int i;
  335. va_list optarg;
  336. va_start(optarg, cmd);
  337. args = &m.u.Fcntl;
  338. PSX_FORMAT_API_MSG(m, PsxFcntlApi, sizeof(*args));
  339. args->FileDes = fildes;
  340. args->Command = cmd;
  341. switch (cmd) {
  342. case F_DUPFD:
  343. // third arg is type int
  344. args->u.i = va_arg(optarg, int);
  345. va_end(optarg);
  346. break;
  347. case F_GETFD:
  348. // no third arg
  349. va_end(optarg);
  350. break;
  351. case F_SETFD:
  352. // third arg is type int
  353. args->u.i = va_arg(optarg, int);
  354. va_end(optarg);
  355. break;
  356. case F_GETFL:
  357. // no third arg
  358. va_end(optarg);
  359. break;
  360. case F_SETFL:
  361. // third arg is type int
  362. args->u.i = va_arg(optarg, int);
  363. va_end(optarg);
  364. break;
  365. case F_GETLK:
  366. case F_SETLK:
  367. case F_SETLKW:
  368. // third arg is type struct flock*
  369. pf = va_arg(optarg, struct flock *);
  370. va_end(optarg);
  371. tpf = RtlAllocateHeap(PdxPortHeap, 0, sizeof(struct flock));
  372. if (NULL == tpf) {
  373. errno = ENOMEM;
  374. return -1;
  375. }
  376. Status = STATUS_SUCCESS;
  377. try {
  378. memcpy((PVOID)tpf, (PVOID)pf, sizeof(struct flock));
  379. } except (EXCEPTION_EXECUTE_HANDLER) {
  380. Status = STATUS_UNSUCCESSFUL;
  381. }
  382. if (!NT_SUCCESS(Status)) {
  383. RtlFreeHeap(PdxPortHeap, 0, (PVOID)tpf);
  384. errno = EFAULT;
  385. return -1;
  386. }
  387. args->u.pf = (struct flock *)((PCHAR)tpf + PsxPortMemoryRemoteDelta);
  388. break;
  389. #if DBG
  390. case 99:
  391. // no third arg
  392. va_end(optarg);
  393. break;
  394. #endif
  395. default:
  396. // unknown command
  397. va_end(optarg);
  398. errno = EINVAL;
  399. return -1;
  400. }
  401. for (;;) {
  402. Status = NtRequestWaitReplyPort(PsxPortHandle,
  403. (PPORT_MESSAGE)&m, (PPORT_MESSAGE)&m);
  404. #ifdef PSX_MORE_ERRORS
  405. if (!NT_SUCCESS(Status)) {
  406. KdPrint(("PSXDLL: fcntl: NtRequest: 0x%x\n", Status));
  407. NtTerminateProcess(NtCurrentProcess(), 1);
  408. }
  409. ASSERT(NT_SUCCESS(Status));
  410. #endif
  411. if (m.Error == EINTR && m.Signal == SIGCONT) {
  412. PSX_FORMAT_API_MSG(m, PsxFcntlApi, sizeof(*args));
  413. continue;
  414. }
  415. if (m.Error) {
  416. if (NULL != tpf) {
  417. RtlFreeHeap(PdxPortHeap, 0, (PVOID)tpf);
  418. }
  419. errno = (int)m.Error;
  420. return -1;
  421. }
  422. // successful return
  423. break;
  424. }
  425. if (NULL != tpf) {
  426. // copy the flock back to the caller's address
  427. if (F_GETLK == cmd) {
  428. //
  429. // Copy the retrieved lock back into the user's buf.
  430. //
  431. memcpy((PVOID)pf, (PVOID)tpf, sizeof(struct flock));
  432. }
  433. RtlFreeHeap(PdxPortHeap, 0, (PVOID)tpf);
  434. }
  435. return (int)m.ReturnValue;
  436. }
  437. int
  438. __cdecl
  439. isatty(int fd)
  440. {
  441. PSX_API_MSG m;
  442. NTSTATUS Status;
  443. PPSX_ISATTY_MSG args;
  444. SCREQUESTMSG Request;
  445. args = &m.u.Isatty;
  446. PSX_FORMAT_API_MSG(m, PsxIsattyApi, sizeof(*args));
  447. args->FileDes = fd;
  448. args->Command = IO_COMMAND_DONE;
  449. Status = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  450. (PPORT_MESSAGE)&m);
  451. #ifdef PSX_MORE_ERRORS
  452. ASSERT(NT_SUCCESS(Status));
  453. #endif
  454. if (m.Error) {
  455. errno = (int)m.Error;
  456. return 0;
  457. }
  458. if (IO_COMMAND_DONE == args->Command) {
  459. return m.ReturnValue;
  460. }
  461. ASSERT(IO_COMMAND_DO_CONSIO == args->Command);
  462. Request.Request = ConRequest;
  463. Request.d.Con.Request = ScIsatty;
  464. Request.d.Con.d.IoBuf.Handle = (HANDLE)args->FileDes;
  465. Status = SendConsoleRequest(&Request);
  466. if (!NT_SUCCESS(Status)) {
  467. errno = PdxStatusToErrno(Status);
  468. return 0;
  469. }
  470. //
  471. // When the request returns, Len holds the value we're
  472. // supposed to return, 0 or 1, and -1 for error.
  473. //
  474. if (-1 == Request.d.Con.d.IoBuf.Len) {
  475. errno = EBADF;
  476. return 0;
  477. }
  478. return Request.d.Con.d.IoBuf.Len;
  479. }
  480. //
  481. // isatty2 -- just like isatty, but more permissive. Will return
  482. // TRUE if fd open on a console window, even if _POSIX_TERM is
  483. // not set.
  484. //
  485. int
  486. __cdecl
  487. isatty2(int fd)
  488. {
  489. PSX_API_MSG m;
  490. NTSTATUS Status;
  491. PPSX_ISATTY_MSG args;
  492. SCREQUESTMSG Request;
  493. args = &m.u.Isatty;
  494. PSX_FORMAT_API_MSG(m, PsxIsattyApi, sizeof(*args));
  495. args->FileDes = fd;
  496. args->Command = IO_COMMAND_DONE;
  497. Status = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  498. (PPORT_MESSAGE)&m);
  499. #ifdef PSX_MORE_ERRORS
  500. ASSERT(NT_SUCCESS(Status));
  501. #endif
  502. if (m.Error) {
  503. errno = (int)m.Error;
  504. return 0;
  505. }
  506. if (IO_COMMAND_DONE == args->Command) {
  507. return m.ReturnValue;
  508. }
  509. ASSERT(IO_COMMAND_DO_CONSIO == args->Command);
  510. Request.Request = ConRequest;
  511. Request.d.Con.Request = ScIsatty2;
  512. Request.d.Con.d.IoBuf.Handle = (HANDLE)args->FileDes;
  513. Status = SendConsoleRequest(&Request);
  514. if (!NT_SUCCESS(Status)) {
  515. errno = PdxStatusToErrno(Status);
  516. return 0;
  517. }
  518. //
  519. // When the request returns, Len holds the value we're
  520. // supposed to return, 0 or 1, and -1 for error.
  521. //
  522. if (-1 == Request.d.Con.d.IoBuf.Len) {
  523. errno = EBADF;
  524. return 0;
  525. }
  526. return Request.d.Con.d.IoBuf.Len;
  527. }
  528. int
  529. __cdecl
  530. ftruncate(int fildes, off_t len)
  531. {
  532. PSX_API_MSG m;
  533. PPSX_FTRUNCATE_MSG args;
  534. NTSTATUS Status;
  535. args = &m.u.Ftruncate;
  536. PSX_FORMAT_API_MSG(m, PsxFtruncateApi, sizeof(*args));
  537. args->FileDes = fildes;
  538. args->Length = len;
  539. Status = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  540. (PPORT_MESSAGE)&m);
  541. if (!NT_SUCCESS(Status)) {
  542. return -1;
  543. }
  544. if (m.Error) {
  545. errno = (int)m.Error;
  546. return -1;
  547. }
  548. return 0;
  549. }