Tcl Source Code

Check-in [5f80f9af59]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Stub fix, safe interpreter fix, and use more size_t wherever possible
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-branch
Files: files | file ages | folders
SHA3-256: 5f80f9af59113b72a3138159d42fd826a61f170d13ddb82033be1d04c7df8c37
User & Date: jan.nijtmans 2018-09-12 19:32:31
Context
2018-09-13
20:30
Fix test-case registry-6.20, which started failing starting with the TIP #389 commit. check-in: 0db5ab91bb user: jan.nijtmans tags: core-8-branch
2018-09-12
19:34
Merge 8.7 (TIP #430 implementation) check-in: d2d99b2173 user: jan.nijtmans tags: trunk
19:32
Stub fix, safe interpreter fix, and use more size_t wherever possible check-in: 5f80f9af59 user: jan.nijtmans tags: core-8-branch
19:30
TIP #430 implementation check-in: b74093feee user: jan.nijtmans tags: core-8-branch
2018-09-11
22:41
Make ready for TIP #494 compatibility Closed-Leaf check-in: da3a746b1d user: jan.nijtmans tags: core_zip_vfs-review
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to .fossil-settings/binary-glob.

1
2
3
4
5
6

7
8
9
compat/zlib/win32/zdll.lib
compat/zlib/win32/zlib1.dll
compat/zlib/win64/zdll.lib
compat/zlib/win64/zlib1.dll
compat/zlib/win64/libz.dll.a
compat/zlib/zlib.3.pdf

*.bmp
*.gif
*.png





>



1
2
3
4
5
6
7
8
9
10
compat/zlib/win32/zdll.lib
compat/zlib/win32/zlib1.dll
compat/zlib/win64/zdll.lib
compat/zlib/win64/zlib1.dll
compat/zlib/win64/libz.dll.a
compat/zlib/zlib.3.pdf
tools/empty.zip
*.bmp
*.gif
*.png

Changes to generic/tcl.decls.

2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
....
2350
2351
2352
2353
2354
2355
2356



2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
# TIP #456
declare 631 {
    Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service,
	    const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc,
	    ClientData callbackData)
}

# ----- BASELINE -- FOR -- 8.7.0 ----- #

# TIP #430
declare 632 {
    int TclZipfs_Mount(
    Tcl_Interp *interp,
    const char *mntpt,
    const char *zipname,
    const char *passwd)
................................................................................
    int TclZipfs_Mount_Buffer(
    Tcl_Interp *interp,
    const char *mntpt,
    unsigned char *data,
    size_t datalen,
    int copy)
}



##############################################################################

# Define the platform specific public Tcl interface. These functions are only
# available on the designated platform.

interface tclPlat

################################
# Unix specific functions
#   (none)
declare 0 unix {
    int TclZipfs_AppHook(int *argc, char ***argv)
}

################################
# Windows specific functions

# Added in Tcl 8.1






<
<







 







>
>
>










|







2326
2327
2328
2329
2330
2331
2332


2333
2334
2335
2336
2337
2338
2339
....
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
# TIP #456
declare 631 {
    Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service,
	    const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc,
	    ClientData callbackData)
}



# TIP #430
declare 632 {
    int TclZipfs_Mount(
    Tcl_Interp *interp,
    const char *mntpt,
    const char *zipname,
    const char *passwd)
................................................................................
    int TclZipfs_Mount_Buffer(
    Tcl_Interp *interp,
    const char *mntpt,
    unsigned char *data,
    size_t datalen,
    int copy)
}

# ----- BASELINE -- FOR -- 8.7.0 ----- #

##############################################################################

# Define the platform specific public Tcl interface. These functions are only
# available on the designated platform.

interface tclPlat

################################
# Unix specific functions
#   (none)
declare 2 unix {
    int TclZipfs_AppHook(int *argc, char ***argv)
}

################################
# Windows specific functions

# Added in Tcl 8.1

Changes to generic/tclPlatDecls.h.

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
94
95
96
97
98
99
...
102
103
104
105
106
107
108


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124


125
126
127
128
129
130
131
132
133
134
135
136
#endif

/*
 * Exported function declarations:
 */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */


/* 0 */
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
EXTERN TCHAR *		Tcl_WinUtfToTChar(const char *str, int len,
				Tcl_DString *dsPtr);
/* 1 */
................................................................................
EXTERN char *		Tcl_WinTCharToUtf(const TCHAR *str, int len,
				Tcl_DString *dsPtr);
/* 2 */
EXTERN int		TclZipfs_AppHook(int *argc, TCHAR ***argv);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 0 */
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);


/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, const char *bundleName,
				const char *bundleVersion,
				int hasResourceFile, int maxPathLen,
				char *libraryPath);


#endif /* MACOSX */

typedef struct TclPlatStubs {
    int magic;
    void *hooks;

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */


    int (*tclZipfs_AppHook) (int *argc, char ***argv); /* 0 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
    char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
    int (*tclZipfs_AppHook) (int *argc, TCHAR ***argv); /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tclZipfs_AppHook) (int *argc, char ***argv); /* 0 */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */

#endif /* MACOSX */
} TclPlatStubs;

extern const TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}
................................................................................
#if defined(USE_TCL_STUBS)

/*
 * Inline function declarations:
 */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */


#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 0 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define Tcl_WinUtfToTChar \
	(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#define Tcl_WinTCharToUtf \
	(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 0 */
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */


#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLPLATDECLS */








>
>
|







 







|
>
>






>
>







>
>
|







|

>







 







>
>

|










|
|


>
>












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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#endif

/*
 * Exported function declarations:
 */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
/* Slot 0 is reserved */
/* Slot 1 is reserved */
/* 2 */
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
EXTERN TCHAR *		Tcl_WinUtfToTChar(const char *str, int len,
				Tcl_DString *dsPtr);
/* 1 */
................................................................................
EXTERN char *		Tcl_WinTCharToUtf(const TCHAR *str, int len,
				Tcl_DString *dsPtr);
/* 2 */
EXTERN int		TclZipfs_AppHook(int *argc, TCHAR ***argv);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 0 */
EXTERN int		Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
				const char *bundleName, int hasResourceFile,
				int maxPathLen, char *libraryPath);
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, const char *bundleName,
				const char *bundleVersion,
				int hasResourceFile, int maxPathLen,
				char *libraryPath);
/* 2 */
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);
#endif /* MACOSX */

typedef struct TclPlatStubs {
    int magic;
    void *hooks;

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    void (*reserved0)(void);
    void (*reserved1)(void);
    int (*tclZipfs_AppHook) (int *argc, char ***argv); /* 2 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
    char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
    int (*tclZipfs_AppHook) (int *argc, TCHAR ***argv); /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */
    int (*tclZipfs_AppHook) (int *argc, char ***argv); /* 2 */
#endif /* MACOSX */
} TclPlatStubs;

extern const TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}
................................................................................
#if defined(USE_TCL_STUBS)

/*
 * Inline function declarations:
 */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
/* Slot 0 is reserved */
/* Slot 1 is reserved */
#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 2 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define Tcl_WinUtfToTChar \
	(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#define Tcl_WinTCharToUtf \
	(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#define Tcl_MacOSXOpenBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#define TclZipfs_AppHook \
	(tclPlatStubsPtr->tclZipfs_AppHook) /* 2 */
#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLPLATDECLS */


Changes to generic/tclStubInit.c.

834
835
836
837
838
839
840


841
842
843
844
845
846
847
848
849
850

851
852
853
854
855
856
857
#endif /* MACOSX */
};

static const TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */


    TclZipfs_AppHook, /* 0 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    Tcl_WinUtfToTChar, /* 0 */
    Tcl_WinTCharToUtf, /* 1 */
    TclZipfs_AppHook, /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    TclZipfs_AppHook, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */

#endif /* MACOSX */
};

const TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    0,
    TclBN_epoch, /* 0 */






>
>
|







|

>







834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
#endif /* MACOSX */
};

static const TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    0, /* 0 */
    0, /* 1 */
    TclZipfs_AppHook, /* 2 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    Tcl_WinUtfToTChar, /* 0 */
    Tcl_WinTCharToUtf, /* 1 */
    TclZipfs_AppHook, /* 2 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_MacOSXOpenBundleResources, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */
    TclZipfs_AppHook, /* 2 */
#endif /* MACOSX */
};

const TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    0,
    TclBN_epoch, /* 0 */

Changes to generic/tclZipfs.c.

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
....
1054
1055
1056
1057
1058
1059
1060





1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
....
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
....
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
....
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
....
1910
1911
1912
1913
1914
1915
1916

1917

1918
1919
1920
1921
1922
1923
1924
1925
....
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
....
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
....
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
....
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
....
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
....
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
....
2227
2228
2229
2230
2231
2232
2233
2234


2235
2236
2237
2238
2239
2240
2241
....
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
....
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
....
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
....
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
....
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
....
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
....
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
....
2884
2885
2886
2887
2888
2889
2890
2891





2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
....
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
....
3770
3771
3772
3773
3774
3775
3776
3777

3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791

3792
3793
3794
3795
3796
3797
3798
....
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
....
3950
3951
3952
3953
3954
3955
3956
3957

3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
....
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
....
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320





4321
4322
4323
4324
4325
4326
4327
....
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
....
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
typedef struct ZipFile {
    char *name;               /* Archive name */
    size_t namelen;
    char is_membuf;           /* When true, not a file but a memory buffer */
    Tcl_Channel chan;         /* Channel handle or NULL */
    unsigned char *data;      /* Memory mapped or malloc'ed file */
    long length;              /* Length of memory mapped file */
    unsigned char *tofree;    /* Non-NULL if malloc'ed file */
    int nfiles;               /* Number of files in archive */
    unsigned long baseoffs;             /* Archive start */
    long baseoffsp;            /* Password start */
    unsigned long centoffs;             /* Archive directory start */
    unsigned char pwbuf[264];          /* Password buffer */
#if defined(_WIN32) || defined(_WIN64)
    HANDLE mh;
#endif
    unsigned long nopen;                /* Number of open files on archive */
    struct ZipEntry *entries; /* List of files in archive */
    struct ZipEntry *topents; /* List of top-level dirs in archive */
#if HAS_DRIVES
    int mntdrv;                  /* Drive letter of mount point */
#endif
    int mntptlen;
    char *mntpt;              /* Mount point */
} ZipFile;

/*
 * In-core description of file contained in mounted ZIP archive.
 */

typedef struct ZipEntry {
    char *name;               /* The full pathname of the virtual file */
    ZipFile *zipfile;         /* The ZIP file holding this virtual file */
    long offset;              /* Data offset into memory mapped ZIP file */
    int nbyte;                /* Uncompressed size of the virtual file */
    int nbytecompr;           /* Compressed size of the virtual file */
    int cmeth;                /* Compress method */
    int isdir;                  /* Set to 1 if directory, or -1 if root */
    int depth;                   /* Number of slashes in path. */
    int crc32;                /* CRC-32 */
    int timestamp;            /* Modification time */
................................................................................
/*
 * File channel for file contained in mounted ZIP archive.
 */

typedef struct ZipChannel {
    ZipFile *zipfile;         /* The ZIP file holding this channel */
    ZipEntry *zipentry;       /* Pointer back to virtual file */
    unsigned long nmax;       /* Max. size for write */
    unsigned long nbyte;      /* Number of bytes of uncompressed data */
    unsigned long nread;      /* Pos of next byte to be read from the channel */
    unsigned char *ubuf;      /* Pointer to the uncompressed data */
    int iscompr;              /* True if data is compressed */
    int isdir;                  /* Set to 1 if directory, or -1 if root */
    int isenc;                /* True if data is encrypted */
    int iswr;                 /* True if open for writing */
    unsigned long keys[3];    /* Key for decryption */
} ZipChannel;

/*
 * Global variables.
................................................................................
 *    The given ZipFile struct is filled with information about the ZIP archive file.
 *
 *-------------------------------------------------------------------------
 */
static int
ZipFS_Find_TOC(Tcl_Interp *interp, int needZip, ZipFile *zf)
{
    int i;
    unsigned char *p, *q;
    p = zf->data + zf->length - ZIP_CENTRAL_END_LEN;
    while (p >= zf->data) {
        if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
            if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) {
            break;
            }
................................................................................
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSOpenArchive(Tcl_Interp *interp, const char *zipname, int needZip, ZipFile *zf)
{
    int i;
    ClientData handle;
    zf->namelen=0;
    zf->is_membuf=0;
#if defined(_WIN32) || defined(_WIN64)
    zf->data = NULL;
    zf->mh = INVALID_HANDLE_VALUE;
#else
................................................................................
        if (Tcl_SetChannelOption(interp, zf->chan, "-translation", "binary") != TCL_OK) {
            goto error;
        }
        if (Tcl_SetChannelOption(interp, zf->chan, "-encoding", "binary") != TCL_OK) {
            goto error;
        }
        zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
        if ((zf->length <= 0) || (zf->length > 64 * 1024 * 1024)) {
            ZIPFS_ERROR(interp,"illegal file size");
            goto error;
        }
        Tcl_Seek(zf->chan, 0, SEEK_SET);
        zf->tofree = zf->data = (unsigned char *) Tcl_AttemptAlloc(zf->length);
        if (zf->tofree == NULL) {
            ZIPFS_ERROR(interp,"out of memory")
................................................................................
            ZIPFS_ERROR(interp,"file read error");
            goto error;
        }
        Tcl_Close(interp, zf->chan);
        zf->chan = NULL;
    } else {
#if defined(_WIN32) || defined(_WIN64)





        zf->length = GetFileSize((HANDLE) handle, 0);
        if (
            (zf->length == INVALID_FILE_SIZE) ||

            (zf->length < ZIP_CENTRAL_END_LEN)
        ) {
            ZIPFS_ERROR(interp,"invalid file size");
            goto error;
        }
        zf->mh = CreateFileMapping((HANDLE) handle, 0, PAGE_READONLY, 0,
                       zf->length, 0);
................................................................................
        }
        zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length);
        if (zf->data == NULL) {
            ZIPFS_ERROR(interp,"file mapping failed");
            goto error;
        }
#else
        zf->length = lseek((int) (long) handle, 0, SEEK_END);
        if ((zf->length == -1) || (zf->length < ZIP_CENTRAL_END_LEN)) {
            ZIPFS_ERROR(interp,"invalid file size");
            goto error;
        }
        lseek((int) (long) handle, 0, SEEK_SET);
        zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ,
                          MAP_FILE | MAP_PRIVATE,
                          (int) (long) handle, 0);
        if (zf->data == MAP_FAILED) {
            ZIPFS_ERROR(interp,"file mapping failed");
            goto error;
        }
#endif
    }
    return ZipFS_Find_TOC(interp,needZip,zf);
................................................................................
 * Side effects:
 *-------------------------------------------------------------------------
 */

