1570af302Sopenharmony_ci#include "stdio_impl.h"
2570af302Sopenharmony_ci#include <fcntl.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include <errno.h>
5570af302Sopenharmony_ci
6570af302Sopenharmony_ciint __fmodeflags(const char *mode, int *flags)
7570af302Sopenharmony_ci{
8570af302Sopenharmony_ci	int mode_flags = 0;
9570af302Sopenharmony_ci	int options = 0;
10570af302Sopenharmony_ci
11570af302Sopenharmony_ci	switch (*mode) {
12570af302Sopenharmony_ci		case 'r':
13570af302Sopenharmony_ci			mode_flags = O_RDONLY;
14570af302Sopenharmony_ci			*flags = F_NOWR;
15570af302Sopenharmony_ci			break;
16570af302Sopenharmony_ci		case 'w':
17570af302Sopenharmony_ci			mode_flags = O_WRONLY;
18570af302Sopenharmony_ci			options = O_TRUNC | O_CREAT;
19570af302Sopenharmony_ci			*flags = F_NORD;
20570af302Sopenharmony_ci			break;
21570af302Sopenharmony_ci		case 'a':
22570af302Sopenharmony_ci			mode_flags = O_WRONLY;
23570af302Sopenharmony_ci			options = O_APPEND | O_CREAT;
24570af302Sopenharmony_ci			*flags = F_NORD | F_APP;
25570af302Sopenharmony_ci			break;
26570af302Sopenharmony_ci		default:
27570af302Sopenharmony_ci			errno = EINVAL;
28570af302Sopenharmony_ci			return -EINVAL;
29570af302Sopenharmony_ci	}
30570af302Sopenharmony_ci
31570af302Sopenharmony_ci	mode++;
32570af302Sopenharmony_ci	while (*mode != '\0') {
33570af302Sopenharmony_ci		switch (*mode) {
34570af302Sopenharmony_ci			case '+':
35570af302Sopenharmony_ci				mode_flags = O_RDWR;
36570af302Sopenharmony_ci				*flags &= ~(F_NORD | F_NOWR);
37570af302Sopenharmony_ci				break;
38570af302Sopenharmony_ci			case 'x':
39570af302Sopenharmony_ci				/* need O_CREAT check */
40570af302Sopenharmony_ci				options |= O_EXCL;
41570af302Sopenharmony_ci				break;
42570af302Sopenharmony_ci			case 'e':
43570af302Sopenharmony_ci				options |= O_CLOEXEC;
44570af302Sopenharmony_ci				break;
45570af302Sopenharmony_ci			case 'b':
46570af302Sopenharmony_ci				break;
47570af302Sopenharmony_ci			default:
48570af302Sopenharmony_ci				/* only accept "+xeb" */
49570af302Sopenharmony_ci				break;
50570af302Sopenharmony_ci		}
51570af302Sopenharmony_ci		mode++;
52570af302Sopenharmony_ci	}
53570af302Sopenharmony_ci
54570af302Sopenharmony_ci	return mode_flags | options;
55570af302Sopenharmony_ci}
56