| author | |
| committer | |
| log | af4cc20ce275aeb0e59eee3d893b2f310c1f0239 |
| tree | cc3ff8fa792c20ff0fc0f1e19e98998cc76c07c2 |
| parent | 03a23418ff13e6ff64cdeed3ef4b54f99c533d88 |
| parent | 9fe4c89230df2d78c8bf37b4b1d7a9bedb92677b |
Master branch added in the concept of library versioning being optional
to main.cpp. It will need to be re-added into this branch before merging
back into master.34 files changed, 1680 insertions(+), 119 deletions(-)
README.md+18| ... | ... | @@ -76,3 +76,21 @@ Hopefully this will be fixed upstream with LLVM 10.0.1. |
| 76 | 76 | ##### Windows |
| 77 | 77 | |
| 78 | 78 | See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows |
| 79 | ||
| 80 | ## License | |
| 81 | ||
| 82 | The ultimate goal of the Zig project is to serve users. As a first-order | |
| 83 | effect, this means users of the compiler, helping programmers to write better | |
| 84 | code. Even more important, however, are the end users. | |
| 85 | ||
| 86 | Zig is intended to be used to help end users accomplish their goals. For | |
| 87 | example, it would be inappropriate and offensive to use Zig to implement | |
| 88 | [dark patterns](https://en.wikipedia.org/wiki/Dark_pattern) and it would be | |
| 89 | shameful to utilize Zig to exploit people instead of benefit them. | |
| 90 | ||
| 91 | However, such problems are best solved with social norms, not with software | |
| 92 | licenses. Any attempt to complicate the software license of Zig would risk | |
| 93 | compromising the value Zig provides to users. | |
| 94 | ||
| 95 | Therefore, Zig is available under the MIT (Expat) License, and comes with a | |
| 96 | humble request: use it to make software better serve the needs of end users. |
build.zig+1| ... | ... | @@ -65,6 +65,7 @@ pub fn build(b: *Builder) !void { |
| 65 | 65 | "README.md", |
| 66 | 66 | ".z.0", |
| 67 | 67 | ".z.9", |
| 68 | ".gz", | |
| 68 | 69 | "rfc1951.txt", |
| 69 | 70 | }, |
| 70 | 71 | }); |
lib/std/build.zig+80-44| ... | ... | @@ -258,9 +258,14 @@ pub const Builder = struct { |
| 258 | 258 | })); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | pub fn addSharedLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep { | |
| 261 | pub fn addSharedLibrary( | |
| 262 | self: *Builder, | |
| 263 | name: []const u8, | |
| 264 | root_src: ?[]const u8, | |
| 265 | kind: LibExeObjStep.SharedLibKind, | |
| 266 | ) *LibExeObjStep { | |
| 262 | 267 | const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null; |
| 263 | return LibExeObjStep.createSharedLibrary(self, name, root_src_param, ver); | |
| 268 | return LibExeObjStep.createSharedLibrary(self, name, root_src_param, kind); | |
| 264 | 269 | } |
| 265 | 270 | |
| 266 | 271 | pub fn addStaticLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| ... | ... | @@ -338,11 +343,13 @@ pub const Builder = struct { |
| 338 | 343 | return TranslateCStep.create(self, source); |
| 339 | 344 | } |
| 340 | 345 | |
| 341 | pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version { | |
| 342 | return Version{ | |
| 343 | .major = major, | |
| 344 | .minor = minor, | |
| 345 | .patch = patch, | |
| 346 | pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) LibExeObjStep.SharedLibKind { | |
| 347 | return .{ | |
| 348 | .versioned = .{ | |
| 349 | .major = major, | |
| 350 | .minor = minor, | |
| 351 | .patch = patch, | |
| 352 | }, | |
| 346 | 353 | }; |
| 347 | 354 | } |
| 348 | 355 | |
| ... | ... | @@ -1048,6 +1055,7 @@ pub const Builder = struct { |
| 1048 | 1055 | .Bin => self.exe_dir, |
| 1049 | 1056 | .Lib => self.lib_dir, |
| 1050 | 1057 | .Header => self.h_dir, |
| 1058 | .Custom => |path| fs.path.join(self.allocator, &[_][]const u8{ self.install_path, path }) catch unreachable, | |
| 1051 | 1059 | }; |
| 1052 | 1060 | return fs.path.resolve( |
| 1053 | 1061 | self.allocator, |
| ... | ... | @@ -1166,7 +1174,7 @@ pub const LibExeObjStep = struct { |
| 1166 | 1174 | version_script: ?[]const u8 = null, |
| 1167 | 1175 | out_filename: []const u8, |
| 1168 | 1176 | is_dynamic: bool, |
| 1169 | version: Version, | |
| 1177 | version: ?Version, | |
| 1170 | 1178 | build_mode: builtin.Mode, |
| 1171 | 1179 | kind: Kind, |
| 1172 | 1180 | major_only_filename: []const u8, |
| ... | ... | @@ -1212,6 +1220,8 @@ pub const LibExeObjStep = struct { |
| 1212 | 1220 | is_linking_libc: bool = false, |
| 1213 | 1221 | vcpkg_bin_path: ?[]const u8 = null, |
| 1214 | 1222 | |
| 1223 | /// This may be set in order to override the default install directory | |
| 1224 | override_dest_dir: ?InstallDir, | |
| 1215 | 1225 | installed_path: ?[]const u8, |
| 1216 | 1226 | install_step: ?*InstallArtifactStep, |
| 1217 | 1227 | |
| ... | ... | @@ -1268,33 +1278,41 @@ pub const LibExeObjStep = struct { |
| 1268 | 1278 | Test, |
| 1269 | 1279 | }; |
| 1270 | 1280 | |
| 1271 | pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, ver: Version) *LibExeObjStep { | |
| 1281 | const SharedLibKind = union(enum) { | |
| 1282 | versioned: Version, | |
| 1283 | unversioned: void, | |
| 1284 | }; | |
| 1285 | ||
| 1286 | pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, kind: SharedLibKind) *LibExeObjStep { | |
| 1272 | 1287 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 1273 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, ver); | |
| 1288 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, switch (kind) { | |
| 1289 | .versioned => |ver| ver, | |
| 1290 | .unversioned => null, | |
| 1291 | }); | |
| 1274 | 1292 | return self; |
| 1275 | 1293 | } |
| 1276 | 1294 | |
| 1277 | 1295 | pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep { |
| 1278 | 1296 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 1279 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, builder.version(0, 0, 0)); | |
| 1297 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, null); | |
| 1280 | 1298 | return self; |
| 1281 | 1299 | } |
| 1282 | 1300 | |
| 1283 | 1301 | pub fn createObject(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep { |
| 1284 | 1302 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 1285 | self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); | |
| 1303 | self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, null); | |
| 1286 | 1304 | return self; |
| 1287 | 1305 | } |
| 1288 | 1306 | |
| 1289 | 1307 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?FileSource, is_dynamic: bool) *LibExeObjStep { |
| 1290 | 1308 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 1291 | self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, builder.version(0, 0, 0)); | |
| 1309 | self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, null); | |
| 1292 | 1310 | return self; |
| 1293 | 1311 | } |
| 1294 | 1312 | |
| 1295 | 1313 | pub fn createTest(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep { |
| 1296 | 1314 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 1297 | self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, builder.version(0, 0, 0)); | |
| 1315 | self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, null); | |
| 1298 | 1316 | return self; |
| 1299 | 1317 | } |
| 1300 | 1318 | |
| ... | ... | @@ -1304,7 +1322,7 @@ pub const LibExeObjStep = struct { |
| 1304 | 1322 | root_src: ?FileSource, |
| 1305 | 1323 | kind: Kind, |
| 1306 | 1324 | is_dynamic: bool, |
| 1307 | ver: Version, | |
| 1325 | ver: ?Version, | |
| 1308 | 1326 | ) LibExeObjStep { |
| 1309 | 1327 | if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) { |
| 1310 | 1328 | panic("invalid name: '{}'. It looks like a file path, but it is supposed to be the library or application name.", .{name}); |
| ... | ... | @@ -1348,6 +1366,7 @@ pub const LibExeObjStep = struct { |
| 1348 | 1366 | .rdynamic = false, |
| 1349 | 1367 | .output_dir = null, |
| 1350 | 1368 | .single_threaded = false, |
| 1369 | .override_dest_dir = null, | |
| 1351 | 1370 | .installed_path = null, |
| 1352 | 1371 | .install_step = null, |
| 1353 | 1372 | }; |
| ... | ... | @@ -1375,17 +1394,17 @@ pub const LibExeObjStep = struct { |
| 1375 | 1394 | self.target.staticLibSuffix(), |
| 1376 | 1395 | }); |
| 1377 | 1396 | self.out_lib_filename = self.out_filename; |
| 1378 | } else { | |
| 1397 | } else if (self.version) |version| { | |
| 1379 | 1398 | if (self.target.isDarwin()) { |
| 1380 | 1399 | self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", .{ |
| 1381 | 1400 | self.name, |
| 1382 | self.version.major, | |
| 1383 | self.version.minor, | |
| 1384 | self.version.patch, | |
| 1401 | version.major, | |
| 1402 | version.minor, | |
| 1403 | version.patch, | |
| 1385 | 1404 | }); |
| 1386 | 1405 | self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{ |
| 1387 | 1406 | self.name, |
| 1388 | self.version.major, | |
| 1407 | version.major, | |
| 1389 | 1408 | }); |
| 1390 | 1409 | self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name}); |
| 1391 | 1410 | self.out_lib_filename = self.out_filename; |
| ... | ... | @@ -1395,14 +1414,25 @@ pub const LibExeObjStep = struct { |
| 1395 | 1414 | } else { |
| 1396 | 1415 | self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", .{ |
| 1397 | 1416 | self.name, |
| 1398 | self.version.major, | |
| 1399 | self.version.minor, | |
| 1400 | self.version.patch, | |
| 1417 | version.major, | |
| 1418 | version.minor, | |
| 1419 | version.patch, | |
| 1401 | 1420 | }); |
| 1402 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, self.version.major }); | |
| 1421 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major }); | |
| 1403 | 1422 | self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name}); |
| 1404 | 1423 | self.out_lib_filename = self.out_filename; |
| 1405 | 1424 | } |
| 1425 | } else { | |
| 1426 | if (self.target.isDarwin()) { | |
| 1427 | self.out_filename = self.builder.fmt("lib{}.dylib", .{self.name}); | |
| 1428 | self.out_lib_filename = self.out_filename; | |
| 1429 | } else if (self.target.isWindows()) { | |
| 1430 | self.out_filename = self.builder.fmt("{}.dll", .{self.name}); | |
| 1431 | self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name}); | |
| 1432 | } else { | |
| 1433 | self.out_filename = self.builder.fmt("lib{}.so", .{self.name}); | |
| 1434 | self.out_lib_filename = self.out_filename; | |
| 1435 | } | |
| 1406 | 1436 | } |
| 1407 | 1437 | }, |
| 1408 | 1438 | } |
| ... | ... | @@ -2037,14 +2067,16 @@ pub const LibExeObjStep = struct { |
| 2037 | 2067 | zig_args.append(self.name) catch unreachable; |
| 2038 | 2068 | |
| 2039 | 2069 | if (self.kind == Kind.Lib and self.is_dynamic) { |
| 2040 | zig_args.append("--ver-major") catch unreachable; | |
| 2041 | zig_args.append(builder.fmt("{}", .{self.version.major})) catch unreachable; | |
| 2070 | if (self.version) |version| { | |
| 2071 | zig_args.append("--ver-major") catch unreachable; | |
| 2072 | zig_args.append(builder.fmt("{}", .{version.major})) catch unreachable; | |
| 2042 | 2073 | |
| 2043 | zig_args.append("--ver-minor") catch unreachable; | |
| 2044 | zig_args.append(builder.fmt("{}", .{self.version.minor})) catch unreachable; | |
| 2074 | zig_args.append("--ver-minor") catch unreachable; | |
| 2075 | zig_args.append(builder.fmt("{}", .{version.minor})) catch unreachable; | |
| 2045 | 2076 | |
| 2046 | zig_args.append("--ver-patch") catch unreachable; | |
| 2047 | zig_args.append(builder.fmt("{}", .{self.version.patch})) catch unreachable; | |
| 2077 | zig_args.append("--ver-patch") catch unreachable; | |
| 2078 | zig_args.append(builder.fmt("{}", .{version.patch})) catch unreachable; | |
| 2079 | } | |
| 2048 | 2080 | } |
| 2049 | 2081 | if (self.is_dynamic) { |
| 2050 | 2082 | try zig_args.append("-dynamic"); |
| ... | ... | @@ -2285,7 +2317,7 @@ pub const LibExeObjStep = struct { |
| 2285 | 2317 | } |
| 2286 | 2318 | } |
| 2287 | 2319 | |
| 2288 | if (self.kind == Kind.Lib and self.is_dynamic and self.target.wantSharedLibSymLinks()) { | |
| 2320 | if (self.kind == Kind.Lib and self.is_dynamic and self.version != null and self.target.wantSharedLibSymLinks()) { | |
| 2289 | 2321 | try doAtomicSymLinks(builder.allocator, self.getOutputPath(), self.major_only_filename, self.name_only_filename); |
| 2290 | 2322 | } |
| 2291 | 2323 | } |
| ... | ... | @@ -2309,17 +2341,17 @@ pub const InstallArtifactStep = struct { |
| 2309 | 2341 | .builder = builder, |
| 2310 | 2342 | .step = Step.init(.InstallArtifact, builder.fmt("install {}", .{artifact.step.name}), builder.allocator, make), |
| 2311 | 2343 | .artifact = artifact, |
| 2312 | .dest_dir = switch (artifact.kind) { | |
| 2344 | .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) { | |
| 2313 | 2345 | .Obj => unreachable, |
| 2314 | 2346 | .Test => unreachable, |
| 2315 | .Exe => .Bin, | |
| 2316 | .Lib => .Lib, | |
| 2347 | .Exe => InstallDir{ .Bin = {} }, | |
| 2348 | .Lib => InstallDir{ .Lib = {} }, | |
| 2317 | 2349 | }, |
| 2318 | 2350 | .pdb_dir = if (artifact.producesPdbFile()) blk: { |
| 2319 | 2351 | if (artifact.kind == .Exe) { |
| 2320 | break :blk InstallDir.Bin; | |
| 2352 | break :blk InstallDir{ .Bin = {} }; | |
| 2321 | 2353 | } else { |
| 2322 | break :blk InstallDir.Lib; | |
| 2354 | break :blk InstallDir{ .Lib = {} }; | |
| 2323 | 2355 | } |
| 2324 | 2356 | } else null, |
| 2325 | 2357 | .h_dir = if (artifact.kind == .Lib and artifact.emit_h) .Header else null, |
| ... | ... | @@ -2329,8 +2361,10 @@ pub const InstallArtifactStep = struct { |
| 2329 | 2361 | |
| 2330 | 2362 | builder.pushInstalledFile(self.dest_dir, artifact.out_filename); |
| 2331 | 2363 | if (self.artifact.isDynamicLibrary()) { |
| 2332 | builder.pushInstalledFile(.Lib, artifact.major_only_filename); | |
| 2333 | builder.pushInstalledFile(.Lib, artifact.name_only_filename); | |
| 2364 | if (self.artifact.version != null) { | |
| 2365 | builder.pushInstalledFile(.Lib, artifact.major_only_filename); | |
| 2366 | builder.pushInstalledFile(.Lib, artifact.name_only_filename); | |
| 2367 | } | |
| 2334 | 2368 | if (self.artifact.target.isWindows()) { |
| 2335 | 2369 | builder.pushInstalledFile(.Lib, artifact.out_lib_filename); |
| 2336 | 2370 | } |
| ... | ... | @@ -2350,7 +2384,7 @@ pub const InstallArtifactStep = struct { |
| 2350 | 2384 | |
| 2351 | 2385 | const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename); |
| 2352 | 2386 | try builder.updateFile(self.artifact.getOutputPath(), full_dest_path); |
| 2353 | if (self.artifact.isDynamicLibrary() and self.artifact.target.wantSharedLibSymLinks()) { | |
| 2387 | if (self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) { | |
| 2354 | 2388 | try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename, self.artifact.name_only_filename); |
| 2355 | 2389 | } |
| 2356 | 2390 | if (self.pdb_dir) |pdb_dir| { |
| ... | ... | @@ -2615,11 +2649,13 @@ const VcpkgRootStatus = enum { |
| 2615 | 2649 | |
| 2616 | 2650 | pub const VcpkgLinkage = std.builtin.LinkMode; |
| 2617 | 2651 | |
| 2618 | pub const InstallDir = enum { | |
| 2619 | Prefix, | |
| 2620 | Lib, | |
| 2621 | Bin, | |
| 2622 | Header, | |
| 2652 | pub const InstallDir = union(enum) { | |
| 2653 | Prefix: void, | |
| 2654 | Lib: void, | |
| 2655 | Bin: void, | |
| 2656 | Header: void, | |
| 2657 | /// A path relative to the prefix | |
| 2658 | Custom: []const u8, | |
| 2623 | 2659 | }; |
| 2624 | 2660 | |
| 2625 | 2661 | pub const InstalledFile = struct { |
lib/std/c.zig+11-4| ... | ... | @@ -132,8 +132,6 @@ pub usingnamespace switch (builtin.os.tag) { |
| 132 | 132 | }, |
| 133 | 133 | }; |
| 134 | 134 | |
| 135 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; | |
| 136 | pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int; | |
| 137 | 135 | pub extern "c" fn rmdir(path: [*:0]const u8) c_int; |
| 138 | 136 | pub extern "c" fn getenv(name: [*:0]const u8) ?[*:0]u8; |
| 139 | 137 | pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; |
| ... | ... | @@ -237,8 +235,15 @@ pub usingnamespace switch (builtin.os.tag) { |
| 237 | 235 | |
| 238 | 236 | pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int; |
| 239 | 237 | pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize; |
| 240 | pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int; | |
| 241 | pub extern "c" fn setuid(uid: c_uint) c_int; | |
| 238 | ||
| 239 | pub extern "c" fn setuid(uid: uid_t) c_int; | |
| 240 | pub extern "c" fn setgid(gid: gid_t) c_int; | |
| 241 | pub extern "c" fn seteuid(euid: uid_t) c_int; | |
| 242 | pub extern "c" fn setegid(egid: gid_t) c_int; | |
| 243 | pub extern "c" fn setreuid(ruid: uid_t, euid: uid_t) c_int; | |
| 244 | pub extern "c" fn setregid(rgid: gid_t, egid: gid_t) c_int; | |
| 245 | pub extern "c" fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) c_int; | |
| 246 | pub extern "c" fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) c_int; | |
| 242 | 247 | |
| 243 | 248 | pub extern "c" fn aligned_alloc(alignment: usize, size: usize) ?*c_void; |
| 244 | 249 | pub extern "c" fn malloc(usize) ?*c_void; |
| ... | ... | @@ -335,3 +340,5 @@ pub extern "c" fn sync() void; |
| 335 | 340 | pub extern "c" fn syncfs(fd: c_int) c_int; |
| 336 | 341 | pub extern "c" fn fsync(fd: c_int) c_int; |
| 337 | 342 | pub extern "c" fn fdatasync(fd: c_int) c_int; |
| 343 | ||
| 344 | pub extern "c" fn prctl(option: c_int, ...) c_int; |
lib/std/compress.zig+2| ... | ... | @@ -6,8 +6,10 @@ |
| 6 | 6 | const std = @import("std.zig"); |
| 7 | 7 | |
| 8 | 8 | pub const deflate = @import("compress/deflate.zig"); |
| 9 | pub const gzip = @import("compress/gzip.zig"); | |
| 9 | 10 | pub const zlib = @import("compress/zlib.zig"); |
| 10 | 11 | |
| 11 | 12 | test "" { |
| 13 | _ = gzip; | |
| 12 | 14 | _ = zlib; |
| 13 | 15 | } |
lib/std/compress/deflate.zig+149-35| ... | ... | @@ -21,48 +21,121 @@ const MAXDCODES = 30; |
| 21 | 21 | const MAXCODES = MAXLCODES + MAXDCODES; |
| 22 | 22 | const FIXLCODES = 288; |
| 23 | 23 | |
| 24 | // The maximum length of a Huffman code's prefix we can decode using the fast | |
| 25 | // path. The factor 9 is inherited from Zlib, tweaking the value showed little | |
| 26 | // or no changes in the profiler output. | |
| 27 | const PREFIX_LUT_BITS = 9; | |
| 28 | ||
| 24 | 29 | const Huffman = struct { |
| 30 | // Number of codes for each possible length | |
| 25 | 31 | count: [MAXBITS + 1]u16, |
| 32 | // Mapping between codes and symbols | |
| 26 | 33 | symbol: [MAXCODES]u16, |
| 27 | 34 | |
| 28 | fn construct(self: *Huffman, length: []const u16) !void { | |
| 35 | // The decoding process uses a trick explained by Mark Adler in [1]. | |
| 36 | // We basically precompute for a fixed number of codes (0 <= x <= 2^N-1) | |
| 37 | // the symbol and the effective code length we'd get if the decoder was run | |
| 38 | // on the given N-bit sequence. | |
| 39 | // A code with length 0 means the sequence is not a valid prefix for this | |
| 40 | // canonical Huffman code and we have to decode it using a slower method. | |
| 41 | // | |
| 42 | // [1] https://github.com/madler/zlib/blob/v1.2.11/doc/algorithm.txt#L58 | |
| 43 | prefix_lut: [1 << PREFIX_LUT_BITS]u16, | |
| 44 | prefix_lut_len: [1 << PREFIX_LUT_BITS]u16, | |
| 45 | // The following info refer to the codes of length PREFIX_LUT_BITS+1 and are | |
| 46 | // used to bootstrap the bit-by-bit reading method if the fast-path fails. | |
| 47 | last_code: u16, | |
| 48 | last_index: u16, | |
| 49 | ||
| 50 | fn construct(self: *Huffman, code_length: []const u16) !void { | |
| 29 | 51 | for (self.count) |*val| { |
| 30 | 52 | val.* = 0; |
| 31 | 53 | } |
| 32 | 54 | |
| 33 | for (length) |val| { | |
| 34 | self.count[val] += 1; | |
| 55 | for (code_length) |len| { | |
| 56 | self.count[len] += 1; | |
| 35 | 57 | } |
| 36 | 58 | |
| 37 | if (self.count[0] == length.len) | |
| 59 | // All zero. | |
| 60 | if (self.count[0] == code_length.len) | |
| 38 | 61 | return; |
| 39 | 62 | |
| 40 | 63 | var left: isize = 1; |
| 41 | 64 | for (self.count[1..]) |val| { |
| 65 | // Each added bit doubles the amount of codes. | |
| 42 | 66 | left *= 2; |
| 67 | // Make sure the number of codes with this length isn't too high. | |
| 43 | 68 | left -= @as(isize, @bitCast(i16, val)); |
| 44 | 69 | if (left < 0) |
| 45 | 70 | return error.InvalidTree; |
| 46 | 71 | } |
| 47 | 72 | |
| 48 | var offs: [MAXBITS + 1]u16 = undefined; | |
| 73 | // Compute the offset of the first symbol represented by a code of a | |
| 74 | // given length in the symbol table, together with the first canonical | |
| 75 | // Huffman code for that length. | |
| 76 | var offset: [MAXBITS + 1]u16 = undefined; | |
| 77 | var codes: [MAXBITS + 1]u16 = undefined; | |
| 49 | 78 | { |
| 79 | offset[1] = 0; | |
| 80 | codes[1] = 0; | |
| 50 | 81 | var len: usize = 1; |
| 51 | offs[1] = 0; | |
| 52 | 82 | while (len < MAXBITS) : (len += 1) { |
| 53 | offs[len + 1] = offs[len] + self.count[len]; | |
| 83 | offset[len + 1] = offset[len] + self.count[len]; | |
| 84 | codes[len + 1] = (codes[len] + self.count[len]) << 1; | |
| 54 | 85 | } |
| 55 | 86 | } |
| 56 | 87 | |
| 57 | for (length) |val, symbol| { | |
| 58 | if (val != 0) { | |
| 59 | self.symbol[offs[val]] = @truncate(u16, symbol); | |
| 60 | offs[val] += 1; | |
| 88 | self.prefix_lut_len = mem.zeroes(@TypeOf(self.prefix_lut_len)); | |
| 89 | ||
| 90 | for (code_length) |len, symbol| { | |
| 91 | if (len != 0) { | |
| 92 | // Fill the symbol table. | |
| 93 | // The symbols are assigned sequentially for each length. | |
| 94 | self.symbol[offset[len]] = @truncate(u16, symbol); | |
| 95 | // Track the last assigned offset | |
| 96 | offset[len] += 1; | |
| 97 | } | |
| 98 | ||
| 99 | if (len == 0 or len > PREFIX_LUT_BITS) | |
| 100 | continue; | |
| 101 | ||
| 102 | // Given a Huffman code of length N we have to massage it so | |
| 103 | // that it becomes an index in the lookup table. | |
| 104 | // The bit order is reversed as the fast path reads the bit | |
| 105 | // sequence MSB to LSB using an &, the order is flipped wrt the | |
| 106 | // one obtained by reading bit-by-bit. | |
| 107 | // The codes are prefix-free, if the prefix matches we can | |
| 108 | // safely ignore the trail bits. We do so by replicating the | |
| 109 | // symbol info for each combination of the trailing bits. | |
| 110 | const bits_to_fill = @intCast(u5, PREFIX_LUT_BITS - len); | |
| 111 | const rev_code = bitReverse(codes[len], len); | |
| 112 | // Track the last used code, but only for lengths < PREFIX_LUT_BITS | |
| 113 | codes[len] += 1; | |
| 114 | ||
| 115 | var j: usize = 0; | |
| 116 | while (j < @as(usize, 1) << bits_to_fill) : (j += 1) { | |
| 117 | const index = rev_code | (j << @intCast(u5, len)); | |
| 118 | assert(self.prefix_lut_len[index] == 0); | |
| 119 | self.prefix_lut[index] = @truncate(u16, symbol); | |
| 120 | self.prefix_lut_len[index] = @truncate(u16, len); | |
| 61 | 121 | } |
| 62 | 122 | } |
| 123 | ||
| 124 | self.last_code = codes[PREFIX_LUT_BITS + 1]; | |
| 125 | self.last_index = offset[PREFIX_LUT_BITS + 1] - self.count[PREFIX_LUT_BITS + 1]; | |
| 63 | 126 | } |
| 64 | 127 | }; |
| 65 | 128 | |
| 129 | // Reverse bit-by-bit a N-bit value | |
| 130 | fn bitReverse(x: usize, N: usize) usize { | |
| 131 | var tmp: usize = 0; | |
| 132 | var i: usize = 0; | |
| 133 | while (i < N) : (i += 1) { | |
| 134 | tmp |= ((x >> @intCast(u5, i)) & 1) << @intCast(u5, N - i - 1); | |
| 135 | } | |
| 136 | return tmp; | |
| 137 | } | |
| 138 | ||
| 66 | 139 | pub fn InflateStream(comptime ReaderType: type) type { |
| 67 | 140 | return struct { |
| 68 | 141 | const Self = @This(); |
| ... | ... | @@ -83,7 +156,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 83 | 156 | }; |
| 84 | 157 | pub const Reader = io.Reader(*Self, Error, read); |
| 85 | 158 | |
| 86 | bit_reader: io.BitReader(.Little, ReaderType), | |
| 159 | inner_reader: ReaderType, | |
| 87 | 160 | |
| 88 | 161 | // True if the decoder met the end of the compressed stream, no further |
| 89 | 162 | // data can be decompressed |
| ... | ... | @@ -135,7 +208,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 135 | 208 | |
| 136 | 209 | // Insert a single byte into the window. |
| 137 | 210 | // Assumes there's enough space. |
| 138 | fn appendUnsafe(self: *WSelf, value: u8) void { | |
| 211 | inline fn appendUnsafe(self: *WSelf, value: u8) void { | |
| 139 | 212 | self.buf[self.wi] = value; |
| 140 | 213 | self.wi = (self.wi + 1) & (self.buf.len - 1); |
| 141 | 214 | self.el += 1; |
| ... | ... | @@ -180,7 +253,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 180 | 253 | // of the window memory for the non-overlapping case. |
| 181 | 254 | var i: usize = 0; |
| 182 | 255 | while (i < N) : (i += 1) { |
| 183 | const index = (self.wi -% distance) % self.buf.len; | |
| 256 | const index = (self.wi -% distance) & (self.buf.len - 1); | |
| 184 | 257 | self.appendUnsafe(self.buf[index]); |
| 185 | 258 | } |
| 186 | 259 | |
| ... | ... | @@ -196,13 +269,36 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 196 | 269 | hdist: *Huffman, |
| 197 | 270 | hlen: *Huffman, |
| 198 | 271 | |
| 272 | // Temporary buffer for the bitstream, only bits 0..`bits_left` are | |
| 273 | // considered valid. | |
| 274 | bits: u32, | |
| 275 | bits_left: usize, | |
| 276 | ||
| 277 | fn peekBits(self: *Self, bits: usize) !u32 { | |
| 278 | while (self.bits_left < bits) { | |
| 279 | const byte = try self.inner_reader.readByte(); | |
| 280 | self.bits |= @as(u32, byte) << @intCast(u5, self.bits_left); | |
| 281 | self.bits_left += 8; | |
| 282 | } | |
| 283 | return self.bits & ((@as(u32, 1) << @intCast(u5, bits)) - 1); | |
| 284 | } | |
| 285 | fn readBits(self: *Self, bits: usize) !u32 { | |
| 286 | const val = self.peekBits(bits); | |
| 287 | self.discardBits(bits); | |
| 288 | return val; | |
| 289 | } | |
| 290 | fn discardBits(self: *Self, bits: usize) void { | |
| 291 | self.bits >>= @intCast(u5, bits); | |
| 292 | self.bits_left -= bits; | |
| 293 | } | |
| 294 | ||
| 199 | 295 | fn stored(self: *Self) !void { |
| 200 | 296 | // Discard the remaining bits, the lenght field is always |
| 201 | 297 | // byte-aligned (and so is the data) |
| 202 | self.bit_reader.alignToByte(); | |
| 298 | self.discardBits(self.bits_left); | |
| 203 | 299 | |
| 204 | const length = (try self.bit_reader.readBitsNoEof(u16, 16)); | |
| 205 | const length_cpl = (try self.bit_reader.readBitsNoEof(u16, 16)); | |
| 300 | const length = try self.inner_reader.readIntLittle(u16); | |
| 301 | const length_cpl = try self.inner_reader.readIntLittle(u16); | |
| 206 | 302 | |
| 207 | 303 | if (length != ~length_cpl) |
| 208 | 304 | return error.InvalidStoredSize; |
| ... | ... | @@ -237,11 +333,11 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 237 | 333 | |
| 238 | 334 | fn dynamic(self: *Self) !void { |
| 239 | 335 | // Number of length codes |
| 240 | const nlen = (try self.bit_reader.readBitsNoEof(usize, 5)) + 257; | |
| 336 | const nlen = (try self.readBits(5)) + 257; | |
| 241 | 337 | // Number of distance codes |
| 242 | const ndist = (try self.bit_reader.readBitsNoEof(usize, 5)) + 1; | |
| 338 | const ndist = (try self.readBits(5)) + 1; | |
| 243 | 339 | // Number of code length codes |
| 244 | const ncode = (try self.bit_reader.readBitsNoEof(usize, 4)) + 4; | |
| 340 | const ncode = (try self.readBits(4)) + 4; | |
| 245 | 341 | |
| 246 | 342 | if (nlen > MAXLCODES or ndist > MAXDCODES) |
| 247 | 343 | return error.BadCounts; |
| ... | ... | @@ -259,7 +355,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 259 | 355 | |
| 260 | 356 | // Read the code lengths, missing ones are left as zero |
| 261 | 357 | for (ORDER[0..ncode]) |val| { |
| 262 | lengths[val] = try self.bit_reader.readBitsNoEof(u16, 3); | |
| 358 | lengths[val] = @intCast(u16, try self.readBits(3)); | |
| 263 | 359 | } |
| 264 | 360 | |
| 265 | 361 | try lencode.construct(lengths[0..]); |
| ... | ... | @@ -284,7 +380,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 284 | 380 | if (i == 0) return error.NoLastLength; |
| 285 | 381 | |
| 286 | 382 | const last_length = lengths[i - 1]; |
| 287 | const repeat = 3 + (try self.bit_reader.readBitsNoEof(usize, 2)); | |
| 383 | const repeat = 3 + (try self.readBits(2)); | |
| 288 | 384 | const last_index = i + repeat; |
| 289 | 385 | while (i < last_index) : (i += 1) { |
| 290 | 386 | lengths[i] = last_length; |
| ... | ... | @@ -292,11 +388,11 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 292 | 388 | }, |
| 293 | 389 | 17 => { |
| 294 | 390 | // repeat zero 3..10 times |
| 295 | i += 3 + (try self.bit_reader.readBitsNoEof(usize, 3)); | |
| 391 | i += 3 + (try self.readBits(3)); | |
| 296 | 392 | }, |
| 297 | 393 | 18 => { |
| 298 | 394 | // repeat zero 11..138 times |
| 299 | i += 11 + (try self.bit_reader.readBitsNoEof(usize, 7)); | |
| 395 | i += 11 + (try self.readBits(7)); | |
| 300 | 396 | }, |
| 301 | 397 | else => return error.InvalidSymbol, |
| 302 | 398 | } |
| ... | ... | @@ -359,11 +455,11 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 359 | 455 | // Length/distance pair |
| 360 | 456 | const length_symbol = symbol - 257; |
| 361 | 457 | const length = LENS[length_symbol] + |
| 362 | try self.bit_reader.readBitsNoEof(u16, LEXT[length_symbol]); | |
| 458 | @intCast(u16, try self.readBits(LEXT[length_symbol])); | |
| 363 | 459 | |
| 364 | 460 | const distance_symbol = try self.decode(distcode); |
| 365 | 461 | const distance = DISTS[distance_symbol] + |
| 366 | try self.bit_reader.readBitsNoEof(u16, DEXT[distance_symbol]); | |
| 462 | @intCast(u16, try self.readBits(DEXT[distance_symbol])); | |
| 367 | 463 | |
| 368 | 464 | if (distance > self.window.buf.len) |
| 369 | 465 | return error.InvalidDistance; |
| ... | ... | @@ -385,13 +481,29 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 385 | 481 | } |
| 386 | 482 | |
| 387 | 483 | fn decode(self: *Self, h: *Huffman) !u16 { |
| 388 | var len: usize = 1; | |
| 389 | var code: usize = 0; | |
| 390 | var first: usize = 0; | |
| 391 | var index: usize = 0; | |
| 484 | // Fast path, read some bits and hope they're prefixes of some code | |
| 485 | const prefix = try self.peekBits(PREFIX_LUT_BITS); | |
| 486 | if (h.prefix_lut_len[prefix] != 0) { | |
| 487 | self.discardBits(h.prefix_lut_len[prefix]); | |
| 488 | return h.prefix_lut[prefix]; | |
| 489 | } | |
| 490 | ||
| 491 | // The sequence we've read is not a prefix of any code of length <= | |
| 492 | // PREFIX_LUT_BITS, keep decoding it using a slower method | |
| 493 | self.discardBits(PREFIX_LUT_BITS); | |
| 494 | ||
| 495 | // Speed up the decoding by starting from the first code length | |
| 496 | // that's not covered by the table | |
| 497 | var len: usize = PREFIX_LUT_BITS + 1; | |
| 498 | var first: usize = h.last_code; | |
| 499 | var index: usize = h.last_index; | |
| 500 | ||
| 501 | // Reverse the prefix so that the LSB becomes the MSB and make space | |
| 502 | // for the next bit | |
| 503 | var code = bitReverse(prefix, PREFIX_LUT_BITS + 1); | |
| 392 | 504 | |
| 393 | 505 | while (len <= MAXBITS) : (len += 1) { |
| 394 | code |= try self.bit_reader.readBitsNoEof(usize, 1); | |
| 506 | code |= try self.readBits(1); | |
| 395 | 507 | const count = h.count[len]; |
| 396 | 508 | if (code < first + count) |
| 397 | 509 | return h.symbol[index + (code - first)]; |
| ... | ... | @@ -411,8 +523,8 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 411 | 523 | // The compressed stream is done |
| 412 | 524 | if (self.seen_eos) return; |
| 413 | 525 | |
| 414 | const last = try self.bit_reader.readBitsNoEof(u1, 1); | |
| 415 | const kind = try self.bit_reader.readBitsNoEof(u2, 2); | |
| 526 | const last = @intCast(u1, try self.readBits(1)); | |
| 527 | const kind = @intCast(u2, try self.readBits(2)); | |
| 416 | 528 | |
| 417 | 529 | self.seen_eos = last != 0; |
| 418 | 530 | |
| ... | ... | @@ -439,7 +551,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 439 | 551 | var i: usize = 0; |
| 440 | 552 | while (i < N) : (i += 1) { |
| 441 | 553 | var tmp: [1]u8 = undefined; |
| 442 | if ((try self.bit_reader.read(&tmp)) != 1) { | |
| 554 | if ((try self.inner_reader.read(&tmp)) != 1) { | |
| 443 | 555 | // Unexpected end of stream, keep this error |
| 444 | 556 | // consistent with the use of readBitsNoEof |
| 445 | 557 | return error.EndOfStream; |
| ... | ... | @@ -478,12 +590,14 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 478 | 590 | assert(math.isPowerOfTwo(window_slice.len)); |
| 479 | 591 | |
| 480 | 592 | return Self{ |
| 481 | .bit_reader = io.bitReader(.Little, source), | |
| 593 | .inner_reader = source, | |
| 482 | 594 | .window = .{ .buf = window_slice }, |
| 483 | 595 | .seen_eos = false, |
| 484 | 596 | .state = .DecodeBlockHeader, |
| 485 | 597 | .hdist = undefined, |
| 486 | 598 | .hlen = undefined, |
| 599 | .bits = 0, | |
| 600 | .bits_left = 0, | |
| 487 | 601 | }; |
| 488 | 602 | } |
| 489 | 603 |
lib/std/compress/gzip.zig created+248| ... | ... | @@ -0,0 +1,248 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2020 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | // | |
| 7 | // Decompressor for GZIP data streams (RFC1952) | |
| 8 | ||
| 9 | const std = @import("std"); | |
| 10 | const io = std.io; | |
| 11 | const fs = std.fs; | |
| 12 | const testing = std.testing; | |
| 13 | const mem = std.mem; | |
| 14 | const deflate = std.compress.deflate; | |
| 15 | ||
| 16 | // Flags for the FLG field in the header | |
| 17 | const FTEXT = 1 << 0; | |
| 18 | const FHCRC = 1 << 1; | |
| 19 | const FEXTRA = 1 << 2; | |
| 20 | const FNAME = 1 << 3; | |
| 21 | const FCOMMENT = 1 << 4; | |
| 22 | ||
| 23 | pub fn GzipStream(comptime ReaderType: type) type { | |
| 24 | return struct { | |
| 25 | const Self = @This(); | |
| 26 | ||
| 27 | pub const Error = ReaderType.Error || | |
| 28 | deflate.InflateStream(ReaderType).Error || | |
| 29 | error{ CorruptedData, WrongChecksum }; | |
| 30 | pub const Reader = io.Reader(*Self, Error, read); | |
| 31 | ||
| 32 | allocator: *mem.Allocator, | |
| 33 | inflater: deflate.InflateStream(ReaderType), | |
| 34 | in_reader: ReaderType, | |
| 35 | hasher: std.hash.Crc32, | |
| 36 | window_slice: []u8, | |
| 37 | read_amt: usize, | |
| 38 | ||
| 39 | info: struct { | |
| 40 | filename: ?[]const u8, | |
| 41 | comment: ?[]const u8, | |
| 42 | modification_time: u32, | |
| 43 | }, | |
| 44 | ||
| 45 | fn init(allocator: *mem.Allocator, source: ReaderType) !Self { | |
| 46 | // gzip header format is specified in RFC1952 | |
| 47 | const header = try source.readBytesNoEof(10); | |
| 48 | ||
| 49 | // Check the ID1/ID2 fields | |
| 50 | if (header[0] != 0x1f or header[1] != 0x8b) | |
| 51 | return error.BadHeader; | |
| 52 | ||
| 53 | const CM = header[2]; | |
| 54 | // The CM field must be 8 to indicate the use of DEFLATE | |
| 55 | if (CM != 8) return error.InvalidCompression; | |
| 56 | // Flags | |
| 57 | const FLG = header[3]; | |
| 58 | // Modification time, as a Unix timestamp. | |
| 59 | // If zero there's no timestamp available. | |
| 60 | const MTIME = mem.readIntLittle(u32, header[4..8]); | |
| 61 | // Extra flags | |
| 62 | const XFL = header[8]; | |
| 63 | // Operating system where the compression took place | |
| 64 | const OS = header[9]; | |
| 65 | ||
| 66 | if (FLG & FEXTRA != 0) { | |
| 67 | // Skip the extra data, we could read and expose it to the user | |
| 68 | // if somebody needs it. | |
| 69 | const len = try source.readIntLittle(u16); | |
| 70 | try source.skipBytes(len, .{}); | |
| 71 | } | |
| 72 | ||
| 73 | var filename: ?[]const u8 = null; | |
| 74 | if (FLG & FNAME != 0) { | |
| 75 | filename = try source.readUntilDelimiterAlloc( | |
| 76 | allocator, | |
| 77 | 0, | |
| 78 | std.math.maxInt(usize), | |
| 79 | ); | |
| 80 | } | |
| 81 | errdefer if (filename) |p| allocator.free(p); | |
| 82 | ||
| 83 | var comment: ?[]const u8 = null; | |
| 84 | if (FLG & FCOMMENT != 0) { | |
| 85 | comment = try source.readUntilDelimiterAlloc( | |
| 86 | allocator, | |
| 87 | 0, | |
| 88 | std.math.maxInt(usize), | |
| 89 | ); | |
| 90 | } | |
| 91 | errdefer if (comment) |p| allocator.free(p); | |
| 92 | ||
| 93 | if (FLG & FHCRC != 0) { | |
| 94 | // TODO: Evaluate and check the header checksum. The stdlib has | |
| 95 | // no CRC16 yet :( | |
| 96 | _ = try source.readIntLittle(u16); | |
| 97 | } | |
| 98 | ||
| 99 | // The RFC doesn't say anything about the DEFLATE window size to be | |
| 100 | // used, default to 32K. | |
| 101 | var window_slice = try allocator.alloc(u8, 32 * 1024); | |
| 102 | ||
| 103 | return Self{ | |
| 104 | .allocator = allocator, | |
| 105 | .inflater = deflate.inflateStream(source, window_slice), | |
| 106 | .in_reader = source, | |
| 107 | .hasher = std.hash.Crc32.init(), | |
| 108 | .window_slice = window_slice, | |
| 109 | .info = .{ | |
| 110 | .filename = filename, | |
| 111 | .comment = comment, | |
| 112 | .modification_time = MTIME, | |
| 113 | }, | |
| 114 | .read_amt = 0, | |
| 115 | }; | |
| 116 | } | |
| 117 | ||
| 118 | pub fn deinit(self: *Self) void { | |
| 119 | self.allocator.free(self.window_slice); | |
| 120 | if (self.info.filename) |filename| | |
| 121 | self.allocator.free(filename); | |
| 122 | if (self.info.comment) |comment| | |
| 123 | self.allocator.free(comment); | |
| 124 | } | |
| 125 | ||
| 126 | // Implements the io.Reader interface | |
| 127 | pub fn read(self: *Self, buffer: []u8) Error!usize { | |
| 128 | if (buffer.len == 0) | |
| 129 | return 0; | |
| 130 | ||
| 131 | // Read from the compressed stream and update the computed checksum | |
| 132 | const r = try self.inflater.read(buffer); | |
| 133 | if (r != 0) { | |
| 134 | self.hasher.update(buffer[0..r]); | |
| 135 | self.read_amt += r; | |
| 136 | return r; | |
| 137 | } | |
| 138 | ||
| 139 | // We've reached the end of stream, check if the checksum matches | |
| 140 | const hash = try self.in_reader.readIntLittle(u32); | |
| 141 | if (hash != self.hasher.final()) | |
| 142 | return error.WrongChecksum; | |
| 143 | ||
| 144 | // The ISIZE field is the size of the uncompressed input modulo 2^32 | |
| 145 | const input_size = try self.in_reader.readIntLittle(u32); | |
| 146 | if (self.read_amt & 0xffffffff != input_size) | |
| 147 | return error.CorruptedData; | |
| 148 | ||
| 149 | return 0; | |
| 150 | } | |
| 151 | ||
| 152 | pub fn reader(self: *Self) Reader { | |
| 153 | return .{ .context = self }; | |
| 154 | } | |
| 155 | }; | |
| 156 | } | |
| 157 | ||
| 158 | pub fn gzipStream(allocator: *mem.Allocator, reader: anytype) !GzipStream(@TypeOf(reader)) { | |
| 159 | return GzipStream(@TypeOf(reader)).init(allocator, reader); | |
| 160 | } | |
| 161 | ||
| 162 | fn testReader(data: []const u8, comptime expected: []const u8) !void { | |
| 163 | var in_stream = io.fixedBufferStream(data); | |
| 164 | ||
| 165 | var gzip_stream = try gzipStream(testing.allocator, in_stream.reader()); | |
| 166 | defer gzip_stream.deinit(); | |
| 167 | ||
| 168 | // Read and decompress the whole file | |
| 169 | const buf = try gzip_stream.reader().readAllAlloc(testing.allocator, std.math.maxInt(usize)); | |
| 170 | defer testing.allocator.free(buf); | |
| 171 | // Calculate its SHA256 hash and check it against the reference | |
| 172 | var hash: [32]u8 = undefined; | |
| 173 | std.crypto.hash.sha2.Sha256.hash(buf, hash[0..], .{}); | |
| 174 | ||
| 175 | assertEqual(expected, &hash); | |
| 176 | } | |
| 177 | ||
| 178 | // Assert `expected` == `input` where `input` is a bytestring. | |
| 179 | pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { | |
| 180 | var expected_bytes: [expected.len / 2]u8 = undefined; | |
| 181 | for (expected_bytes) |*r, i| { | |
| 182 | r.* = std.fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; | |
| 183 | } | |
| 184 | ||
| 185 | testing.expectEqualSlices(u8, &expected_bytes, input); | |
| 186 | } | |
| 187 | ||
| 188 | // All the test cases are obtained by compressing the RFC1952 text | |
| 189 | // | |
| 190 | // https://tools.ietf.org/rfc/rfc1952.txt length=25037 bytes | |
| 191 | // SHA256=164ef0897b4cbec63abf1b57f069f3599bd0fb7c72c2a4dee21bd7e03ec9af67 | |
| 192 | test "compressed data" { | |
| 193 | try testReader( | |
| 194 | @embedFile("rfc1952.txt.gz"), | |
| 195 | "164ef0897b4cbec63abf1b57f069f3599bd0fb7c72c2a4dee21bd7e03ec9af67", | |
| 196 | ); | |
| 197 | } | |
| 198 | ||
| 199 | test "sanity checks" { | |
| 200 | // Truncated header | |
| 201 | testing.expectError( | |
| 202 | error.EndOfStream, | |
| 203 | testReader(&[_]u8{ 0x1f, 0x8B }, ""), | |
| 204 | ); | |
| 205 | // Wrong CM | |
| 206 | testing.expectError( | |
| 207 | error.InvalidCompression, | |
| 208 | testReader(&[_]u8{ | |
| 209 | 0x1f, 0x8b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 210 | 0x00, 0x03, | |
| 211 | }, ""), | |
| 212 | ); | |
| 213 | // Wrong checksum | |
| 214 | testing.expectError( | |
| 215 | error.WrongChecksum, | |
| 216 | testReader(&[_]u8{ | |
| 217 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 218 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, | |
| 219 | 0x00, 0x00, 0x00, 0x00, | |
| 220 | }, ""), | |
| 221 | ); | |
| 222 | // Truncated checksum | |
| 223 | testing.expectError( | |
| 224 | error.EndOfStream, | |
| 225 | testReader(&[_]u8{ | |
| 226 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 227 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, | |
| 228 | }, ""), | |
| 229 | ); | |
| 230 | // Wrong initial size | |
| 231 | testing.expectError( | |
| 232 | error.CorruptedData, | |
| 233 | testReader(&[_]u8{ | |
| 234 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 235 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 236 | 0x00, 0x00, 0x00, 0x01, | |
| 237 | }, ""), | |
| 238 | ); | |
| 239 | // Truncated initial size field | |
| 240 | testing.expectError( | |
| 241 | error.EndOfStream, | |
| 242 | testReader(&[_]u8{ | |
| 243 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 244 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 245 | 0x00, 0x00, 0x00, | |
| 246 | }, ""), | |
| 247 | ); | |
| 248 | } |
lib/std/compress/rfc1952.txt.gz created| Binary files /dev/null and b/lib/std/compress/rfc1952.txt.gz differ |
lib/std/event/loop.zig+2-1| ... | ... | @@ -112,7 +112,8 @@ pub const Loop = struct { |
| 112 | 112 | /// have the correct pointer value. |
| 113 | 113 | /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765 |
| 114 | 114 | pub fn init(self: *Loop) !void { |
| 115 | if (builtin.single_threaded) { | |
| 115 | if (builtin.single_threaded | |
| 116 | or (@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded)) { | |
| 116 | 117 | return self.initSingleThreaded(); |
| 117 | 118 | } else { |
| 118 | 119 | return self.initMultiThreaded(); |
lib/std/fs/file.zig+5-3| ... | ... | @@ -728,7 +728,7 @@ pub const File = struct { |
| 728 | 728 | } |
| 729 | 729 | var i: usize = 0; |
| 730 | 730 | while (i < trailers.len) { |
| 731 | while (amt >= headers[i].iov_len) { | |
| 731 | while (amt >= trailers[i].iov_len) { | |
| 732 | 732 | amt -= trailers[i].iov_len; |
| 733 | 733 | i += 1; |
| 734 | 734 | if (i >= trailers.len) return; |
| ... | ... | @@ -740,14 +740,16 @@ pub const File = struct { |
| 740 | 740 | } |
| 741 | 741 | |
| 742 | 742 | pub const Reader = io.Reader(File, ReadError, read); |
| 743 | ||
| 743 | 744 | /// Deprecated: use `Reader` |
| 744 | 745 | pub const InStream = Reader; |
| 745 | 746 | |
| 746 | pub fn reader(file: File) io.Reader(File, ReadError, read) { | |
| 747 | pub fn reader(file: File) Reader { | |
| 747 | 748 | return .{ .context = file }; |
| 748 | 749 | } |
| 750 | ||
| 749 | 751 | /// Deprecated: use `reader` |
| 750 | pub fn inStream(file: File) io.InStream(File, ReadError, read) { | |
| 752 | pub fn inStream(file: File) Reader { | |
| 751 | 753 | return .{ .context = file }; |
| 752 | 754 | } |
| 753 | 755 |
lib/std/os.zig+41-2| ... | ... | @@ -2515,9 +2515,9 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read |
| 2515 | 2515 | pub const SetEidError = error{ |
| 2516 | 2516 | InvalidUserId, |
| 2517 | 2517 | PermissionDenied, |
| 2518 | }; | |
| 2518 | } || UnexpectedError; | |
| 2519 | 2519 | |
| 2520 | pub const SetIdError = error{ResourceLimitReached} || SetEidError || UnexpectedError; | |
| 2520 | pub const SetIdError = error{ResourceLimitReached} || SetEidError; | |
| 2521 | 2521 | |
| 2522 | 2522 | pub fn setuid(uid: uid_t) SetIdError!void { |
| 2523 | 2523 | switch (errno(system.setuid(uid))) { |
| ... | ... | @@ -5418,3 +5418,42 @@ pub fn fdatasync(fd: fd_t) SyncError!void { |
| 5418 | 5418 | else => |err| return std.os.unexpectedErrno(err), |
| 5419 | 5419 | } |
| 5420 | 5420 | } |
| 5421 | ||
| 5422 | pub const PrctlError = error{ | |
| 5423 | /// Can only occur with PR_SET_SECCOMP/SECCOMP_MODE_FILTER or | |
| 5424 | /// PR_SET_MM/PR_SET_MM_EXE_FILE | |
| 5425 | AccessDenied, | |
| 5426 | /// Can only occur with PR_SET_MM/PR_SET_MM_EXE_FILE | |
| 5427 | InvalidFileDescriptor, | |
| 5428 | InvalidAddress, | |
| 5429 | /// Can only occur with PR_SET_SPECULATION_CTRL, PR_MPX_ENABLE_MANAGEMENT, | |
| 5430 | /// or PR_MPX_DISABLE_MANAGEMENT | |
| 5431 | UnsupportedFeature, | |
| 5432 | /// Can only occur wih PR_SET_FP_MODE | |
| 5433 | OperationNotSupported, | |
| 5434 | PermissionDenied, | |
| 5435 | } || UnexpectedError; | |
| 5436 | ||
| 5437 | pub fn prctl(option: i32, args: anytype) PrctlError!u31 { | |
| 5438 | if (@typeInfo(@TypeOf(args)) != .Struct) | |
| 5439 | @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args))); | |
| 5440 | if (args.len > 4) | |
| 5441 | @compileError("prctl takes a maximum of 4 optional arguments"); | |
| 5442 | ||
| 5443 | var buf: [4]usize = undefined; | |
| 5444 | inline for (args) |arg, i| buf[i] = arg; | |
| 5445 | ||
| 5446 | const rc = system.prctl(option, buf[0], buf[1], buf[2], buf[3]); | |
| 5447 | switch (errno(rc)) { | |
| 5448 | 0 => return @intCast(u31, rc), | |
| 5449 | EACCES => return error.AccessDenied, | |
| 5450 | EBADF => return error.InvalidFileDescriptor, | |
| 5451 | EFAULT => return error.InvalidAddress, | |
| 5452 | EINVAL => unreachable, | |
| 5453 | ENODEV, ENXIO => return error.UnsupportedFeature, | |
| 5454 | EOPNOTSUPP => return error.OperationNotSupported, | |
| 5455 | EPERM, EBUSY => return error.PermissionDenied, | |
| 5456 | ERANGE => unreachable, | |
| 5457 | else => |err| return std.os.unexpectedErrno(err), | |
| 5458 | } | |
| 5459 | } |
lib/std/os/bits/linux.zig+3| ... | ... | @@ -20,10 +20,13 @@ pub usingnamespace switch (builtin.arch) { |
| 20 | 20 | .arm => @import("linux/arm-eabi.zig"), |
| 21 | 21 | .riscv64 => @import("linux/riscv64.zig"), |
| 22 | 22 | .mips, .mipsel => @import("linux/mips.zig"), |
| 23 | .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), | |
| 23 | 24 | else => struct {}, |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | pub usingnamespace @import("linux/netlink.zig"); |
| 28 | pub usingnamespace @import("linux/prctl.zig"); | |
| 29 | pub usingnamespace @import("linux/securebits.zig"); | |
| 27 | 30 | |
| 28 | 31 | const is_mips = builtin.arch.isMIPS(); |
| 29 | 32 |
lib/std/os/bits/linux/powerpc64.zig created+602| ... | ... | @@ -0,0 +1,602 @@ |
| 1 | const std = @import("../../../std.zig"); | |
| 2 | const linux = std.os.linux; | |
| 3 | const socklen_t = linux.socklen_t; | |
| 4 | const iovec = linux.iovec; | |
| 5 | const iovec_const = linux.iovec_const; | |
| 6 | const uid_t = linux.uid_t; | |
| 7 | const gid_t = linux.gid_t; | |
| 8 | const pid_t = linux.pid_t; | |
| 9 | const stack_t = linux.stack_t; | |
| 10 | const sigset_t = linux.sigset_t; | |
| 11 | pub const SYS = extern enum(usize) { | |
| 12 | restart_syscall = 0, | |
| 13 | exit = 1, | |
| 14 | fork = 2, | |
| 15 | read = 3, | |
| 16 | write = 4, | |
| 17 | open = 5, | |
| 18 | close = 6, | |
| 19 | waitpid = 7, | |
| 20 | creat = 8, | |
| 21 | link = 9, | |
| 22 | unlink = 10, | |
| 23 | execve = 11, | |
| 24 | chdir = 12, | |
| 25 | time = 13, | |
| 26 | mknod = 14, | |
| 27 | chmod = 15, | |
| 28 | lchown = 16, | |
| 29 | @"break" = 17, | |
| 30 | oldstat = 18, | |
| 31 | lseek = 19, | |
| 32 | getpid = 20, | |
| 33 | mount = 21, | |
| 34 | umount = 22, | |
| 35 | setuid = 23, | |
| 36 | getuid = 24, | |
| 37 | stime = 25, | |
| 38 | ptrace = 26, | |
| 39 | alarm = 27, | |
| 40 | oldfstat = 28, | |
| 41 | pause = 29, | |
| 42 | utime = 30, | |
| 43 | stty = 31, | |
| 44 | gtty = 32, | |
| 45 | access = 33, | |
| 46 | nice = 34, | |
| 47 | ftime = 35, | |
| 48 | sync = 36, | |
| 49 | kill = 37, | |
| 50 | rename = 38, | |
| 51 | mkdir = 39, | |
| 52 | rmdir = 40, | |
| 53 | dup = 41, | |
| 54 | pipe = 42, | |
| 55 | times = 43, | |
| 56 | prof = 44, | |
| 57 | brk = 45, | |
| 58 | setgid = 46, | |
| 59 | getgid = 47, | |
| 60 | signal = 48, | |
| 61 | geteuid = 49, | |
| 62 | getegid = 50, | |
| 63 | acct = 51, | |
| 64 | umount2 = 52, | |
| 65 | lock = 53, | |
| 66 | ioctl = 54, | |
| 67 | fcntl = 55, | |
| 68 | mpx = 56, | |
| 69 | setpgid = 57, | |
| 70 | ulimit = 58, | |
| 71 | oldolduname = 59, | |
| 72 | umask = 60, | |
| 73 | chroot = 61, | |
| 74 | ustat = 62, | |
| 75 | dup2 = 63, | |
| 76 | getppid = 64, | |
| 77 | getpgrp = 65, | |
| 78 | setsid = 66, | |
| 79 | sigaction = 67, | |
| 80 | sgetmask = 68, | |
| 81 | ssetmask = 69, | |
| 82 | setreuid = 70, | |
| 83 | setregid = 71, | |
| 84 | sigsuspend = 72, | |
| 85 | sigpending = 73, | |
| 86 | sethostname = 74, | |
| 87 | setrlimit = 75, | |
| 88 | getrlimit = 76, | |
| 89 | getrusage = 77, | |
| 90 | gettimeofday = 78, | |
| 91 | settimeofday = 79, | |
| 92 | getgroups = 80, | |
| 93 | setgroups = 81, | |
| 94 | select = 82, | |
| 95 | symlink = 83, | |
| 96 | oldlstat = 84, | |
| 97 | readlink = 85, | |
| 98 | uselib = 86, | |
| 99 | swapon = 87, | |
| 100 | reboot = 88, | |
| 101 | readdir = 89, | |
| 102 | mmap = 90, | |
| 103 | munmap = 91, | |
| 104 | truncate = 92, | |
| 105 | ftruncate = 93, | |
| 106 | fchmod = 94, | |
| 107 | fchown = 95, | |
| 108 | getpriority = 96, | |
| 109 | setpriority = 97, | |
| 110 | profil = 98, | |
| 111 | statfs = 99, | |
| 112 | fstatfs = 100, | |
| 113 | ioperm = 101, | |
| 114 | socketcall = 102, | |
| 115 | syslog = 103, | |
| 116 | setitimer = 104, | |
| 117 | getitimer = 105, | |
| 118 | stat = 106, | |
| 119 | lstat = 107, | |
| 120 | fstat = 108, | |
| 121 | olduname = 109, | |
| 122 | iopl = 110, | |
| 123 | vhangup = 111, | |
| 124 | idle = 112, | |
| 125 | vm86 = 113, | |
| 126 | wait4 = 114, | |
| 127 | swapoff = 115, | |
| 128 | sysinfo = 116, | |
| 129 | ipc = 117, | |
| 130 | fsync = 118, | |
| 131 | sigreturn = 119, | |
| 132 | clone = 120, | |
| 133 | setdomainname = 121, | |
| 134 | uname = 122, | |
| 135 | modify_ldt = 123, | |
| 136 | adjtimex = 124, | |
| 137 | mprotect = 125, | |
| 138 | sigprocmask = 126, | |
| 139 | create_module = 127, | |
| 140 | init_module = 128, | |
| 141 | delete_module = 129, | |
| 142 | get_kernel_syms = 130, | |
| 143 | quotactl = 131, | |
| 144 | getpgid = 132, | |
| 145 | fchdir = 133, | |
| 146 | bdflush = 134, | |
| 147 | sysfs = 135, | |
| 148 | personality = 136, | |
| 149 | afs_syscall = 137, | |
| 150 | setfsuid = 138, | |
| 151 | setfsgid = 139, | |
| 152 | _llseek = 140, | |
| 153 | getdents = 141, | |
| 154 | _newselect = 142, | |
| 155 | flock = 143, | |
| 156 | msync = 144, | |
| 157 | readv = 145, | |
| 158 | writev = 146, | |
| 159 | getsid = 147, | |
| 160 | fdatasync = 148, | |
| 161 | _sysctl = 149, | |
| 162 | mlock = 150, | |
| 163 | munlock = 151, | |
| 164 | mlockall = 152, | |
| 165 | munlockall = 153, | |
| 166 | sched_setparam = 154, | |
| 167 | sched_getparam = 155, | |
| 168 | sched_setscheduler = 156, | |
| 169 | sched_getscheduler = 157, | |
| 170 | sched_yield = 158, | |
| 171 | sched_get_priority_max = 159, | |
| 172 | sched_get_priority_min = 160, | |
| 173 | sched_rr_get_interval = 161, | |
| 174 | nanosleep = 162, | |
| 175 | mremap = 163, | |
| 176 | setresuid = 164, | |
| 177 | getresuid = 165, | |
| 178 | query_module = 166, | |
| 179 | poll = 167, | |
| 180 | nfsservctl = 168, | |
| 181 | setresgid = 169, | |
| 182 | getresgid = 170, | |
| 183 | prctl = 171, | |
| 184 | rt_sigreturn = 172, | |
| 185 | rt_sigaction = 173, | |
| 186 | rt_sigprocmask = 174, | |
| 187 | rt_sigpending = 175, | |
| 188 | rt_sigtimedwait = 176, | |
| 189 | rt_sigqueueinfo = 177, | |
| 190 | rt_sigsuspend = 178, | |
| 191 | pread64 = 179, | |
| 192 | pwrite64 = 180, | |
| 193 | chown = 181, | |
| 194 | getcwd = 182, | |
| 195 | capget = 183, | |
| 196 | capset = 184, | |
| 197 | sigaltstack = 185, | |
| 198 | sendfile = 186, | |
| 199 | getpmsg = 187, | |
| 200 | putpmsg = 188, | |
| 201 | vfork = 189, | |
| 202 | ugetrlimit = 190, | |
| 203 | readahead = 191, | |
| 204 | pciconfig_read = 198, | |
| 205 | pciconfig_write = 199, | |
| 206 | pciconfig_iobase = 200, | |
| 207 | multiplexer = 201, | |
| 208 | getdents64 = 202, | |
| 209 | pivot_root = 203, | |
| 210 | madvise = 205, | |
| 211 | mincore = 206, | |
| 212 | gettid = 207, | |
| 213 | tkill = 208, | |
| 214 | setxattr = 209, | |
| 215 | lsetxattr = 210, | |
| 216 | fsetxattr = 211, | |
| 217 | getxattr = 212, | |
| 218 | lgetxattr = 213, | |
| 219 | fgetxattr = 214, | |
| 220 | listxattr = 215, | |
| 221 | llistxattr = 216, | |
| 222 | flistxattr = 217, | |
| 223 | removexattr = 218, | |
| 224 | lremovexattr = 219, | |
| 225 | fremovexattr = 220, | |
| 226 | futex = 221, | |
| 227 | sched_setaffinity = 222, | |
| 228 | sched_getaffinity = 223, | |
| 229 | tuxcall = 225, | |
| 230 | io_setup = 227, | |
| 231 | io_destroy = 228, | |
| 232 | io_getevents = 229, | |
| 233 | io_submit = 230, | |
| 234 | io_cancel = 231, | |
| 235 | set_tid_address = 232, | |
| 236 | fadvise64 = 233, | |
| 237 | exit_group = 234, | |
| 238 | lookup_dcookie = 235, | |
| 239 | epoll_create = 236, | |
| 240 | epoll_ctl = 237, | |
| 241 | epoll_wait = 238, | |
| 242 | remap_file_pages = 239, | |
| 243 | timer_create = 240, | |
| 244 | timer_settime = 241, | |
| 245 | timer_gettime = 242, | |
| 246 | timer_getoverrun = 243, | |
| 247 | timer_delete = 244, | |
| 248 | clock_settime = 245, | |
| 249 | clock_gettime = 246, | |
| 250 | clock_getres = 247, | |
| 251 | clock_nanosleep = 248, | |
| 252 | swapcontext = 249, | |
| 253 | tgkill = 250, | |
| 254 | utimes = 251, | |
| 255 | statfs64 = 252, | |
| 256 | fstatfs64 = 253, | |
| 257 | rtas = 255, | |
| 258 | sys_debug_setcontext = 256, | |
| 259 | migrate_pages = 258, | |
| 260 | mbind = 259, | |
| 261 | get_mempolicy = 260, | |
| 262 | set_mempolicy = 261, | |
| 263 | mq_open = 262, | |
| 264 | mq_unlink = 263, | |
| 265 | mq_timedsend = 264, | |
| 266 | mq_timedreceive = 265, | |
| 267 | mq_notify = 266, | |
| 268 | mq_getsetattr = 267, | |
| 269 | kexec_load = 268, | |
| 270 | add_key = 269, | |
| 271 | request_key = 270, | |
| 272 | keyctl = 271, | |
| 273 | waitid = 272, | |
| 274 | ioprio_set = 273, | |
| 275 | ioprio_get = 274, | |
| 276 | inotify_init = 275, | |
| 277 | inotify_add_watch = 276, | |
| 278 | inotify_rm_watch = 277, | |
| 279 | spu_run = 278, | |
| 280 | spu_create = 279, | |
| 281 | pselect6 = 280, | |
| 282 | ppoll = 281, | |
| 283 | unshare = 282, | |
| 284 | splice = 283, | |
| 285 | tee = 284, | |
| 286 | vmsplice = 285, | |
| 287 | openat = 286, | |
| 288 | mkdirat = 287, | |
| 289 | mknodat = 288, | |
| 290 | fchownat = 289, | |
| 291 | futimesat = 290, | |
| 292 | newfstatat = 291, | |
| 293 | unlinkat = 292, | |
| 294 | renameat = 293, | |
| 295 | linkat = 294, | |
| 296 | symlinkat = 295, | |
| 297 | readlinkat = 296, | |
| 298 | fchmodat = 297, | |
| 299 | faccessat = 298, | |
| 300 | get_robust_list = 299, | |
| 301 | set_robust_list = 300, | |
| 302 | move_pages = 301, | |
| 303 | getcpu = 302, | |
| 304 | epoll_pwait = 303, | |
| 305 | utimensat = 304, | |
| 306 | signalfd = 305, | |
| 307 | timerfd_create = 306, | |
| 308 | eventfd = 307, | |
| 309 | sync_file_range2 = 308, | |
| 310 | fallocate = 309, | |
| 311 | subpage_prot = 310, | |
| 312 | timerfd_settime = 311, | |
| 313 | timerfd_gettime = 312, | |
| 314 | signalfd4 = 313, | |
| 315 | eventfd2 = 314, | |
| 316 | epoll_create1 = 315, | |
| 317 | dup3 = 316, | |
| 318 | pipe2 = 317, | |
| 319 | inotify_init1 = 318, | |
| 320 | perf_event_open = 319, | |
| 321 | preadv = 320, | |
| 322 | pwritev = 321, | |
| 323 | rt_tgsigqueueinfo = 322, | |
| 324 | fanotify_init = 323, | |
| 325 | fanotify_mark = 324, | |
| 326 | prlimit64 = 325, | |
| 327 | socket = 326, | |
| 328 | bind = 327, | |
| 329 | connect = 328, | |
| 330 | listen = 329, | |
| 331 | accept = 330, | |
| 332 | getsockname = 331, | |
| 333 | getpeername = 332, | |
| 334 | socketpair = 333, | |
| 335 | send = 334, | |
| 336 | sendto = 335, | |
| 337 | recv = 336, | |
| 338 | recvfrom = 337, | |
| 339 | shutdown = 338, | |
| 340 | setsockopt = 339, | |
| 341 | getsockopt = 340, | |
| 342 | sendmsg = 341, | |
| 343 | recvmsg = 342, | |
| 344 | recvmmsg = 343, | |
| 345 | accept4 = 344, | |
| 346 | name_to_handle_at = 345, | |
| 347 | open_by_handle_at = 346, | |
| 348 | clock_adjtime = 347, | |
| 349 | syncfs = 348, | |
| 350 | sendmmsg = 349, | |
| 351 | setns = 350, | |
| 352 | process_vm_readv = 351, | |
| 353 | process_vm_writev = 352, | |
| 354 | finit_module = 353, | |
| 355 | kcmp = 354, | |
| 356 | sched_setattr = 355, | |
| 357 | sched_getattr = 356, | |
| 358 | renameat2 = 357, | |
| 359 | seccomp = 358, | |
| 360 | getrandom = 359, | |
| 361 | memfd_create = 360, | |
| 362 | bpf = 361, | |
| 363 | execveat = 362, | |
| 364 | switch_endian = 363, | |
| 365 | userfaultfd = 364, | |
| 366 | membarrier = 365, | |
| 367 | mlock2 = 378, | |
| 368 | copy_file_range = 379, | |
| 369 | preadv2 = 380, | |
| 370 | pwritev2 = 381, | |
| 371 | kexec_file_load = 382, | |
| 372 | statx = 383, | |
| 373 | pkey_alloc = 384, | |
| 374 | pkey_free = 385, | |
| 375 | pkey_mprotect = 386, | |
| 376 | rseq = 387, | |
| 377 | io_pgetevents = 388, | |
| 378 | semtimedop = 392, | |
| 379 | semget = 393, | |
| 380 | semctl = 394, | |
| 381 | shmget = 395, | |
| 382 | shmctl = 396, | |
| 383 | shmat = 397, | |
| 384 | shmdt = 398, | |
| 385 | msgget = 399, | |
| 386 | msgsnd = 400, | |
| 387 | msgrcv = 401, | |
| 388 | msgctl = 402, | |
| 389 | pidfd_send_signal = 424, | |
| 390 | io_uring_setup = 425, | |
| 391 | io_uring_enter = 426, | |
| 392 | io_uring_register = 427, | |
| 393 | open_tree = 428, | |
| 394 | move_mount = 429, | |
| 395 | fsopen = 430, | |
| 396 | fsconfig = 431, | |
| 397 | fsmount = 432, | |
| 398 | fspick = 433, | |
| 399 | pidfd_open = 434, | |
| 400 | clone3 = 435, | |
| 401 | openat2 = 437, | |
| 402 | pidfd_getfd = 438, | |
| 403 | ||
| 404 | _, | |
| 405 | }; | |
| 406 | ||
| 407 | pub const O_CREAT = 0o100; | |
| 408 | pub const O_EXCL = 0o200; | |
| 409 | pub const O_NOCTTY = 0o400; | |
| 410 | pub const O_TRUNC = 0o1000; | |
| 411 | pub const O_APPEND = 0o2000; | |
| 412 | pub const O_NONBLOCK = 0o4000; | |
| 413 | pub const O_DSYNC = 0o10000; | |
| 414 | pub const O_SYNC = 0o4010000; | |
| 415 | pub const O_RSYNC = 0o4010000; | |
| 416 | pub const O_DIRECTORY = 0o40000; | |
| 417 | pub const O_NOFOLLOW = 0o100000; | |
| 418 | pub const O_CLOEXEC = 0o2000000; | |
| 419 | ||
| 420 | pub const O_ASYNC = 0o20000; | |
| 421 | pub const O_DIRECT = 0o400000; | |
| 422 | pub const O_LARGEFILE = 0o200000; | |
| 423 | pub const O_NOATIME = 0o1000000; | |
| 424 | pub const O_PATH = 0o10000000; | |
| 425 | pub const O_TMPFILE = 0o20200000; | |
| 426 | pub const O_NDELAY = O_NONBLOCK; | |
| 427 | ||
| 428 | pub const F_DUPFD = 0; | |
| 429 | pub const F_GETFD = 1; | |
| 430 | pub const F_SETFD = 2; | |
| 431 | pub const F_GETFL = 3; | |
| 432 | pub const F_SETFL = 4; | |
| 433 | ||
| 434 | pub const F_SETOWN = 8; | |
| 435 | pub const F_GETOWN = 9; | |
| 436 | pub const F_SETSIG = 10; | |
| 437 | pub const F_GETSIG = 11; | |
| 438 | ||
| 439 | pub const F_GETLK = 5; | |
| 440 | pub const F_SETLK = 6; | |
| 441 | pub const F_SETLKW = 7; | |
| 442 | ||
| 443 | pub const F_RDLCK = 0; | |
| 444 | pub const F_WRLCK = 1; | |
| 445 | pub const F_UNLCK = 2; | |
| 446 | ||
| 447 | pub const LOCK_SH = 1; | |
| 448 | pub const LOCK_EX = 2; | |
| 449 | pub const LOCK_UN = 8; | |
| 450 | pub const LOCK_NB = 4; | |
| 451 | ||
| 452 | pub const F_SETOWN_EX = 15; | |
| 453 | pub const F_GETOWN_EX = 16; | |
| 454 | ||
| 455 | pub const F_GETOWNER_UIDS = 17; | |
| 456 | ||
| 457 | /// stack-like segment | |
| 458 | pub const MAP_GROWSDOWN = 0x0100; | |
| 459 | ||
| 460 | /// ETXTBSY | |
| 461 | pub const MAP_DENYWRITE = 0x0800; | |
| 462 | ||
| 463 | /// mark it as an executable | |
| 464 | pub const MAP_EXECUTABLE = 0x1000; | |
| 465 | ||
| 466 | /// pages are locked | |
| 467 | pub const MAP_LOCKED = 0x0080; | |
| 468 | ||
| 469 | /// don't check for reservations | |
| 470 | pub const MAP_NORESERVE = 0x0040; | |
| 471 | ||
| 472 | pub const VDSO_CGT_SYM = "__kernel_clock_gettime"; | |
| 473 | pub const VDSO_CGT_VER = "LINUX_2.6.15"; | |
| 474 | ||
| 475 | pub const Flock = extern struct { | |
| 476 | l_type: i16, | |
| 477 | l_whence: i16, | |
| 478 | l_start: off_t, | |
| 479 | l_len: off_t, | |
| 480 | l_pid: pid_t, | |
| 481 | __unused: [4]u8, | |
| 482 | }; | |
| 483 | ||
| 484 | pub const msghdr = extern struct { | |
| 485 | msg_name: ?*sockaddr, | |
| 486 | msg_namelen: socklen_t, | |
| 487 | msg_iov: [*]iovec, | |
| 488 | msg_iovlen: usize, | |
| 489 | msg_control: ?*c_void, | |
| 490 | msg_controllen: usize, | |
| 491 | msg_flags: i32, | |
| 492 | }; | |
| 493 | ||
| 494 | pub const msghdr_const = extern struct { | |
| 495 | msg_name: ?*const sockaddr, | |
| 496 | msg_namelen: socklen_t, | |
| 497 | msg_iov: [*]iovec_const, | |
| 498 | msg_iovlen: usize, | |
| 499 | msg_control: ?*c_void, | |
| 500 | msg_controllen: usize, | |
| 501 | msg_flags: i32, | |
| 502 | }; | |
| 503 | ||
| 504 | pub const blksize_t = i64; | |
| 505 | pub const nlink_t = u64; | |
| 506 | pub const time_t = i64; | |
| 507 | pub const mode_t = u32; | |
| 508 | pub const off_t = i64; | |
| 509 | pub const ino_t = u64; | |
| 510 | pub const dev_t = u64; | |
| 511 | pub const blkcnt_t = i64; | |
| 512 | ||
| 513 | /// Renamed to Stat to not conflict with the stat function. | |
| 514 | /// atime, mtime, and ctime have functions to return `timespec`, | |
| 515 | /// because although this is a POSIX API, the layout and names of | |
| 516 | /// the structs are inconsistent across operating systems, and | |
| 517 | /// in C, macros are used to hide the differences. Here we use | |
| 518 | /// methods to accomplish this. | |
| 519 | pub const Stat = extern struct { | |
| 520 | dev: dev_t, | |
| 521 | ino: ino_t, | |
| 522 | nlink: nlink_t, | |
| 523 | mode: mode_t, | |
| 524 | uid: uid_t, | |
| 525 | gid: gid_t, | |
| 526 | rdev: dev_t, | |
| 527 | size: off_t, | |
| 528 | blksize: blksize_t, | |
| 529 | blocks: blkcnt_t, | |
| 530 | atim: timespec, | |
| 531 | mtim: timespec, | |
| 532 | ctim: timespec, | |
| 533 | __unused: [3]u64, | |
| 534 | ||
| 535 | pub fn atime(self: Stat) timespec { | |
| 536 | return self.atim; | |
| 537 | } | |
| 538 | ||
| 539 | pub fn mtime(self: Stat) timespec { | |
| 540 | return self.mtim; | |
| 541 | } | |
| 542 | ||
| 543 | pub fn ctime(self: Stat) timespec { | |
| 544 | return self.ctim; | |
| 545 | } | |
| 546 | }; | |
| 547 | ||
| 548 | pub const timespec = extern struct { | |
| 549 | tv_sec: time_t, | |
| 550 | tv_nsec: isize, | |
| 551 | }; | |
| 552 | ||
| 553 | pub const timeval = extern struct { | |
| 554 | tv_sec: isize, | |
| 555 | tv_usec: isize, | |
| 556 | }; | |
| 557 | ||
| 558 | pub const timezone = extern struct { | |
| 559 | tz_minuteswest: i32, | |
| 560 | tz_dsttime: i32, | |
| 561 | }; | |
| 562 | ||
| 563 | pub const greg_t = u64; | |
| 564 | pub const gregset_t = [48]greg_t; | |
| 565 | pub const fpregset_t = [33]f64; | |
| 566 | ||
| 567 | /// The position of the vscr register depends on endianness. | |
| 568 | /// On C, macros are used to change vscr_word's offset to | |
| 569 | /// account for this. Here we'll just define vscr_word_le | |
| 570 | /// and vscr_word_be. Code must take care to use the correct one. | |
| 571 | pub const vrregset = extern struct { | |
| 572 | vrregs: [32][4]u32 align(16), | |
| 573 | vscr_word_le: u32, | |
| 574 | _pad1: [2]u32, | |
| 575 | vscr_word_be: u32, | |
| 576 | vrsave: u32, | |
| 577 | _pad2: [3]u32, | |
| 578 | }; | |
| 579 | pub const vrregset_t = vrregset; | |
| 580 | ||
| 581 | pub const mcontext_t = extern struct { | |
| 582 | __unused: [4]u64, | |
| 583 | signal: i32, | |
| 584 | _pad0: i32, | |
| 585 | handler: u64, | |
| 586 | oldmask: u64, | |
| 587 | regs: ?*c_void, | |
| 588 | gp_regs: gregset_t, | |
| 589 | fp_regs: fpregset_t, | |
| 590 | v_regs: *vrregset_t, | |
| 591 | vmx_reserve: [34 + 34 + 32 + 1]i64, | |
| 592 | }; | |
| 593 | ||
| 594 | pub const ucontext_t = extern struct { | |
| 595 | flags: u32, | |
| 596 | link: *ucontext_t, | |
| 597 | stack: stack_t, | |
| 598 | sigmask: sigset_t, | |
| 599 | mcontext: mcontext_t, | |
| 600 | }; | |
| 601 | ||
| 602 | pub const Elf_Symndx = u32; |
lib/std/os/bits/linux/prctl.zig created+158| ... | ... | @@ -0,0 +1,158 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2020 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | ||
| 7 | pub const PR_SET_PDEATHSIG = 1; | |
| 8 | pub const PR_GET_PDEATHSIG = 2; | |
| 9 | ||
| 10 | pub const PR_GET_DUMPABLE = 3; | |
| 11 | pub const PR_SET_DUMPABLE = 4; | |
| 12 | ||
| 13 | pub const PR_GET_UNALIGN = 5; | |
| 14 | pub const PR_SET_UNALIGN = 6; | |
| 15 | pub const PR_UNALIGN_NOPRINT = 1; | |
| 16 | pub const PR_UNALIGN_SIGBUS = 2; | |
| 17 | ||
| 18 | pub const PR_GET_KEEPCAPS = 7; | |
| 19 | pub const PR_SET_KEEPCAPS = 8; | |
| 20 | ||
| 21 | pub const PR_GET_FPEMU = 9; | |
| 22 | pub const PR_SET_FPEMU = 10; | |
| 23 | pub const PR_FPEMU_NOPRINT = 1; | |
| 24 | pub const PR_FPEMU_SIGFPE = 2; | |
| 25 | ||
| 26 | pub const PR_GET_FPEXC = 11; | |
| 27 | pub const PR_SET_FPEXC = 12; | |
| 28 | pub const PR_FP_EXC_SW_ENABLE = 0x80; | |
| 29 | pub const PR_FP_EXC_DIV = 0x010000; | |
| 30 | pub const PR_FP_EXC_OVF = 0x020000; | |
| 31 | pub const PR_FP_EXC_UND = 0x040000; | |
| 32 | pub const PR_FP_EXC_RES = 0x080000; | |
| 33 | pub const PR_FP_EXC_INV = 0x100000; | |
| 34 | pub const PR_FP_EXC_DISABLED = 0; | |
| 35 | pub const PR_FP_EXC_NONRECOV = 1; | |
| 36 | pub const PR_FP_EXC_ASYNC = 2; | |
| 37 | pub const PR_FP_EXC_PRECISE = 3; | |
| 38 | ||
| 39 | pub const PR_GET_TIMING = 13; | |
| 40 | pub const PR_SET_TIMING = 14; | |
| 41 | pub const PR_TIMING_STATISTICAL = 0; | |
| 42 | pub const PR_TIMING_TIMESTAMP = 1; | |
| 43 | ||
| 44 | pub const PR_SET_NAME = 15; | |
| 45 | pub const PR_GET_NAME = 16; | |
| 46 | ||
| 47 | pub const PR_GET_ENDIAN = 19; | |
| 48 | pub const PR_SET_ENDIAN = 20; | |
| 49 | pub const PR_ENDIAN_BIG = 0; | |
| 50 | pub const PR_ENDIAN_LITTLE = 1; | |
| 51 | pub const PR_ENDIAN_PPC_LITTLE = 2; | |
| 52 | ||
| 53 | pub const PR_GET_SECCOMP = 21; | |
| 54 | pub const PR_SET_SECCOMP = 22; | |
| 55 | ||
| 56 | pub const PR_CAPBSET_READ = 23; | |
| 57 | pub const PR_CAPBSET_DROP = 24; | |
| 58 | ||
| 59 | pub const PR_GET_TSC = 25; | |
| 60 | pub const PR_SET_TSC = 26; | |
| 61 | pub const PR_TSC_ENABLE = 1; | |
| 62 | pub const PR_TSC_SIGSEGV = 2; | |
| 63 | ||
| 64 | pub const PR_GET_SECUREBITS = 27; | |
| 65 | pub const PR_SET_SECUREBITS = 28; | |
| 66 | ||
| 67 | pub const PR_SET_TIMERSLACK = 29; | |
| 68 | pub const PR_GET_TIMERSLACK = 30; | |
| 69 | ||
| 70 | pub const PR_TASK_PERF_EVENTS_DISABLE = 31; | |
| 71 | pub const PR_TASK_PERF_EVENTS_ENABLE = 32; | |
| 72 | ||
| 73 | pub const PR_MCE_KILL = 33; | |
| 74 | pub const PR_MCE_KILL_CLEAR = 0; | |
| 75 | pub const PR_MCE_KILL_SET = 1; | |
| 76 | ||
| 77 | pub const PR_MCE_KILL_LATE = 0; | |
| 78 | pub const PR_MCE_KILL_EARLY = 1; | |
| 79 | pub const PR_MCE_KILL_DEFAULT = 2; | |
| 80 | ||
| 81 | pub const PR_MCE_KILL_GET = 34; | |
| 82 | ||
| 83 | pub const PR_SET_MM = 35; | |
| 84 | pub const PR_SET_MM_START_CODE = 1; | |
| 85 | pub const PR_SET_MM_END_CODE = 2; | |
| 86 | pub const PR_SET_MM_START_DATA = 3; | |
| 87 | pub const PR_SET_MM_END_DATA = 4; | |
| 88 | pub const PR_SET_MM_START_STACK = 5; | |
| 89 | pub const PR_SET_MM_START_BRK = 6; | |
| 90 | pub const PR_SET_MM_BRK = 7; | |
| 91 | pub const PR_SET_MM_ARG_START = 8; | |
| 92 | pub const PR_SET_MM_ARG_END = 9; | |
| 93 | pub const PR_SET_MM_ENV_START = 10; | |
| 94 | pub const PR_SET_MM_ENV_END = 11; | |
| 95 | pub const PR_SET_MM_AUXV = 12; | |
| 96 | pub const PR_SET_MM_EXE_FILE = 13; | |
| 97 | pub const PR_SET_MM_MAP = 14; | |
| 98 | pub const PR_SET_MM_MAP_SIZE = 15; | |
| 99 | ||
| 100 | pub const prctl_mm_map = extern struct { | |
| 101 | start_code: u64, | |
| 102 | end_code: u64, | |
| 103 | start_data: u64, | |
| 104 | end_data: u64, | |
| 105 | start_brk: u64, | |
| 106 | brk: u64, | |
| 107 | start_stack: u64, | |
| 108 | arg_start: u64, | |
| 109 | arg_end: u64, | |
| 110 | env_start: u64, | |
| 111 | env_end: u64, | |
| 112 | auxv: *u64, | |
| 113 | auxv_size: u32, | |
| 114 | exe_fd: u32, | |
| 115 | }; | |
| 116 | ||
| 117 | pub const PR_SET_PTRACER = 0x59616d61; | |
| 118 | pub const PR_SET_PTRACER_ANY = std.math.maxInt(c_ulong); | |
| 119 | ||
| 120 | pub const PR_SET_CHILD_SUBREAPER = 36; | |
| 121 | pub const PR_GET_CHILD_SUBREAPER = 37; | |
| 122 | ||
| 123 | pub const PR_SET_NO_NEW_PRIVS = 38; | |
| 124 | pub const PR_GET_NO_NEW_PRIVS = 39; | |
| 125 | ||
| 126 | pub const PR_GET_TID_ADDRESS = 40; | |
| 127 | ||
| 128 | pub const PR_SET_THP_DISABLE = 41; | |
| 129 | pub const PR_GET_THP_DISABLE = 42; | |
| 130 | ||
| 131 | pub const PR_MPX_ENABLE_MANAGEMENT = 43; | |
| 132 | pub const PR_MPX_DISABLE_MANAGEMENT = 44; | |
| 133 | ||
| 134 | pub const PR_SET_FP_MODE = 45; | |
| 135 | pub const PR_GET_FP_MODE = 46; | |
| 136 | pub const PR_FP_MODE_FR = 1 << 0; | |
| 137 | pub const PR_FP_MODE_FRE = 1 << 1; | |
| 138 | ||
| 139 | pub const PR_CAP_AMBIENT = 47; | |
| 140 | pub const PR_CAP_AMBIENT_IS_SET = 1; | |
| 141 | pub const PR_CAP_AMBIENT_RAISE = 2; | |
| 142 | pub const PR_CAP_AMBIENT_LOWER = 3; | |
| 143 | pub const PR_CAP_AMBIENT_CLEAR_ALL = 4; | |
| 144 | ||
| 145 | pub const PR_SVE_SET_VL = 50; | |
| 146 | pub const PR_SVE_SET_VL_ONEXEC = 1 << 18; | |
| 147 | pub const PR_SVE_GET_VL = 51; | |
| 148 | pub const PR_SVE_VL_LEN_MASK = 0xffff; | |
| 149 | pub const PR_SVE_VL_INHERIT = 1 << 17; | |
| 150 | ||
| 151 | pub const PR_GET_SPECULATION_CTRL = 52; | |
| 152 | pub const PR_SET_SPECULATION_CTRL = 53; | |
| 153 | pub const PR_SPEC_STORE_BYPASS = 0; | |
| 154 | pub const PR_SPEC_NOT_AFFECTED = 0; | |
| 155 | pub const PR_SPEC_PRCTL = 1 << 0; | |
| 156 | pub const PR_SPEC_ENABLE = 1 << 1; | |
| 157 | pub const PR_SPEC_DISABLE = 1 << 2; | |
| 158 | pub const PR_SPEC_FORCE_DISABLE = 1 << 3; |
lib/std/os/bits/linux/securebits.zig created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2020 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | ||
| 7 | fn issecure_mask(comptime x: comptime_int) comptime_int { | |
| 8 | return 1 << x; | |
| 9 | } | |
| 10 | ||
| 11 | pub const SECUREBITS_DEFAULT = 0x00000000; | |
| 12 | ||
| 13 | pub const SECURE_NOROOT = 0; | |
| 14 | pub const SECURE_NOROOT_LOCKED = 1; | |
| 15 | ||
| 16 | pub const SECBIT_NOROOT = issecure_mask(SECURE_NOROOT); | |
| 17 | pub const SECBIT_NOROOT_LOCKED = issecure_mask(SECURE_NOROOT_LOCKED); | |
| 18 | ||
| 19 | pub const SECURE_NO_SETUID_FIXUP = 2; | |
| 20 | pub const SECURE_NO_SETUID_FIXUP_LOCKED = 3; | |
| 21 | ||
| 22 | pub const SECBIT_NO_SETUID_FIXUP = issecure_mask(SECURE_NO_SETUID_FIXUP); | |
| 23 | pub const SECBIT_NO_SETUID_FIXUP_LOCKED = issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED); | |
| 24 | ||
| 25 | pub const SECURE_KEEP_CAPS = 4; | |
| 26 | pub const SECURE_KEEP_CAPS_LOCKED = 5; | |
| 27 | ||
| 28 | pub const SECBIT_KEEP_CAPS = issecure_mask(SECURE_KEEP_CAPS); | |
| 29 | pub const SECBIT_KEEP_CAPS_LOCKED = issecure_mask(SECURE_KEEP_CAPS_LOCKED); | |
| 30 | ||
| 31 | pub const SECURE_NO_CAP_AMBIENT_RAISE = 6; | |
| 32 | pub const SECURE_NO_CAP_AMBIENT_RAISE_LOCKED = 7; | |
| 33 | ||
| 34 | pub const SECBIT_NO_CAP_AMBIENT_RAISE = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE); | |
| 35 | pub const SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED); | |
| 36 | ||
| 37 | pub const SECURE_ALL_BITS = issecure_mask(SECURE_NOROOT) | | |
| 38 | issecure_mask(SECURE_NO_SETUID_FIXUP) | | |
| 39 | issecure_mask(SECURE_KEEP_CAPS) | | |
| 40 | issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE); | |
| 41 | pub const SECURE_ALL_LOCKS = SECURE_ALL_BITS << 1; |
lib/std/os/linux.zig+5| ... | ... | @@ -25,6 +25,7 @@ pub usingnamespace switch (builtin.arch) { |
| 25 | 25 | .arm => @import("linux/arm-eabi.zig"), |
| 26 | 26 | .riscv64 => @import("linux/riscv64.zig"), |
| 27 | 27 | .mips, .mipsel => @import("linux/mips.zig"), |
| 28 | .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), | |
| 28 | 29 | else => struct {}, |
| 29 | 30 | }; |
| 30 | 31 | pub usingnamespace @import("bits.zig"); |
| ... | ... | @@ -1258,6 +1259,10 @@ pub fn fdatasync(fd: fd_t) usize { |
| 1258 | 1259 | return syscall1(.fdatasync, @bitCast(usize, @as(isize, fd))); |
| 1259 | 1260 | } |
| 1260 | 1261 | |
| 1262 | pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { | |
| 1263 | return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5); | |
| 1264 | } | |
| 1265 | ||
| 1261 | 1266 | test "" { |
| 1262 | 1267 | if (builtin.os.tag == .linux) { |
| 1263 | 1268 | _ = @import("linux/test.zig"); |
lib/std/os/linux/powerpc64.zig created+127| ... | ... | @@ -0,0 +1,127 @@ |
| 1 | usingnamespace @import("../bits.zig"); | |
| 2 | ||
| 3 | pub fn syscall0(number: SYS) usize { | |
| 4 | return asm volatile ( | |
| 5 | \\ sc | |
| 6 | \\ bns+ 1f | |
| 7 | \\ neg 3, 3 | |
| 8 | \\ 1: | |
| 9 | : [ret] "={r3}" (-> usize) | |
| 10 | : [number] "{r0}" (@enumToInt(number)) | |
| 11 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 12 | ); | |
| 13 | } | |
| 14 | ||
| 15 | pub fn syscall1(number: SYS, arg1: usize) usize { | |
| 16 | return asm volatile ( | |
| 17 | \\ sc | |
| 18 | \\ bns+ 1f | |
| 19 | \\ neg 3, 3 | |
| 20 | \\ 1: | |
| 21 | : [ret] "={r3}" (-> usize) | |
| 22 | : [number] "{r0}" (@enumToInt(number)), | |
| 23 | [arg1] "{r3}" (arg1) | |
| 24 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 25 | ); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { | |
| 29 | return asm volatile ( | |
| 30 | \\ sc | |
| 31 | \\ bns+ 1f | |
| 32 | \\ neg 3, 3 | |
| 33 | \\ 1: | |
| 34 | : [ret] "={r3}" (-> usize) | |
| 35 | : [number] "{r0}" (@enumToInt(number)), | |
| 36 | [arg1] "{r3}" (arg1), | |
| 37 | [arg2] "{r4}" (arg2) | |
| 38 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 39 | ); | |
| 40 | } | |
| 41 | ||
| 42 | pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { | |
| 43 | return asm volatile ( | |
| 44 | \\ sc | |
| 45 | \\ bns+ 1f | |
| 46 | \\ neg 3, 3 | |
| 47 | \\ 1: | |
| 48 | : [ret] "={r3}" (-> usize) | |
| 49 | : [number] "{r0}" (@enumToInt(number)), | |
| 50 | [arg1] "{r3}" (arg1), | |
| 51 | [arg2] "{r4}" (arg2), | |
| 52 | [arg3] "{r5}" (arg3) | |
| 53 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 54 | ); | |
| 55 | } | |
| 56 | ||
| 57 | pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { | |
| 58 | return asm volatile ( | |
| 59 | \\ sc | |
| 60 | \\ bns+ 1f | |
| 61 | \\ neg 3, 3 | |
| 62 | \\ 1: | |
| 63 | : [ret] "={r3}" (-> usize) | |
| 64 | : [number] "{r0}" (@enumToInt(number)), | |
| 65 | [arg1] "{r3}" (arg1), | |
| 66 | [arg2] "{r4}" (arg2), | |
| 67 | [arg3] "{r5}" (arg3), | |
| 68 | [arg4] "{r6}" (arg4) | |
| 69 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 70 | ); | |
| 71 | } | |
| 72 | ||
| 73 | pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { | |
| 74 | return asm volatile ( | |
| 75 | \\ sc | |
| 76 | \\ bns+ 1f | |
| 77 | \\ neg 3, 3 | |
| 78 | \\ 1: | |
| 79 | : [ret] "={r3}" (-> usize) | |
| 80 | : [number] "{r0}" (@enumToInt(number)), | |
| 81 | [arg1] "{r3}" (arg1), | |
| 82 | [arg2] "{r4}" (arg2), | |
| 83 | [arg3] "{r5}" (arg3), | |
| 84 | [arg4] "{r6}" (arg4), | |
| 85 | [arg5] "{r7}" (arg5) | |
| 86 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 87 | ); | |
| 88 | } | |
| 89 | ||
| 90 | pub fn syscall6( | |
| 91 | number: SYS, | |
| 92 | arg1: usize, | |
| 93 | arg2: usize, | |
| 94 | arg3: usize, | |
| 95 | arg4: usize, | |
| 96 | arg5: usize, | |
| 97 | arg6: usize, | |
| 98 | ) usize { | |
| 99 | return asm volatile ( | |
| 100 | \\ sc | |
| 101 | \\ bns+ 1f | |
| 102 | \\ neg 3, 3 | |
| 103 | \\ 1: | |
| 104 | : [ret] "={r3}" (-> usize) | |
| 105 | : [number] "{r0}" (@enumToInt(number)), | |
| 106 | [arg1] "{r3}" (arg1), | |
| 107 | [arg2] "{r4}" (arg2), | |
| 108 | [arg3] "{r5}" (arg3), | |
| 109 | [arg4] "{r6}" (arg4), | |
| 110 | [arg5] "{r7}" (arg5), | |
| 111 | [arg6] "{r8}" (arg6) | |
| 112 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 113 | ); | |
| 114 | } | |
| 115 | ||
| 116 | /// This matches the libc clone function. | |
| 117 | pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | |
| 118 | ||
| 119 | pub const restore = restore_rt; | |
| 120 | ||
| 121 | pub fn restore_rt() callconv(.Naked) void { | |
| 122 | return asm volatile ("sc" | |
| 123 | : | |
| 124 | : [number] "{r0}" (@enumToInt(SYS.rt_sigreturn)) | |
| 125 | : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" | |
| 126 | ); | |
| 127 | } |
lib/std/os/linux/tls.zig+10-3| ... | ... | @@ -53,7 +53,7 @@ const TLSVariant = enum { |
| 53 | 53 | }; |
| 54 | 54 | |
| 55 | 55 | const tls_variant = switch (builtin.arch) { |
| 56 | .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel => TLSVariant.VariantI, | |
| 56 | .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, | |
| 57 | 57 | .x86_64, .i386 => TLSVariant.VariantII, |
| 58 | 58 | else => @compileError("undefined tls_variant for this architecture"), |
| 59 | 59 | }; |
| ... | ... | @@ -77,12 +77,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) { |
| 77 | 77 | // make the generated code more efficient |
| 78 | 78 | |
| 79 | 79 | const tls_tp_offset = switch (builtin.arch) { |
| 80 | .mips, .mipsel => 0x7000, | |
| 80 | .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000, | |
| 81 | 81 | else => 0, |
| 82 | 82 | }; |
| 83 | 83 | |
| 84 | 84 | const tls_dtv_offset = switch (builtin.arch) { |
| 85 | .mips, .mipsel => 0x8000, | |
| 85 | .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000, | |
| 86 | 86 | .riscv32, .riscv64 => 0x800, |
| 87 | 87 | else => 0, |
| 88 | 88 | }; |
| ... | ... | @@ -165,6 +165,13 @@ pub fn setThreadPointer(addr: usize) void { |
| 165 | 165 | const rc = std.os.linux.syscall1(.set_thread_area, addr); |
| 166 | 166 | assert(rc == 0); |
| 167 | 167 | }, |
| 168 | .powerpc, .powerpc64, .powerpc64le => { | |
| 169 | asm volatile ( | |
| 170 | \\ mr 13, %[addr] | |
| 171 | : | |
| 172 | : [addr] "r" (addr) | |
| 173 | ); | |
| 174 | }, | |
| 168 | 175 | else => @compileError("Unsupported architecture"), |
| 169 | 176 | } |
| 170 | 177 | } |
lib/std/priority_queue.zig+10-1| ... | ... | @@ -195,7 +195,7 @@ pub fn PriorityQueue(comptime T: type) type { |
| 195 | 195 | count: usize, |
| 196 | 196 | |
| 197 | 197 | pub fn next(it: *Iterator) ?T { |
| 198 | if (it.count > it.queue.len - 1) return null; | |
| 198 | if (it.count >= it.queue.len) return null; | |
| 199 | 199 | const out = it.count; |
| 200 | 200 | it.count += 1; |
| 201 | 201 | return it.queue.items[out]; |
| ... | ... | @@ -428,3 +428,12 @@ test "std.PriorityQueue: remove at index" { |
| 428 | 428 | expectEqual(queue.remove(), 3); |
| 429 | 429 | expectEqual(queue.removeOrNull(), null); |
| 430 | 430 | } |
| 431 | ||
| 432 | test "std.PriorityQueue: iterator while empty" { | |
| 433 | var queue = PQ.init(testing.allocator, lessThan); | |
| 434 | defer queue.deinit(); | |
| 435 | ||
| 436 | var it = queue.iterator(); | |
| 437 | ||
| 438 | expectEqual(it.next(), null); | |
| 439 | } |
lib/std/process.zig+8-6| ... | ... | @@ -593,8 +593,10 @@ pub fn getUserInfo(name: []const u8) !UserInfo { |
| 593 | 593 | /// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else |
| 594 | 594 | /// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`. |
| 595 | 595 | pub fn posixGetUserInfo(name: []const u8) !UserInfo { |
| 596 | var reader = try io.Reader.open("/etc/passwd", null); | |
| 597 | defer reader.close(); | |
| 596 | const file = try std.fs.openFileAbsolute("/etc/passwd", .{}); | |
| 597 | defer file.close(); | |
| 598 | ||
| 599 | const reader = file.reader(); | |
| 598 | 600 | |
| 599 | 601 | const State = enum { |
| 600 | 602 | Start, |
| ... | ... | @@ -650,8 +652,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { |
| 650 | 652 | '0'...'9' => byte - '0', |
| 651 | 653 | else => return error.CorruptPasswordFile, |
| 652 | 654 | }; |
| 653 | if (@mulWithOverflow(u32, uid, 10, *uid)) return error.CorruptPasswordFile; | |
| 654 | if (@addWithOverflow(u32, uid, digit, *uid)) return error.CorruptPasswordFile; | |
| 655 | if (@mulWithOverflow(u32, uid, 10, &uid)) return error.CorruptPasswordFile; | |
| 656 | if (@addWithOverflow(u32, uid, digit, &uid)) return error.CorruptPasswordFile; | |
| 655 | 657 | }, |
| 656 | 658 | }, |
| 657 | 659 | .ReadGroupId => switch (byte) { |
| ... | ... | @@ -666,8 +668,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { |
| 666 | 668 | '0'...'9' => byte - '0', |
| 667 | 669 | else => return error.CorruptPasswordFile, |
| 668 | 670 | }; |
| 669 | if (@mulWithOverflow(u32, gid, 10, *gid)) return error.CorruptPasswordFile; | |
| 670 | if (@addWithOverflow(u32, gid, digit, *gid)) return error.CorruptPasswordFile; | |
| 671 | if (@mulWithOverflow(u32, gid, 10, &gid)) return error.CorruptPasswordFile; | |
| 672 | if (@addWithOverflow(u32, gid, digit, &gid)) return error.CorruptPasswordFile; | |
| 671 | 673 | }, |
| 672 | 674 | }, |
| 673 | 675 | } |
lib/std/special/c.zig+55| ... | ... | @@ -394,6 +394,61 @@ fn clone() callconv(.Naked) void { |
| 394 | 394 | \\ syscall |
| 395 | 395 | ); |
| 396 | 396 | }, |
| 397 | ||
| 398 | .powerpc64, .powerpc64le => { | |
| 399 | asm volatile ( | |
| 400 | \\ # store non-volatile regs r30, r31 on stack in order to put our | |
| 401 | \\ # start func and its arg there | |
| 402 | \\ stwu 30, -16(1) | |
| 403 | \\ stw 31, 4(1) | |
| 404 | \\ # save r3 (func) into r30, and r6(arg) into r31 | |
| 405 | \\ mr 30, 3 | |
| 406 | \\ mr 31, 6 | |
| 407 | \\ # create initial stack frame for new thread | |
| 408 | \\ clrrwi 4, 4, 4 | |
| 409 | \\ li 0, 0 | |
| 410 | \\ stwu 0, -16(4) | |
| 411 | \\ #move c into first arg | |
| 412 | \\ mr 3, 5 | |
| 413 | \\ mr 5, 7 | |
| 414 | \\ mr 6, 8 | |
| 415 | \\ mr 7, 9 | |
| 416 | \\ # move syscall number into r0 | |
| 417 | \\ li 0, 120 | |
| 418 | \\ sc | |
| 419 | ||
| 420 | \\ # check for syscall error | |
| 421 | \\ bns+ 1f # jump to label 1 if no summary overflow. | |
| 422 | \\ #else | |
| 423 | \\ neg 3, 3 #negate the result (errno) | |
| 424 | \\1: | |
| 425 | \\ # compare sc result with 0 | |
| 426 | \\ cmpwi cr7, 3, 0 | |
| 427 | ||
| 428 | \\ # if not 0, jump to end | |
| 429 | \\ bne cr7, 2f | |
| 430 | ||
| 431 | \\ #else: we're the child | |
| 432 | \\ #call funcptr: move arg (d) into r3 | |
| 433 | \\ mr 3, 31 | |
| 434 | \\ #move r30 (funcptr) into CTR reg | |
| 435 | \\ mtctr 30 | |
| 436 | \\ # call CTR reg | |
| 437 | \\ bctrl | |
| 438 | \\ # mov SYS_exit into r0 (the exit param is already in r3) | |
| 439 | \\ li 0, 1 | |
| 440 | \\ sc | |
| 441 | ||
| 442 | \\2: | |
| 443 | \\ # restore stack | |
| 444 | \\ lwz 30, 0(1) | |
| 445 | \\ lwz 31, 4(1) | |
| 446 | \\ addi 1, 1, 16 | |
| 447 | ||
| 448 | \\ blr | |
| 449 | ); | |
| 450 | }, | |
| 451 | ||
| 397 | 452 | else => @compileError("Implement clone() for this arch."), |
| 398 | 453 | } |
| 399 | 454 | } |
lib/std/start.zig+15| ... | ... | @@ -121,6 +121,21 @@ fn _start() callconv(.Naked) noreturn { |
| 121 | 121 | : [argc] "=r" (-> [*]usize) |
| 122 | 122 | ); |
| 123 | 123 | }, |
| 124 | .powerpc64le => { | |
| 125 | // Before returning the stack pointer, we have to set up a backchain | |
| 126 | // and a few other registers required by the ELFv2 ABI. | |
| 127 | // TODO: Support powerpc64 (big endian) on ELFv2. | |
| 128 | starting_stack_ptr = asm ( | |
| 129 | \\ mr 4, 1 | |
| 130 | \\ subi 1, 1, 32 | |
| 131 | \\ li 5, 0 | |
| 132 | \\ std 5, 0(1) | |
| 133 | \\ mr %[argc], 4 | |
| 134 | : [argc] "=r" (-> [*]usize) | |
| 135 | : | |
| 136 | : "r4", "r5" | |
| 137 | ); | |
| 138 | }, | |
| 124 | 139 | else => @compileError("unsupported arch"), |
| 125 | 140 | } |
| 126 | 141 | // If LLVM inlines stack variables into _start, they will overwrite |
src-self-hosted/translate_c.zig+38| ... | ... | @@ -5899,6 +5899,10 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N |
| 5899 | 5899 | saw_l_paren = true; |
| 5900 | 5900 | _ = m.next(); |
| 5901 | 5901 | }, |
| 5902 | // (type)sizeof(x) | |
| 5903 | .Keyword_sizeof, | |
| 5904 | // (type)alignof(x) | |
| 5905 | .Keyword_alignof, | |
| 5902 | 5906 | // (type)identifier |
| 5903 | 5907 | .Identifier => {}, |
| 5904 | 5908 | // (type)integer |
| ... | ... | @@ -6309,6 +6313,40 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast. |
| 6309 | 6313 | node.rhs = try parseCPrefixOpExpr(c, m, scope); |
| 6310 | 6314 | return &node.base; |
| 6311 | 6315 | }, |
| 6316 | .Keyword_sizeof => { | |
| 6317 | const inner = if (m.peek().? == .LParen) blk: { | |
| 6318 | _ = m.next(); | |
| 6319 | const inner = try parseCExpr(c, m, scope); | |
| 6320 | if (m.next().? != .RParen) { | |
| 6321 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); | |
| 6322 | return error.ParseError; | |
| 6323 | } | |
| 6324 | break :blk inner; | |
| 6325 | } else try parseCPrefixOpExpr(c, m, scope); | |
| 6326 | ||
| 6327 | const builtin_call = try c.createBuiltinCall("@sizeOf", 1); | |
| 6328 | builtin_call.params()[0] = inner; | |
| 6329 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); | |
| 6330 | return &builtin_call.base; | |
| 6331 | }, | |
| 6332 | .Keyword_alignof => { | |
| 6333 | // TODO this won't work if using <stdalign.h>'s | |
| 6334 | // #define alignof _Alignof | |
| 6335 | if (m.next().? != .LParen) { | |
| 6336 | try m.fail(c, "unable to translate C expr: expected '('", .{}); | |
| 6337 | return error.ParseError; | |
| 6338 | } | |
| 6339 | const inner = try parseCExpr(c, m, scope); | |
| 6340 | if (m.next().? != .RParen) { | |
| 6341 | try m.fail(c, "unable to translate C expr: expected ')'", .{}); | |
| 6342 | return error.ParseError; | |
| 6343 | } | |
| 6344 | ||
| 6345 | const builtin_call = try c.createBuiltinCall("@alignOf", 1); | |
| 6346 | builtin_call.params()[0] = inner; | |
| 6347 | builtin_call.rparen_token = try appendToken(c, .RParen, ")"); | |
| 6348 | return &builtin_call.base; | |
| 6349 | }, | |
| 6312 | 6350 | else => { |
| 6313 | 6351 | m.i -= 1; |
| 6314 | 6352 | return try parseCSuffixOpExpr(c, m, scope); |
src/all_types.hpp+1| ... | ... | @@ -2265,6 +2265,7 @@ struct CodeGen { |
| 2265 | 2265 | |
| 2266 | 2266 | Stage2LibCInstallation *libc; |
| 2267 | 2267 | |
| 2268 | bool is_versioned; | |
| 2268 | 2269 | size_t version_major; |
| 2269 | 2270 | size_t version_minor; |
| 2270 | 2271 | size_t version_patch; |
src/analyze.cpp+2-1| ... | ... | @@ -1009,7 +1009,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1009 | 1009 | g->zig_target->arch == ZigLLVM_x86_64 || |
| 1010 | 1010 | target_is_arm(g->zig_target) || |
| 1011 | 1011 | target_is_riscv(g->zig_target) || |
| 1012 | target_is_wasm(g->zig_target)) | |
| 1012 | target_is_wasm(g->zig_target) || | |
| 1013 | target_is_ppc(g->zig_target)) | |
| 1013 | 1014 | { |
| 1014 | 1015 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); |
| 1015 | 1016 | return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval; |
src/codegen.cpp+4-2| ... | ... | @@ -90,7 +90,8 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix) { |
| 90 | 90 | g->test_name_prefix = prefix; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch) { | |
| 93 | void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch) { | |
| 94 | g->is_versioned = is_versioned; | |
| 94 | 95 | g->version_major = major; |
| 95 | 96 | g->version_minor = minor; |
| 96 | 97 | g->version_patch = patch; |
| ... | ... | @@ -10823,6 +10824,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 10823 | 10824 | cache_bool(ch, g->emit_bin); |
| 10824 | 10825 | cache_bool(ch, g->emit_llvm_ir); |
| 10825 | 10826 | cache_bool(ch, g->emit_asm); |
| 10827 | cache_bool(ch, g->is_versioned); | |
| 10826 | 10828 | cache_usize(ch, g->version_major); |
| 10827 | 10829 | cache_usize(ch, g->version_minor); |
| 10828 | 10830 | cache_usize(ch, g->version_patch); |
| ... | ... | @@ -10893,7 +10895,7 @@ static void resolve_out_paths(CodeGen *g) { |
| 10893 | 10895 | buf_resize(out_basename, 0); |
| 10894 | 10896 | buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); |
| 10895 | 10897 | buf_append_buf(out_basename, g->root_out_name); |
| 10896 | buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, | |
| 10898 | buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, g->is_versioned, | |
| 10897 | 10899 | g->version_major, g->version_minor, g->version_patch)); |
| 10898 | 10900 | break; |
| 10899 | 10901 | } |
src/codegen.hpp+1-1| ... | ... | @@ -38,7 +38,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic); |
| 38 | 38 | void codegen_set_linker_script(CodeGen *g, const char *linker_script); |
| 39 | 39 | void codegen_set_test_filter(CodeGen *g, Buf *filter); |
| 40 | 40 | void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); |
| 41 | void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); | |
| 41 | void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch); | |
| 42 | 42 | void codegen_add_time_event(CodeGen *g, const char *name); |
| 43 | 43 | void codegen_print_timing_report(CodeGen *g, FILE *f); |
| 44 | 44 | void codegen_link(CodeGen *g); |
src/glibc.cpp+1-1| ... | ... | @@ -335,7 +335,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con |
| 335 | 335 | bool is_ld = (strcmp(lib->name, "ld") == 0); |
| 336 | 336 | |
| 337 | 337 | CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node); |
| 338 | codegen_set_lib_version(child_gen, lib->sover, 0, 0); | |
| 338 | codegen_set_lib_version(child_gen, true, lib->sover, 0, 0); | |
| 339 | 339 | child_gen->is_dynamic = true; |
| 340 | 340 | child_gen->is_dummy_so = true; |
| 341 | 341 | child_gen->version_script_path = map_file_path; |
src/main.cpp+5-1| ... | ... | @@ -415,6 +415,7 @@ static int main0(int argc, char **argv) { |
| 415 | 415 | const char *test_filter = nullptr; |
| 416 | 416 | const char *test_name_prefix = nullptr; |
| 417 | 417 | bool test_evented_io = false; |
| 418 | bool is_versioned = false; | |
| 418 | 419 | size_t ver_major = 0; |
| 419 | 420 | size_t ver_minor = 0; |
| 420 | 421 | size_t ver_patch = 0; |
| ... | ... | @@ -870,10 +871,13 @@ static int main0(int argc, char **argv) { |
| 870 | 871 | } else if (strcmp(arg, "--test-name-prefix") == 0) { |
| 871 | 872 | test_name_prefix = argv[i]; |
| 872 | 873 | } else if (strcmp(arg, "--ver-major") == 0) { |
| 874 | is_versioned = true; | |
| 873 | 875 | ver_major = atoi(argv[i]); |
| 874 | 876 | } else if (strcmp(arg, "--ver-minor") == 0) { |
| 877 | is_versioned = true; | |
| 875 | 878 | ver_minor = atoi(argv[i]); |
| 876 | 879 | } else if (strcmp(arg, "--ver-patch") == 0) { |
| 880 | is_versioned = true; | |
| 877 | 881 | ver_patch = atoi(argv[i]); |
| 878 | 882 | } else if (strcmp(arg, "--test-cmd") == 0) { |
| 879 | 883 | test_exec_args.append(argv[i]); |
| ... | ... | @@ -1223,7 +1227,7 @@ static int main0(int argc, char **argv) { |
| 1223 | 1227 | g->emit_llvm_ir = emit_llvm_ir; |
| 1224 | 1228 | |
| 1225 | 1229 | codegen_set_out_name(g, buf_out_name); |
| 1226 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); | |
| 1230 | codegen_set_lib_version(g, is_versioned, ver_major, ver_minor, ver_patch); | |
| 1227 | 1231 | g->want_single_threaded = want_single_threaded; |
| 1228 | 1232 | codegen_set_linker_script(g, linker_script); |
| 1229 | 1233 | g->version_script_path = version_script; |
src/target.cpp+21-8| ... | ... | @@ -779,7 +779,7 @@ const char *target_lib_file_prefix(const ZigTarget *target) { |
| 779 | 779 | } |
| 780 | 780 | } |
| 781 | 781 | |
| 782 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, | |
| 782 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned, | |
| 783 | 783 | size_t version_major, size_t version_minor, size_t version_patch) |
| 784 | 784 | { |
| 785 | 785 | if (target_is_wasm(target)) { |
| ... | ... | @@ -799,11 +799,19 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static, |
| 799 | 799 | if (is_static) { |
| 800 | 800 | return ".a"; |
| 801 | 801 | } else if (target_os_is_darwin(target->os)) { |
| 802 | return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", | |
| 803 | version_major, version_minor, version_patch)); | |
| 802 | if (is_versioned) { | |
| 803 | return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", | |
| 804 | version_major, version_minor, version_patch)); | |
| 805 | } else { | |
| 806 | return ".dylib"; | |
| 807 | } | |
| 804 | 808 | } else { |
| 805 | return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, | |
| 806 | version_major, version_minor, version_patch)); | |
| 809 | if (is_versioned) { | |
| 810 | return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, | |
| 811 | version_major, version_minor, version_patch)); | |
| 812 | } else { | |
| 813 | return ".so"; | |
| 814 | } | |
| 807 | 815 | } |
| 808 | 816 | } |
| 809 | 817 | } |
| ... | ... | @@ -853,6 +861,9 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { |
| 853 | 861 | case ZigLLVM_riscv32: |
| 854 | 862 | case ZigLLVM_riscv64: |
| 855 | 863 | case ZigLLVM_mipsel: |
| 864 | case ZigLLVM_ppc: | |
| 865 | case ZigLLVM_ppc64: | |
| 866 | case ZigLLVM_ppc64le: | |
| 856 | 867 | return "sp"; |
| 857 | 868 | |
| 858 | 869 | case ZigLLVM_wasm32: |
| ... | ... | @@ -879,7 +890,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { |
| 879 | 890 | case ZigLLVM_msp430: |
| 880 | 891 | case ZigLLVM_nvptx: |
| 881 | 892 | case ZigLLVM_nvptx64: |
| 882 | case ZigLLVM_ppc64le: | |
| 883 | 893 | case ZigLLVM_r600: |
| 884 | 894 | case ZigLLVM_renderscript32: |
| 885 | 895 | case ZigLLVM_renderscript64: |
| ... | ... | @@ -893,8 +903,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { |
| 893 | 903 | case ZigLLVM_tce: |
| 894 | 904 | case ZigLLVM_tcele: |
| 895 | 905 | case ZigLLVM_xcore: |
| 896 | case ZigLLVM_ppc: | |
| 897 | case ZigLLVM_ppc64: | |
| 898 | 906 | case ZigLLVM_ve: |
| 899 | 907 | zig_panic("TODO populate this table with stack pointer register name for this CPU architecture"); |
| 900 | 908 | } |
| ... | ... | @@ -1325,6 +1333,11 @@ bool target_is_mips(const ZigTarget *target) { |
| 1325 | 1333 | target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el; |
| 1326 | 1334 | } |
| 1327 | 1335 | |
| 1336 | bool target_is_ppc(const ZigTarget *target) { | |
| 1337 | return target->arch == ZigLLVM_ppc || target->arch == ZigLLVM_ppc64 || | |
| 1338 | target->arch == ZigLLVM_ppc64le; | |
| 1339 | } | |
| 1340 | ||
| 1328 | 1341 | unsigned target_fn_align(const ZigTarget *target) { |
| 1329 | 1342 | return 16; |
| 1330 | 1343 | } |
src/target.hpp+2-1| ... | ... | @@ -87,7 +87,7 @@ const char *target_asm_file_ext(const ZigTarget *target); |
| 87 | 87 | const char *target_llvm_ir_file_ext(const ZigTarget *target); |
| 88 | 88 | const char *target_exe_file_ext(const ZigTarget *target); |
| 89 | 89 | const char *target_lib_file_prefix(const ZigTarget *target); |
| 90 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, | |
| 90 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned, | |
| 91 | 91 | size_t version_major, size_t version_minor, size_t version_patch); |
| 92 | 92 | |
| 93 | 93 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); |
| ... | ... | @@ -95,6 +95,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 95 | 95 | |
| 96 | 96 | bool target_is_arm(const ZigTarget *target); |
| 97 | 97 | bool target_is_mips(const ZigTarget *target); |
| 98 | bool target_is_ppc(const ZigTarget *target); | |
| 98 | 99 | bool target_allows_addr_zero(const ZigTarget *target); |
| 99 | 100 | bool target_has_valgrind_support(const ZigTarget *target); |
| 100 | 101 | bool target_os_is_darwin(Os os); |
test/stack_traces.zig+3-3| ... | ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 282 | 282 | \\source.zig:10:8: [address] in main (test) |
| 283 | 283 | \\ foo(); |
| 284 | 284 | \\ ^ |
| 285 | \\start.zig:254:29: [address] in std.start.posixCallMainAndExit (test) | |
| 285 | \\start.zig:269:29: [address] in std.start.posixCallMainAndExit (test) | |
| 286 | 286 | \\ return root.main(); |
| 287 | 287 | \\ ^ |
| 288 | \\start.zig:128:5: [address] in std.start._start (test) | |
| 288 | \\start.zig:143:5: [address] in std.start._start (test) | |
| 289 | 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 290 | 290 | \\ ^ |
| 291 | 291 | \\ |
| ... | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 294 | 294 | switch (std.Target.current.cpu.arch) { |
| 295 | 295 | .aarch64 => "", // TODO disabled; results in segfault |
| 296 | 296 | else => |
| 297 | \\start.zig:128:5: [address] in std.start._start (test) | |
| 297 | \\start.zig:143:5: [address] in std.start._start (test) | |
| 298 | 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 299 | 299 | \\ ^ |
| 300 | 300 | \\ |
test/stage1/behavior/translate_c_macros.h+4-1| ... | ... | @@ -6,4 +6,7 @@ typedef struct Color { |
| 6 | 6 | unsigned char a; |
| 7 | 7 | } Color; |
| 8 | 8 | #define CLITERAL(type) (type) |
| 9 | #define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray | |
| \ No newline at end of file | ||
| 9 | #define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray | |
| 10 | ||
| 11 | #define MY_SIZEOF(x) ((int)sizeof(x)) | |
| 12 | #define MY_SIZEOF2(x) ((int)sizeof x) |
test/stage1/behavior/translate_c_macros.zig+7-1| ... | ... | @@ -1,12 +1,18 @@ |
| 1 | 1 | const expect = @import("std").testing.expect; |
| 2 | const expectEqual = @import("std").testing.expectEqual; | |
| 2 | 3 | |
| 3 | 4 | const h = @cImport(@cInclude("stage1/behavior/translate_c_macros.h")); |
| 4 | 5 | |
| 5 | 6 | test "initializer list expression" { |
| 6 | @import("std").testing.expectEqual(h.Color{ | |
| 7 | expectEqual(h.Color{ | |
| 7 | 8 | .r = 200, |
| 8 | 9 | .g = 200, |
| 9 | 10 | .b = 200, |
| 10 | 11 | .a = 255, |
| 11 | 12 | }, h.LIGHTGRAY); |
| 12 | 13 | } |
| 14 | ||
| 15 | test "sizeof in macros" { | |
| 16 | expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32)); | |
| 17 | expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32)); | |
| 18 | } |