static int
ZipFS_Catalogue_Filesystem(Tcl_Interp *interp, ZipFile *zf0, const char *mntpt, const char *passwd, const char *zipname)
{
    int i, pwlen, isNew;

    ZipFile *zf;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_DString ds, dsm, fpBuf;
    unsigned char *q;
#if HAS_DRIVES
    int drive = 0;
#endif
    WriteLock();

    pwlen = 0;
    if (passwd != NULL) {
        pwlen = strlen(passwd);
        if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) {
            if (interp) {
................................................................................
            z->next = zf->entries;
            zf->entries = z;
        }
    }
    q = zf->data + zf->centoffs;
    Tcl_DStringInit(&fpBuf);
    for (i = 0; i < zf->nfiles; i++) {
        int pathlen, comlen, extra, isdir = 0, dosTime, dosDate, nbcompr, offs;

        unsigned char *lq, *gq = NULL;
        char *fullpath, *path;

        pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
        comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
        extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
        Tcl_DStringSetLength(&ds, 0);
................................................................................
    char *buf, int bufsize, Tcl_HashTable *fileHash
) {
    Tcl_Channel in;
    Tcl_HashEntry *hPtr;
    ZipEntry *z;
    z_stream stream;
    const char *zpath;

    int nbyte, nbytecompr, len, crc, flush, pos[3], zpathlen, olen;

    int mtime = 0, isNew, align = 0, cmeth;
    unsigned long keys[3], keys0[3];
    char obuf[4096];

    zpath = name;
    while (zpath != NULL && zpath[0] == '/') {
        zpath++;
    }
................................................................................
            mtime = statBuf.st_mtime;
        }
        Tcl_DecrRefCount(pathObj);
    }
    Tcl_ResetResult(interp);
    crc = 0;
    nbyte = nbytecompr = 0;
    while ((len = Tcl_Read(in, buf, bufsize)) > 0) {
        crc = crc32(crc, (unsigned char *) buf, len);
        nbyte += len;
    }
    if (len == -1) {
        if (nbyte == 0) {
            if (strcmp("illegal operation on a directory",
                   Tcl_PosixError(interp)) == 0) {
            Tcl_Close(interp, in);
            return TCL_OK;
            }
        }
................................................................................
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    pos[0] = Tcl_Tell(out);
    memset(buf, '\0', ZIP_LOCAL_HEADER_LEN);
    memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen);
    len = zpathlen + ZIP_LOCAL_HEADER_LEN;
    if (Tcl_Write(out, buf, len) != len) {
wrerr:
    Tcl_AppendResult(interp, "write error", (char *) NULL);
    Tcl_Close(interp, in);
    return TCL_ERROR;
    }
    if ((len + pos[0]) & 3) {
        unsigned char abuf[8];
................................................................................
         * Align payload to next 4-byte boundary using a dummy extra
         * entry similar to the zipalign tool from Android's SDK.
         */
        align = 4 + ((len + pos[0]) & 3);
        zip_write_short(abuf, 0xffff);
        zip_write_short(abuf + 2, align - 4);
        zip_write_int(abuf + 4, 0x03020100);
        if (Tcl_Write(out, (const char *)abuf, align) != align) {
            goto wrerr;
        }
    }
    if (passwd != NULL) {
        int i, ch, tmp;
        unsigned char kvbuf[24];
        Tcl_Obj *ret;
................................................................................
        Tcl_AppendResult(interp, "compression init error on \"", path, "\"",
                 (char *) NULL);
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    do {
    len = Tcl_Read(in, buf, bufsize);
    if (len == -1) {
        Tcl_AppendResult(interp, "read error on \"", path, "\"",
                 (char *) NULL);
        deflateEnd(&stream);
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    stream.avail_in = len;
    stream.next_in = (unsigned char *) buf;
    flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH;
    do {
        stream.avail_out = sizeof (obuf);
        stream.next_out = (unsigned char *) obuf;
        len = deflate(&stream, flush);
        if (len == Z_STREAM_ERROR) {
            Tcl_AppendResult(interp, "deflate error on \"", path, "\"",
                     (char *) NULL);
            deflateEnd(&stream);
            Tcl_Close(interp, in);
            return TCL_ERROR;
        }
        olen = sizeof (obuf) - stream.avail_out;
................................................................................
    Tcl_Flush(out);
    pos[1] = Tcl_Tell(out);
    if (nbyte - nbytecompr <= 0) {
        /*
         * Compressed file larger than input,
         * write it again uncompressed.
         */
        if ((int) Tcl_Seek(in, 0, SEEK_SET) != 0) {
            goto seekErr;
        }
        if ((int) Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) {
seekErr:
            Tcl_Close(interp, in);
            Tcl_AppendResult(interp, "seek error", (char *) NULL);
            return TCL_ERROR;
        }
        nbytecompr = (passwd != NULL) ? 12 : 0;
        while (1) {
            len = Tcl_Read(in, buf, bufsize);
            if (len == -1) {
            Tcl_AppendResult(interp, "read error on \"", path, "\"",
                     (char *) NULL);
            Tcl_Close(interp, in);
            return TCL_ERROR;
            } else if (len == 0) {
            break;
            }
            if (passwd != NULL) {

            int i, tmp;

            for (i = 0; i < len; i++) {
                buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp);
            }
            }
            if (Tcl_Write(out, buf, len) != len) {
            Tcl_AppendResult(interp, "write error", (char *) NULL);
            Tcl_Close(interp, in);
            return TCL_ERROR;
            }
            nbytecompr += len;
        }
        cmeth = ZIP_COMPMETH_STORED;
................................................................................
    zip_write_short(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp));
    zip_write_short(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp));
    zip_write_int(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
    zip_write_int(buf + ZIP_LOCAL_COMPLEN_OFFS, z->nbytecompr);
    zip_write_int(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->nbyte);
    zip_write_short(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen);
    zip_write_short(buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
    if ((int) Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "seek error", (char *) NULL);
        return TCL_ERROR;
    }
    if (Tcl_Write(out, buf, ZIP_LOCAL_HEADER_LEN) != ZIP_LOCAL_HEADER_LEN) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "write error", (char *) NULL);
        return TCL_ERROR;
    }
    Tcl_Flush(out);
    if ((int) Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "seek error", (char *) NULL);
        return TCL_ERROR;
    }
    return TCL_OK;
}
................................................................................
 */

