forked from dlang/tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chmodzip.d
94 lines (83 loc) · 2.79 KB
/
chmodzip.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import core.stdc.stdlib;
import std.conv;
import std.stdio;
import std.file;
import std.datetime;
import std.zip;
import std.zlib;
int main(string[] args)
{
if (args.length == 1)
{
stderr.writeln("Usage: zip zipfile attr members...");
return EXIT_FAILURE;
}
if (args.length == 2)
{
auto zipname = args[1];
auto buffer = cast(byte[])std.file.read(zipname);
auto zr = new std.zip.ZipArchive(cast(void[])buffer);
writefln("comment = '%s'", zr.comment);
foreach (ArchiveMember de; zr.directory)
{
zr.expand(de);
writefln("name = %s", de.name);
writefln("\tcomment = %s", de.comment);
writefln("\tmadeVersion = x%04x", de.madeVersion);
writefln("\textractVersion = x%04x", de.extractVersion);
writefln("\tflags = x%04x", de.flags);
writefln("\tcompressionMethod = %d", de.compressionMethod);
writefln("\tcrc32 = x%08x", de.crc32);
writefln("\texpandedSize = %s", de.expandedSize);
writefln("\tcompressedSize = %s", de.compressedSize);
writefln("\teattr = %03o, %03o", de.externalAttributes >> 16, de.externalAttributes & 0xFFFF);
writefln("\tiattr = %03o", de.internalAttributes);
//writefln("\tdate = %s", std.date.toString(std.date.toDtime(de.time)));
writefln("\tdate = %s", SysTime(unixTimeToStdTime((de.time))));
}
return 0;
}
auto zipname = args[1];
auto attr = args[2];
auto members = args[3 .. $];
uint newattr = 0;
foreach (c; attr)
{
if (c < '0' || c > '7' || attr.length > 4)
throw new ZipException("attr must be 1..4 octal digits, not " ~ attr);
newattr = (newattr << 3) | (c - '0');
}
auto buffer = cast(byte[])std.file.read(zipname);
auto zr = new std.zip.ZipArchive(cast(void[])buffer);
L1:
foreach (member; members)
{
foreach (ArchiveMember de; zr.directory)
{
if (de.name == member)
continue L1;
}
throw new ZipException(member ~ " not in zipfile " ~ zipname);
}
bool changes;
foreach (ArchiveMember de; zr.directory)
{
zr.expand(de);
foreach (member; members)
{
if (de.name == member && ((de.externalAttributes >> 16) & octal!7777) != newattr)
{
changes = true;
de._madeVersion = 0x317; // necessary or linux unzip will ignore attributes
de.externalAttributes = (de.externalAttributes & ~(octal!7777 << 16)) | (newattr << 16);
break;
}
}
}
if (changes)
{
void[] data2 = zr.build();
std.file.write(zipname, cast(byte[])data2);
}
return 0;
}