this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <fcntl.h>
3#include <sys/stat.h>
4#include <unistd.h>
5
6#include <cerrno>
7
8#include "builtins.h"
9#include "file.h"
10#include "module-builtins.h"
11#include "modules.h"
12#include "os.h"
13#include "runtime.h"
14#include "symbols.h"
15
16namespace py {
17
18RawObject FUNC(_os, access)(Thread*, Arguments args) {
19 CHECK(args.get(0).isStr(), "path must be str");
20 unique_c_ptr<char> path(Str::cast(args.get(0)).toCStr());
21 CHECK(args.get(1).isSmallInt(), "mode must be int");
22 int result = OS::access(path.get(), SmallInt::cast(args.get(1)).value());
23 return Bool::fromBool(result);
24}
25
26RawObject FUNC(_os, close)(Thread* thread, Arguments args) {
27 CHECK(args.get(0).isSmallInt(), "fd must be small int");
28 word fd = SmallInt::cast(args.get(0)).value();
29 int result = File::close(fd);
30 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
31 return NoneType::object();
32}
33
34RawObject FUNC(_os, fstat_size)(Thread* thread, Arguments args) {
35 CHECK(args.get(0).isSmallInt(), "fd must be small int");
36 word fd = SmallInt::cast(args.get(0)).value();
37 int64_t result = File::size(fd);
38 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
39 return thread->runtime()->newInt(result);
40}
41
42RawObject FUNC(_os, ftruncate)(Thread* thread, Arguments args) {
43 CHECK(args.get(0).isSmallInt(), "fd must be small int");
44 word fd = SmallInt::cast(args.get(0)).value();
45 CHECK(args.get(1).isSmallInt(), "size must be small int");
46 word size = SmallInt::cast(args.get(1)).value();
47 int result = File::truncate(fd, size);
48 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
49 return NoneType::object();
50}
51
52RawObject FUNC(_os, isatty)(Thread*, Arguments args) {
53 CHECK(args.get(0).isSmallInt(), "fd must be small int");
54 word fd = SmallInt::cast(args.get(0)).value();
55 int result = File::isatty(fd);
56 return Bool::fromBool(result < 0 ? false : result);
57}
58
59RawObject FUNC(_os, isdir)(Thread* thread, Arguments args) {
60 CHECK(args.get(0).isSmallInt(), "fd must be small int");
61 word fd = SmallInt::cast(args.get(0)).value();
62 int result = File::isDirectory(fd);
63 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
64 return Bool::fromBool(result);
65}
66
67RawObject FUNC(_os, lseek)(Thread* thread, Arguments args) {
68 CHECK(args.get(0).isSmallInt(), "fd must be small int");
69 word fd = SmallInt::cast(args.get(0)).value();
70 CHECK(args.get(1).isInt(), "offset must be int");
71 word offset = Int::cast(args.get(1)).asWord();
72 CHECK(args.get(2).isSmallInt(), "whence must be int");
73 word whence = SmallInt::cast(args.get(2)).value();
74 int64_t result = File::seek(fd, offset, whence);
75 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
76 return thread->runtime()->newInt(result);
77}
78
79RawObject FUNC(_os, open)(Thread* thread, Arguments args) {
80 HandleScope scope(thread);
81 Object flags_obj(&scope, args.get(1));
82 CHECK(flags_obj.isSmallInt(), "flags must be small int");
83 word flags = SmallInt::cast(*flags_obj).value();
84 Object mode_obj(&scope, args.get(2));
85 CHECK(mode_obj.isSmallInt(), "mode must be small int");
86 word mode = SmallInt::cast(*mode_obj).value();
87 Object dir_fd_obj(&scope, args.get(3));
88 if (!dir_fd_obj.isNoneType()) {
89 UNIMPLEMENTED("_os_open with dir_fd");
90 }
91 Object path_obj(&scope, args.get(0));
92 int result;
93 if (path_obj.isStr()) {
94 unique_c_ptr<char> path_cstr(Str::cast(*path_obj).toCStr());
95 result = File::open(path_cstr.get(), flags, mode);
96 } else if (path_obj.isBytes()) {
97 unique_c_ptr<char> path_cstr(Bytes::cast(*path_obj).toCStr());
98 result = File::open(path_cstr.get(), flags, mode);
99 } else {
100 UNIMPLEMENTED("_os_open with non-str/bytes path");
101 }
102 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
103 return SmallInt::fromWord(result);
104}
105
106static bool charInMode(const char c, const Str& mode) {
107 for (word i = 0; i < mode.length(); i++) {
108 if (c == mode.byteAt(i)) return true;
109 }
110 return false;
111}
112
113static word flagsFromMode(const Str& mode) {
114 word flags = 0;
115 bool readable = false, writable = false;
116 if (charInMode('x', mode)) {
117 writable = true;
118 flags = O_EXCL | O_CREAT;
119 } else if (charInMode('r', mode)) {
120 readable = true;
121 } else if (charInMode('w', mode)) {
122 writable = true;
123 flags = O_CREAT | O_TRUNC;
124 } else if (charInMode('a', mode)) {
125 writable = true;
126 flags = O_APPEND | O_CREAT;
127 }
128 if (charInMode('+', mode)) {
129 readable = writable = true;
130 }
131 if (readable && writable) {
132 flags |= O_RDWR;
133 } else if (readable) {
134 flags |= O_RDONLY;
135 } else {
136 flags |= O_WRONLY;
137 }
138 flags |= File::kBinaryFlag;
139 flags |= File::kNoInheritFlag;
140 return flags;
141}
142
143RawObject FUNC(_os, parse_mode)(Thread* thread, Arguments args) {
144 HandleScope scope(thread);
145 Str mode(&scope, args.get(0));
146 return thread->runtime()->newInt(flagsFromMode(mode));
147}
148
149RawObject FUNC(_os, read)(Thread* thread, Arguments args) {
150 HandleScope scope(thread);
151 Object fd_obj(&scope, args.get(0));
152 CHECK(fd_obj.isSmallInt(), "fd must be small int");
153 Object count_obj(&scope, args.get(1));
154 CHECK(count_obj.isSmallInt(), "count must be small int");
155 CHECK(!Int::cast(*count_obj).isNegative(), "count must be non-negative");
156 size_t count = SmallInt::cast(*count_obj).value();
157 std::unique_ptr<byte[]> buffer(new byte[count]);
158 int fd = SmallInt::cast(*fd_obj).value();
159 ssize_t result = File::read(fd, buffer.get(), count);
160 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
161 return thread->runtime()->newBytesWithAll(View<byte>(buffer.get(), result));
162}
163
164RawObject FUNC(_os, set_noinheritable)(Thread* thread, Arguments args) {
165 int fd = SmallInt::cast(args.get(0)).value();
166 int result = File::setNoInheritable(fd);
167 if (result < 0) return thread->raiseOSErrorFromErrno(-result);
168 return NoneType::object();
169}
170
171} // namespace py