static int
ZipFSMkZipOrImgObjCmd(ClientData clientData, Tcl_Interp *interp,
                      int isImg, int isList, int objc, Tcl_Obj *const objv[])
{
    Tcl_Channel out;
    int len = 0, pwlen = 0, slen = 0, i, count, ret = TCL_ERROR, lobjc, pos[3];


    Tcl_Obj **lobjv, *list = NULL;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable fileHash;
    char *strip = NULL, *pw = NULL, pwbuf[264], buf[4096];

................................................................................
        }
        Unlock();
        if (!isMounted) {
            zf = &zf0;
        }
        if (isMounted ||
            (ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK)) {
            i = Tcl_Write(out, (char *) zf->data, zf->baseoffsp);
            if (i != zf->baseoffsp) {
                memset(pwbuf, 0, sizeof (pwbuf));
                Tcl_DecrRefCount(list);
                Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
                Tcl_Close(interp, out);
                if (zf == &zf0) {
                    ZipFSCloseArchive(interp, zf);
                } else {
................................................................................
                ZipFSCloseArchive(interp, zf);
            } else {
                WriteLock();
                zf->nopen--;
                Unlock();
            }
        } else {

            int k, m, n;
            Tcl_Channel in;
            const char *errMsg = "seek error";

            /*
             * Fall back to read it as plain file which
             * hopefully is a static tclsh or wish binary
             * with proper zipfs infrastructure built in.
................................................................................
                Tcl_DecrRefCount(list);
                Tcl_Close(interp, out);
                return TCL_ERROR;
            }
            Tcl_SetChannelOption(interp, in, "-translation", "binary");
            Tcl_SetChannelOption(interp, in, "-encoding", "binary");
            i = Tcl_Seek(in, 0, SEEK_END);
            if (i == -1) {
cperr:
                memset(pwbuf, 0, sizeof (pwbuf));
                Tcl_DecrRefCount(list);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
                Tcl_Close(interp, out);
                Tcl_Close(interp, in);
                return TCL_ERROR;
................................................................................
    }
    Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
    pos[0] = Tcl_Tell(out);
    if (!isList && (objc > 3)) {
        strip = Tcl_GetString(objv[3]);
        slen = strlen(strip);
    }
    for (i = 0; i < lobjc; i += (isList ? 2 : 1)) {
        const char *path, *name;

        path = Tcl_GetString(lobjv[i]);
        if (isList) {
            name = Tcl_GetString(lobjv[i + 1]);
        } else {
            name = path;
................................................................................
        if (ZipAddFile(interp, path, name, out, pw, buf, sizeof (buf),
                       &fileHash) != TCL_OK) {
            goto done;
        }
    }
    pos[1] = Tcl_Tell(out);
    count = 0;
    for (i = 0; i < lobjc; i += (isList ? 2 : 1)) {
        const char *path, *name;

        path = Tcl_GetString(lobjv[i]);
        if (isList) {
            name = Tcl_GetString(lobjv[i + 1]);
        } else {
            name = path;
................................................................................
        zip_write_short(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
        zip_write_short(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
        zip_write_short(buf + ZIP_CENTRAL_IATTR_OFFS, 0);
        zip_write_int(buf + ZIP_CENTRAL_EATTR_OFFS, 0);
        zip_write_int(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]);
        if (
            (Tcl_Write(out, buf, ZIP_CENTRAL_HEADER_LEN) != ZIP_CENTRAL_HEADER_LEN)
            || (Tcl_Write(out, z->name, len) != len)
        ) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
            goto done;
        }
        count++;
    }
    Tcl_Flush(out);
................................................................................
    ReadLock();
    z = ZipFSLookup(filename);
    if (z != NULL) {
        Tcl_Obj *result = Tcl_GetObjResult(interp);

        Tcl_ListObjAppendElement(interp, result,
                     Tcl_NewStringObj(z->zipfile->name, -1));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->nbyte));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->nbytecompr));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->offset));
    }
    Unlock();
    return TCL_OK;
}
 
/*
 *-------------------------------------------------------------------------
................................................................................

Tcl_Obj *TclZipfs_TclLibrary(void) {
    if(zipfs_literal_tcl_library) {
        return Tcl_NewStringObj(zipfs_literal_tcl_library,-1);
    } else {
        Tcl_Obj *vfsinitscript;
        int found=0;






        /* Look for the library file system within the executable */
        vfsinitscript=Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",-1);
        Tcl_IncrRefCount(vfsinitscript);
        found=Tcl_FSAccess(vfsinitscript,F_OK);
        Tcl_DecrRefCount(vfsinitscript);
        if(found==TCL_OK) {
            zipfs_literal_tcl_library=ZIPFS_APP_MOUNT "/tcl_library";
            return Tcl_NewStringObj(zipfs_literal_tcl_library,-1);
        }
#if defined(_WIN32) || defined(_WIN64)
        HMODULE hModule = TclWinGetTclInstance();
        WCHAR wName[MAX_PATH + LIBRARY_SIZE];
        char dllname[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX];

        if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
            GetModuleFileNameA(hModule, dllname, MAX_PATH);
        } else {
            ToUtf(wName, dllname);
        }
        /* Mount zip file and dll before releasing to search */
        if(TclZipfs_AppHook_FindTclInit(dllname)==TCL_OK) {
................................................................................
            }
            Tcl_Free((char *) info);
            ZIPFS_ERROR(interp,"decompression error");
            goto error;
        }
    }
wrapchan:
    sprintf(cname, "zipfs_%lx_%d", (unsigned long) z->offset, ZipFS.idCount++);
    z->zipfile->nopen++;
    Unlock();
    return Tcl_CreateChannel(&ZipChannelType, cname, (ClientData) info, flags);

error:
    Unlock();
    return NULL;
................................................................................
Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result,
               Tcl_Obj *pathPtr, const char *pattern,
               Tcl_GlobTypeData *types)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *normPathPtr;
    int scnt, len, l, dirOnly = -1, prefixLen, strip = 0;

    char *pat, *prefix, *path;
    Tcl_DString dsPref;

    if (!(normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1;

    if (types != NULL) {
        dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR;
    }

    /* the prefix that gets prepended to results */
    prefix = Tcl_GetStringFromObj(pathPtr, &prefixLen);

    /* the (normalized) path we're searching */
    path = Tcl_GetStringFromObj(normPathPtr, &len);


    Tcl_DStringInit(&dsPref);
    Tcl_DStringAppend(&dsPref, prefix, prefixLen);

    if (strcmp(prefix, path) == 0) {
        prefix = NULL;
    } else {
................................................................................
    hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
    while (hPtr != NULL) {
        ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);

        if (zf->mntptlen == 0) {
            ZipEntry *z = zf->topents;
            while (z != NULL) {
                int lenz = strlen(z->name);
                if (
                    (lenz > len + 1)
                    && (strncmp(z->name, path, len) == 0)
                    && (z->name[len] == '/')
                    && (CountSlashes(z->name) == l)
                    && Tcl_StringCaseMatch(z->name + len + 1, pattern, 0)
                ) {
................................................................................

static int
Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    ZipFile *zf;
    int ret = -1, len;

    char *path;

    if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1;

    path = Tcl_GetStringFromObj(pathPtr, &len);
    if(strncmp(path,ZIPFS_VOLUME,ZIPFS_VOLUME_LEN)!=0) {
        return -1;
    }

    len = strlen(path);

    ReadLock();
    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
    if (hPtr != NULL) {
        ret = TCL_OK;
        goto endloop;
    }
    hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
    while (hPtr != NULL) {
        zf = (ZipFile *) Tcl_GetHashValue(hPtr);
        if (zf->mntptlen == 0) {
            ZipEntry *z = zf->topents;
            while (z != NULL) {
                int lenz = strlen(z->name);
                if (
                    (len >= lenz) && (strncmp(path, z->name, lenz) == 0)
                ) {
                    ret = TCL_OK;
                    goto endloop;
                }
                z = z->tnext;
................................................................................
    if (z == NULL) {
        ZIPFS_ERROR(interp,"file not found");
        ret = TCL_ERROR;
        goto done;
    }
    switch (index) {
        case 0:
        *objPtrRef = Tcl_NewIntObj(z->nbyte);
        goto done;
        case 1:
        *objPtrRef= Tcl_NewIntObj(z->nbytecompr);
        goto done;
        case 2:
        *objPtrRef= Tcl_NewLongObj(z->offset);
        goto done;
        case 3:
        *objPtrRef= Tcl_NewStringObj(z->zipfile->mntpt, z->zipfile->mntptlen);
        goto done;
        case 4:
        *objPtrRef= Tcl_NewStringObj(z->zipfile->name, -1);
        goto done;
................................................................................
    /* Tcl_StaticPackage(interp, "zipfs", TclZipfs_Init, TclZipfs_Init); */
    if (!ZipFS.initialized) {
        TclZipfs_C_Init();
    }
    Unlock();
    if(interp != NULL) {
        static const EnsembleImplMap initMap[] = {
            {"mount",      ZipFSMountObjCmd,    NULL, NULL, NULL, 0},
            {"mount_data",      ZipFSMountBufferObjCmd,    NULL, NULL, NULL, 0},
            {"unmount",      ZipFSUnmountObjCmd,    NULL, NULL, NULL, 0},
            {"mkkey",      ZipFSMkKeyObjCmd,    NULL, NULL, NULL, 0},
            {"mkimg",      ZipFSMkImgObjCmd,    NULL, NULL, NULL, 0},
            {"mkzip",      ZipFSMkZipObjCmd,    NULL, NULL, NULL, 0},
            {"lmkimg",      ZipFSLMkImgObjCmd,    NULL, NULL, NULL, 0},
            {"lmkzip",      ZipFSLMkZipObjCmd,    NULL, NULL, NULL, 0},





            {"exists",      ZipFSExistsObjCmd,    NULL, NULL, NULL, 1},
            {"info",      ZipFSInfoObjCmd,    NULL, NULL, NULL, 1},
            {"list",      ZipFSListObjCmd,    NULL, NULL, NULL, 1},
            {"canonical", ZipFSCanonicalObjCmd, NULL, NULL, NULL, 1},
            {"root",      ZipFSRootObjCmd, NULL, NULL, NULL, 1},
            {"tcl_library",      ZipFSTclLibraryObjCmd,    NULL, NULL, NULL, 0},

................................................................................
            "   lappend result $file\n"
            "  }\n"
            " }\n"
            " return [lsort $result]\n"
            "}\n";
        Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL);
        Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,TCL_LINK_INT);
        TclMakeEnsemble(interp, "zipfs", initMap);
        Tcl_PkgProvide(interp, "zipfs", "2.0");
    }
    return TCL_OK;
#else
    ZIPFS_ERROR(interp,"no zlib available");
    return TCL_ERROR;
#endif
................................................................................
{
    /*
     * Tclkit_MainHook --
     * Performs the argument munging for the shell
     */
    char *archive;

    Tcl_FindExecutable(*argv[0]);
    archive=(char *)Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);
    /*
    ** Look for init.tcl in one of the locations mounted later in this function
    */
    if(!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) {
        int found;






|

|
|
|
|
|



|



|

|










|







 







|
|
|


|







 







|







 







|







 







|







 







>
>
>
>
>


|
>







 







|
|



|


|







 







|
>





<
<
<







 







|
>







 







>
|
>
|







 







|



|







 







|







 







|







 







|













|







 







|


|








|








>
|





|







 







|












|







 







|
>
>







 







|
<







 







>
|







 







|







 







|







 







|







 







|







 







|
|
|







 







<
>
>
>
>
>










<
<
<
<







 







|







 







|
>













|
>







 







|







 







|
>




|




|













|







 







|


|


|







 







<
<
<
<




>
>
>
>
>







 







|







 







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
....
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
....
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
....
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133



1134
1135
1136
1137
1138
1139
1140
....
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
....
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
....
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
....
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
....
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
....
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
....
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
....
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
....
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
....
2364
2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
....
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
....
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
....
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
....
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
....
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
....
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
....
2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915




2916
2917
2918
2919
2920
2921
2922
....
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
....
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
....
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
....
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
....
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
....
4319
4320
4321
4322
4323
4324
4325




4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
....
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
....
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
typedef struct ZipFile {
    char *name;               /* Archive name */
    size_t namelen;
    char is_membuf;           /* When true, not a file but a memory buffer */
    Tcl_Channel chan;         /* Channel handle or NULL */
    unsigned char *data;      /* Memory mapped or malloc'ed file */
    size_t length;            /* Length of memory mapped file */
    unsigned char *tofree;    /* Non-NULL if malloc'ed file */
    size_t nfiles;            /* Number of files in archive */
    size_t baseoffs;          /* Archive start */
    size_t baseoffsp;         /* Password start */
    size_t centoffs;          /* Archive directory start */
    unsigned char pwbuf[264]; /* Password buffer */
#if defined(_WIN32) || defined(_WIN64)
    HANDLE mh;
#endif
    size_t nopen;             /* Number of open files on archive */
    struct ZipEntry *entries; /* List of files in archive */
    struct ZipEntry *topents; /* List of top-level dirs in archive */
#if HAS_DRIVES
    int mntdrv;               /* Drive letter of mount point */
#endif
    size_t mntptlen;
    char *mntpt;              /* Mount point */
} ZipFile;

/*
 * In-core description of file contained in mounted ZIP archive.
 */

typedef struct ZipEntry {
    char *name;               /* The full pathname of the virtual file */
    ZipFile *zipfile;         /* The ZIP file holding this virtual file */
    Tcl_WideInt offset;       /* Data offset into memory mapped ZIP file */
    int nbyte;                /* Uncompressed size of the virtual file */
    int nbytecompr;           /* Compressed size of the virtual file */
    int cmeth;                /* Compress method */
    int isdir;                  /* Set to 1 if directory, or -1 if root */
    int depth;                   /* Number of slashes in path. */
    int crc32;                /* CRC-32 */
    int timestamp;            /* Modification time */
................................................................................
/*
 * File channel for file contained in mounted ZIP archive.
 */

typedef struct ZipChannel {
    ZipFile *zipfile;         /* The ZIP file holding this channel */
    ZipEntry *zipentry;       /* Pointer back to virtual file */
    size_t nmax;              /* Max. size for write */
    size_t nbyte;             /* Number of bytes of uncompressed data */
    size_t nread;             /* Pos of next byte to be read from the channel */
    unsigned char *ubuf;      /* Pointer to the uncompressed data */
    int iscompr;              /* True if data is compressed */
    int isdir;                /* Set to 1 if directory, or -1 if root */
    int isenc;                /* True if data is encrypted */
    int iswr;                 /* True if open for writing */
    unsigned long keys[3];    /* Key for decryption */
} ZipChannel;

/*
 * Global variables.
................................................................................
 *    The given ZipFile struct is filled with information about the ZIP archive file.
 *
 *-------------------------------------------------------------------------
 */
static int
ZipFS_Find_TOC(Tcl_Interp *interp, int needZip, ZipFile *zf)
{
    size_t i;
    unsigned char *p, *q;
    p = zf->data + zf->length - ZIP_CENTRAL_END_LEN;
    while (p >= zf->data) {
        if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
            if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) {
            break;
            }
................................................................................
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSOpenArchive(Tcl_Interp *interp, const char *zipname, int needZip, ZipFile *zf)
{
    size_t i;
    ClientData handle;
    zf->namelen=0;
    zf->is_membuf=0;
#if defined(_WIN32) || defined(_WIN64)
    zf->data = NULL;
    zf->mh = INVALID_HANDLE_VALUE;
#else
................................................................................
        if (Tcl_SetChannelOption(interp, zf->chan, "-translation", "binary") != TCL_OK) {
            goto error;
        }
        if (Tcl_SetChannelOption(interp, zf->chan, "-encoding", "binary") != TCL_OK) {
            goto error;
        }
        zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
        if ((zf->length - ZIP_CENTRAL_END_LEN) > (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
            ZIPFS_ERROR(interp,"illegal file size");
            goto error;
        }
        Tcl_Seek(zf->chan, 0, SEEK_SET);
        zf->tofree = zf->data = (unsigned char *) Tcl_AttemptAlloc(zf->length);
        if (zf->tofree == NULL) {
            ZIPFS_ERROR(interp,"out of memory")
................................................................................
            ZIPFS_ERROR(interp,"file read error");
            goto error;
        }
        Tcl_Close(interp, zf->chan);
        zf->chan = NULL;
    } else {
#if defined(_WIN32) || defined(_WIN64)
#   ifdef _WIN64
        i = GetFileSizeEx((HANDLE) handle, (PLARGE_INTEGER)&zf->length);
        if (
            (i == 0) ||
#   else
        zf->length = GetFileSize((HANDLE) handle, 0);
        if (
            (zf->length == (size_t)INVALID_FILE_SIZE) ||
#   endif
            (zf->length < ZIP_CENTRAL_END_LEN)
        ) {
            ZIPFS_ERROR(interp,"invalid file size");
            goto error;
        }
        zf->mh = CreateFileMapping((HANDLE) handle, 0, PAGE_READONLY, 0,
                       zf->length, 0);
................................................................................
        }
        zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length);
        if (zf->data == NULL) {
            ZIPFS_ERROR(interp,"file mapping failed");
            goto error;
        }
#else
        zf->length = lseek(PTR2INT(handle), 0, SEEK_END);
        if ((zf->length == (size_t)-1) || (zf->length < ZIP_CENTRAL_END_LEN)) {
            ZIPFS_ERROR(interp,"invalid file size");
            goto error;
        }
        lseek(PTR2INT(handle), 0, SEEK_SET);
        zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ,
                          MAP_FILE | MAP_PRIVATE,
						  PTR2INT(handle), 0);
        if (zf->data == MAP_FAILED) {
            ZIPFS_ERROR(interp,"file mapping failed");
            goto error;
        }
#endif
    }
    return ZipFS_Find_TOC(interp,needZip,zf);
................................................................................
 * Side effects:
 *-------------------------------------------------------------------------
 */

static int
ZipFS_Catalogue_Filesystem(Tcl_Interp *interp, ZipFile *zf0, const char *mntpt, const char *passwd, const char *zipname)
{
    int pwlen, isNew;
    size_t i;
    ZipFile *zf;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_DString ds, dsm, fpBuf;
    unsigned char *q;



    WriteLock();

    pwlen = 0;
    if (passwd != NULL) {
        pwlen = strlen(passwd);
        if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) {
            if (interp) {
................................................................................
            z->next = zf->entries;
            zf->entries = z;
        }
    }
    q = zf->data + zf->centoffs;
    Tcl_DStringInit(&fpBuf);
    for (i = 0; i < zf->nfiles; i++) {
        int extra, isdir = 0, dosTime, dosDate, nbcompr;
        size_t offs, pathlen, comlen;
        unsigned char *lq, *gq = NULL;
        char *fullpath, *path;

        pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS);
        comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
        extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS);
        Tcl_DStringSetLength(&ds, 0);
................................................................................
    char *buf, int bufsize, Tcl_HashTable *fileHash
) {
    Tcl_Channel in;
    Tcl_HashEntry *hPtr;
    ZipEntry *z;
    z_stream stream;
    const char *zpath;
    int crc, flush, zpathlen, olen;
    size_t nbyte, nbytecompr, len, align = 0;
    Tcl_WideInt pos[3];
    int mtime = 0, isNew, cmeth;
    unsigned long keys[3], keys0[3];
    char obuf[4096];

    zpath = name;
    while (zpath != NULL && zpath[0] == '/') {
        zpath++;
    }
................................................................................
            mtime = statBuf.st_mtime;
        }
        Tcl_DecrRefCount(pathObj);
    }
    Tcl_ResetResult(interp);
    crc = 0;
    nbyte = nbytecompr = 0;
    while ((len = Tcl_Read(in, buf, bufsize)) + 1 > 1) {
        crc = crc32(crc, (unsigned char *) buf, len);
        nbyte += len;
    }
    if (len == (size_t)-1) {
        if (nbyte == 0) {
            if (strcmp("illegal operation on a directory",
                   Tcl_PosixError(interp)) == 0) {
            Tcl_Close(interp, in);
            return TCL_OK;
            }
        }
................................................................................
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    pos[0] = Tcl_Tell(out);
    memset(buf, '\0', ZIP_LOCAL_HEADER_LEN);
    memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen);
    len = zpathlen + ZIP_LOCAL_HEADER_LEN;
    if ((size_t)Tcl_Write(out, buf, len) != len) {
wrerr:
    Tcl_AppendResult(interp, "write error", (char *) NULL);
    Tcl_Close(interp, in);
    return TCL_ERROR;
    }
    if ((len + pos[0]) & 3) {
        unsigned char abuf[8];
................................................................................
         * Align payload to next 4-byte boundary using a dummy extra
         * entry similar to the zipalign tool from Android's SDK.
         */
        align = 4 + ((len + pos[0]) & 3);
        zip_write_short(abuf, 0xffff);
        zip_write_short(abuf + 2, align - 4);
        zip_write_int(abuf + 4, 0x03020100);
        if ((size_t)Tcl_Write(out, (const char *)abuf, align) != align) {
            goto wrerr;
        }
    }
    if (passwd != NULL) {
        int i, ch, tmp;
        unsigned char kvbuf[24];
        Tcl_Obj *ret;
................................................................................
        Tcl_AppendResult(interp, "compression init error on \"", path, "\"",
                 (char *) NULL);
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    do {
    len = Tcl_Read(in, buf, bufsize);
    if (len == (size_t)-1) {
        Tcl_AppendResult(interp, "read error on \"", path, "\"",
                 (char *) NULL);
        deflateEnd(&stream);
        Tcl_Close(interp, in);
        return TCL_ERROR;
    }
    stream.avail_in = len;
    stream.next_in = (unsigned char *) buf;
    flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH;
    do {
        stream.avail_out = sizeof (obuf);
        stream.next_out = (unsigned char *) obuf;
        len = deflate(&stream, flush);
        if (len == (size_t)Z_STREAM_ERROR) {
            Tcl_AppendResult(interp, "deflate error on \"", path, "\"",
                     (char *) NULL);
            deflateEnd(&stream);
            Tcl_Close(interp, in);
            return TCL_ERROR;
        }
        olen = sizeof (obuf) - stream.avail_out;
................................................................................
    Tcl_Flush(out);
    pos[1] = Tcl_Tell(out);
    if (nbyte - nbytecompr <= 0) {
        /*
         * Compressed file larger than input,
         * write it again uncompressed.
         */
        if (Tcl_Seek(in, 0, SEEK_SET) != 0) {
            goto seekErr;
        }
        if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) {
seekErr:
            Tcl_Close(interp, in);
            Tcl_AppendResult(interp, "seek error", (char *) NULL);
            return TCL_ERROR;
        }
        nbytecompr = (passwd != NULL) ? 12 : 0;
        while (1) {
            len = Tcl_Read(in, buf, bufsize);
            if (len == (size_t)-1) {
            Tcl_AppendResult(interp, "read error on \"", path, "\"",
                     (char *) NULL);
            Tcl_Close(interp, in);
            return TCL_ERROR;
            } else if (len == 0) {
            break;
            }
            if (passwd != NULL) {
            size_t i;
            int tmp;

            for (i = 0; i < len; i++) {
                buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp);
            }
            }
            if ((size_t)Tcl_Write(out, buf, len) != len) {
            Tcl_AppendResult(interp, "write error", (char *) NULL);
            Tcl_Close(interp, in);
            return TCL_ERROR;
            }
            nbytecompr += len;
        }
        cmeth = ZIP_COMPMETH_STORED;
................................................................................
    zip_write_short(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp));
    zip_write_short(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp));
    zip_write_int(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
    zip_write_int(buf + ZIP_LOCAL_COMPLEN_OFFS, z->nbytecompr);
    zip_write_int(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->nbyte);
    zip_write_short(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen);
    zip_write_short(buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
    if (Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "seek error", (char *) NULL);
        return TCL_ERROR;
    }
    if (Tcl_Write(out, buf, ZIP_LOCAL_HEADER_LEN) != ZIP_LOCAL_HEADER_LEN) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "write error", (char *) NULL);
        return TCL_ERROR;
    }
    Tcl_Flush(out);
    if (Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) {
        Tcl_DeleteHashEntry(hPtr);
        Tcl_Free((char *) z);
        Tcl_AppendResult(interp, "seek error", (char *) NULL);
        return TCL_ERROR;
    }
    return TCL_OK;
}
................................................................................
 */

static int
ZipFSMkZipOrImgObjCmd(ClientData clientData, Tcl_Interp *interp,
                      int isImg, int isList, int objc, Tcl_Obj *const objv[])
{
    Tcl_Channel out;
    int pwlen = 0, count, ret = TCL_ERROR, lobjc;
    size_t len, slen = 0, i = 0;
    Tcl_WideInt pos[3];
    Tcl_Obj **lobjv, *list = NULL;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable fileHash;
    char *strip = NULL, *pw = NULL, pwbuf[264], buf[4096];

................................................................................
        }
        Unlock();
        if (!isMounted) {
            zf = &zf0;
        }
        if (isMounted ||
            (ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK)) {
            if ((size_t)Tcl_Write(out, (char *) zf->data, zf->baseoffsp) != zf->baseoffsp) {

                memset(pwbuf, 0, sizeof (pwbuf));
                Tcl_DecrRefCount(list);
                Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
                Tcl_Close(interp, out);
                if (zf == &zf0) {
                    ZipFSCloseArchive(interp, zf);
                } else {
................................................................................
                ZipFSCloseArchive(interp, zf);
            } else {
                WriteLock();
                zf->nopen--;
                Unlock();
            }
        } else {
            size_t k;
            int m, n;
            Tcl_Channel in;
            const char *errMsg = "seek error";

            /*
             * Fall back to read it as plain file which
             * hopefully is a static tclsh or wish binary
             * with proper zipfs infrastructure built in.
................................................................................
                Tcl_DecrRefCount(list);
                Tcl_Close(interp, out);
                return TCL_ERROR;
            }
            Tcl_SetChannelOption(interp, in, "-translation", "binary");
            Tcl_SetChannelOption(interp, in, "-encoding", "binary");
            i = Tcl_Seek(in, 0, SEEK_END);
            if (i == (size_t)-1) {
cperr:
                memset(pwbuf, 0, sizeof (pwbuf));
                Tcl_DecrRefCount(list);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
                Tcl_Close(interp, out);
                Tcl_Close(interp, in);
                return TCL_ERROR;
................................................................................
    }
    Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
    pos[0] = Tcl_Tell(out);
    if (!isList && (objc > 3)) {
        strip = Tcl_GetString(objv[3]);
        slen = strlen(strip);
    }
    for (i = 0; i < (size_t)lobjc; i += (isList ? 2 : 1)) {
        const char *path, *name;

        path = Tcl_GetString(lobjv[i]);
        if (isList) {
            name = Tcl_GetString(lobjv[i + 1]);
        } else {
            name = path;
................................................................................
        if (ZipAddFile(interp, path, name, out, pw, buf, sizeof (buf),
                       &fileHash) != TCL_OK) {
            goto done;
        }
    }
    pos[1] = Tcl_Tell(out);
    count = 0;
    for (i = 0; i < (size_t)lobjc; i += (isList ? 2 : 1)) {
        const char *path, *name;

        path = Tcl_GetString(lobjv[i]);
        if (isList) {
            name = Tcl_GetString(lobjv[i + 1]);
        } else {
            name = path;
................................................................................
        zip_write_short(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
        zip_write_short(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
        zip_write_short(buf + ZIP_CENTRAL_IATTR_OFFS, 0);
        zip_write_int(buf + ZIP_CENTRAL_EATTR_OFFS, 0);
        zip_write_int(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]);
        if (
            (Tcl_Write(out, buf, ZIP_CENTRAL_HEADER_LEN) != ZIP_CENTRAL_HEADER_LEN)
            || ((size_t)Tcl_Write(out, z->name, len) != len)
        ) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1));
            goto done;
        }
        count++;
    }
    Tcl_Flush(out);
................................................................................
    ReadLock();
    z = ZipFSLookup(filename);
    if (z != NULL) {
        Tcl_Obj *result = Tcl_GetObjResult(interp);

        Tcl_ListObjAppendElement(interp, result,
                     Tcl_NewStringObj(z->zipfile->name, -1));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->nbyte));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->nbytecompr));
        Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset));
    }
    Unlock();
    return TCL_OK;
}
 
/*
 *-------------------------------------------------------------------------
................................................................................

Tcl_Obj *TclZipfs_TclLibrary(void) {
    if(zipfs_literal_tcl_library) {
        return Tcl_NewStringObj(zipfs_literal_tcl_library,-1);
    } else {
        Tcl_Obj *vfsinitscript;
        int found=0;

#if defined(_WIN32) || defined(_WIN64)
        HMODULE hModule = TclWinGetTclInstance();
        WCHAR wName[MAX_PATH + LIBRARY_SIZE];
        char dllname[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX];
#endif
        /* Look for the library file system within the executable */
        vfsinitscript=Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",-1);
        Tcl_IncrRefCount(vfsinitscript);
        found=Tcl_FSAccess(vfsinitscript,F_OK);
        Tcl_DecrRefCount(vfsinitscript);
        if(found==TCL_OK) {
            zipfs_literal_tcl_library=ZIPFS_APP_MOUNT "/tcl_library";
            return Tcl_NewStringObj(zipfs_literal_tcl_library,-1);
        }
#if defined(_WIN32) || defined(_WIN64)




        if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
            GetModuleFileNameA(hModule, dllname, MAX_PATH);
        } else {
            ToUtf(wName, dllname);
        }
        /* Mount zip file and dll before releasing to search */
        if(TclZipfs_AppHook_FindTclInit(dllname)==TCL_OK) {
................................................................................
            }
            Tcl_Free((char *) info);
            ZIPFS_ERROR(interp,"decompression error");
            goto error;
        }
    }
wrapchan:
    sprintf(cname, "zipfs_%" TCL_LL_MODIFIER "x_%d", z->offset, ZipFS.idCount++);
    z->zipfile->nopen++;
    Unlock();
    return Tcl_CreateChannel(&ZipChannelType, cname, (ClientData) info, flags);

error:
    Unlock();
    return NULL;
................................................................................
Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result,
               Tcl_Obj *pathPtr, const char *pattern,
               Tcl_GlobTypeData *types)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *normPathPtr;
    int scnt, l, dirOnly = -1, prefixLen, strip = 0;
    size_t len;
    char *pat, *prefix, *path;
    Tcl_DString dsPref;

    if (!(normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1;

    if (types != NULL) {
        dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR;
    }

    /* the prefix that gets prepended to results */
    prefix = Tcl_GetStringFromObj(pathPtr, &prefixLen);

    /* the (normalized) path we're searching */
    path = Tcl_GetString(normPathPtr);
    len = normPathPtr->length;

    Tcl_DStringInit(&dsPref);
    Tcl_DStringAppend(&dsPref, prefix, prefixLen);

    if (strcmp(prefix, path) == 0) {
        prefix = NULL;
    } else {
................................................................................
    hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
    while (hPtr != NULL) {
        ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);

        if (zf->mntptlen == 0) {
            ZipEntry *z = zf->topents;
            while (z != NULL) {
                size_t lenz = strlen(z->name);
                if (
                    (lenz > len + 1)
                    && (strncmp(z->name, path, len) == 0)
                    && (z->name[len] == '/')
                    && (CountSlashes(z->name) == l)
                    && Tcl_StringCaseMatch(z->name + len + 1, pattern, 0)
                ) {
................................................................................

static int
Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    ZipFile *zf;
    int ret = -1;
    size_t len;
    char *path;

    if (!(pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr))) return -1;

    path = Tcl_GetString(pathPtr);
    if(strncmp(path,ZIPFS_VOLUME,ZIPFS_VOLUME_LEN)!=0) {
        return -1;
    }

    len = pathPtr->length;

    ReadLock();
    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
    if (hPtr != NULL) {
        ret = TCL_OK;
        goto endloop;
    }
    hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search);
    while (hPtr != NULL) {
        zf = (ZipFile *) Tcl_GetHashValue(hPtr);
        if (zf->mntptlen == 0) {
            ZipEntry *z = zf->topents;
            while (z != NULL) {
                size_t lenz = strlen(z->name);
                if (
                    (len >= lenz) && (strncmp(path, z->name, lenz) == 0)
                ) {
                    ret = TCL_OK;
                    goto endloop;
                }
                z = z->tnext;
................................................................................
    if (z == NULL) {
        ZIPFS_ERROR(interp,"file not found");
        ret = TCL_ERROR;
        goto done;
    }
    switch (index) {
        case 0:
        *objPtrRef = Tcl_NewWideIntObj(z->nbyte);
        goto done;
        case 1:
        *objPtrRef = Tcl_NewWideIntObj(z->nbytecompr);
        goto done;
        case 2:
        *objPtrRef= Tcl_NewWideIntObj(z->offset);
        goto done;
        case 3:
        *objPtrRef= Tcl_NewStringObj(z->zipfile->mntpt, z->zipfile->mntptlen);
        goto done;
        case 4:
        *objPtrRef= Tcl_NewStringObj(z->zipfile->name, -1);
        goto done;
................................................................................
    /* Tcl_StaticPackage(interp, "zipfs", TclZipfs_Init, TclZipfs_Init); */
    if (!ZipFS.initialized) {
        TclZipfs_C_Init();
    }
    Unlock();
    if(interp != NULL) {
        static const EnsembleImplMap initMap[] = {




            {"mkimg",      ZipFSMkImgObjCmd,    NULL, NULL, NULL, 0},
            {"mkzip",      ZipFSMkZipObjCmd,    NULL, NULL, NULL, 0},
            {"lmkimg",      ZipFSLMkImgObjCmd,    NULL, NULL, NULL, 0},
            {"lmkzip",      ZipFSLMkZipObjCmd,    NULL, NULL, NULL, 0},
            /* The 4 entries above are not available in safe interpreters */
            {"mount",      ZipFSMountObjCmd,    NULL, NULL, NULL, 0},
            {"mount_data",      ZipFSMountBufferObjCmd,    NULL, NULL, NULL, 0},
            {"unmount",      ZipFSUnmountObjCmd,    NULL, NULL, NULL, 0},
            {"mkkey",      ZipFSMkKeyObjCmd,    NULL, NULL, NULL, 0},
            {"exists",      ZipFSExistsObjCmd,    NULL, NULL, NULL, 1},
            {"info",      ZipFSInfoObjCmd,    NULL, NULL, NULL, 1},
            {"list",      ZipFSListObjCmd,    NULL, NULL, NULL, 1},
            {"canonical", ZipFSCanonicalObjCmd, NULL, NULL, NULL, 1},
            {"root",      ZipFSRootObjCmd, NULL, NULL, NULL, 1},
            {"tcl_library",      ZipFSTclLibraryObjCmd,    NULL, NULL, NULL, 0},

................................................................................
            "   lappend result $file\n"
            "  }\n"
            " }\n"
            " return [lsort $result]\n"
            "}\n";
        Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL);
        Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,TCL_LINK_INT);
        TclMakeEnsemble(interp, "zipfs", Tcl_IsSafe(interp) ? (initMap+4) : initMap);
        Tcl_PkgProvide(interp, "zipfs", "2.0");
    }
    return TCL_OK;
#else
    ZIPFS_ERROR(interp,"no zlib available");
    return TCL_ERROR;
#endif
................................................................................
{
    /*
     * Tclkit_MainHook --
     * Performs the argument munging for the shell
     */
    char *archive;

    Tcl_FindExecutable((*argv)[0]);
    archive=(char *)Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);
    /*
    ** Look for init.tcl in one of the locations mounted later in this function
    */
    if(!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) {
        int found;

Added tools/empty.zip.

cannot compute difference between binary files

Changes to unix/Makefile.in.

708
709
710
711
712
713
714

715
716
717
718
719
720
721
# This targets actually build the objects needed for the lib in the above case
objs: ${OBJS}

${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE}
	${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} \
		@[email protected] ${TCL_STUB_LIB_FILE} ${LIBS} @[email protected] \
		${CC_SEARCH_FLAGS} -o ${TCL_EXE}


# Must be empty so it doesn't conflict with rule for ${TCL_EXE} above
${NATIVE_TCLSH}:

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in






>







708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# This targets actually build the objects needed for the lib in the above case
objs: ${OBJS}

${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE}
	${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} \
		@[email protected] ${TCL_STUB_LIB_FILE} ${LIBS} @[email protected] \
		${CC_SEARCH_FLAGS} -o ${TCL_EXE}
		cat ${TOOL_DIR}/empty.zip >> ${TCL_EXE}

# Must be empty so it doesn't conflict with rule for ${TCL_EXE} above
${NATIVE_TCLSH}:

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in

Changes to win/Makefile.in.

488
489
490
491
492
493
494

495
496
497
498
499
500
501
	$(COPY) -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}
	cd  ${TCL_VFS_ROOT} ; ${NATIVE_ZIP} ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH}

$(TCLSH): $(TCLSH_OBJS) @[email protected] $(TCL_STUB_LIB_FILE) tclsh.$(RES)
	$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
	tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	@[email protected]


cat32.$(OBJEXT): cat.c
	$(CC) -c $(CC_SWITCHES) @[email protected] $(CC_OBJNAME)

$(CAT32): cat32.$(OBJEXT)
	$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)







>







488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
	$(COPY) -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}
	cd  ${TCL_VFS_ROOT} ; ${NATIVE_ZIP} ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH}

$(TCLSH): $(TCLSH_OBJS) @[email protected] $(TCL_STUB_LIB_FILE) tclsh.$(RES)
	$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
	tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	@[email protected]
	cat ${TOOL_DIR}/empty.zip >> ${TCLSH}

cat32.$(OBJEXT): cat.c
	$(CC) -c $(CC_SWITCHES) @[email protected] $(CC_OBJNAME)

$(CAT32): cat32.$(OBJEXT)
	$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)