kmadej_fast_excel_fork 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.travis.yml +28 -0
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +70 -0
  7. data/Makefile +14 -0
  8. data/README.md +95 -0
  9. data/Rakefile +24 -0
  10. data/appveyor.yml +25 -0
  11. data/benchmarks/1k_rows.rb +59 -0
  12. data/benchmarks/20k_rows.rb +26 -0
  13. data/benchmarks/init.rb +59 -0
  14. data/benchmarks/memory.rb +49 -0
  15. data/examples/example.rb +42 -0
  16. data/examples/example_align.rb +23 -0
  17. data/examples/example_chart.rb +21 -0
  18. data/examples/example_colors.rb +37 -0
  19. data/examples/example_formula.rb +18 -0
  20. data/examples/example_image.rb +13 -0
  21. data/examples/example_styles.rb +27 -0
  22. data/examples/logo.png +0 -0
  23. data/extconf.rb +0 -0
  24. data/fast_excel.gemspec +20 -0
  25. data/lib/fast_excel.rb +600 -0
  26. data/lib/fast_excel/binding.rb +2819 -0
  27. data/lib/fast_excel/binding/chart.rb +2666 -0
  28. data/lib/fast_excel/binding/format.rb +1177 -0
  29. data/lib/fast_excel/binding/workbook.rb +338 -0
  30. data/lib/fast_excel/binding/worksheet.rb +1555 -0
  31. data/libxlsxwriter/.gitignore +49 -0
  32. data/libxlsxwriter/.indent.pro +125 -0
  33. data/libxlsxwriter/.travis.yml +25 -0
  34. data/libxlsxwriter/CONTRIBUTING.md +226 -0
  35. data/libxlsxwriter/Changes.txt +557 -0
  36. data/libxlsxwriter/LICENSE.txt +89 -0
  37. data/libxlsxwriter/Makefile +156 -0
  38. data/libxlsxwriter/Readme.md +78 -0
  39. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +30 -0
  40. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +7 -0
  41. data/libxlsxwriter/include/xlsxwriter.h +23 -0
  42. data/libxlsxwriter/include/xlsxwriter/app.h +79 -0
  43. data/libxlsxwriter/include/xlsxwriter/chart.h +3476 -0
  44. data/libxlsxwriter/include/xlsxwriter/common.h +372 -0
  45. data/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
  46. data/libxlsxwriter/include/xlsxwriter/core.h +51 -0
  47. data/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
  48. data/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
  49. data/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
  50. data/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
  51. data/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
  52. data/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
  53. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
  54. data/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
  55. data/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
  56. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +214 -0
  57. data/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
  58. data/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
  59. data/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
  60. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
  61. data/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
  62. data/libxlsxwriter/include/xlsxwriter/workbook.h +757 -0
  63. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
  64. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
  65. data/libxlsxwriter/lib/.gitignore +0 -0
  66. data/libxlsxwriter/libxlsxwriter.podspec +47 -0
  67. data/libxlsxwriter/src/Makefile +130 -0
  68. data/libxlsxwriter/src/app.c +443 -0
  69. data/libxlsxwriter/src/chart.c +6346 -0
  70. data/libxlsxwriter/src/content_types.c +345 -0
  71. data/libxlsxwriter/src/core.c +293 -0
  72. data/libxlsxwriter/src/custom.c +224 -0
  73. data/libxlsxwriter/src/drawing.c +746 -0
  74. data/libxlsxwriter/src/format.c +729 -0
  75. data/libxlsxwriter/src/hash_table.c +223 -0
  76. data/libxlsxwriter/src/packager.c +948 -0
  77. data/libxlsxwriter/src/relationships.c +245 -0
  78. data/libxlsxwriter/src/shared_strings.c +266 -0
  79. data/libxlsxwriter/src/styles.c +1088 -0
  80. data/libxlsxwriter/src/theme.c +348 -0
  81. data/libxlsxwriter/src/utility.c +515 -0
  82. data/libxlsxwriter/src/workbook.c +1930 -0
  83. data/libxlsxwriter/src/worksheet.c +5022 -0
  84. data/libxlsxwriter/src/xmlwriter.c +355 -0
  85. data/libxlsxwriter/third_party/minizip/Makefile +44 -0
  86. data/libxlsxwriter/third_party/minizip/Makefile.am +45 -0
  87. data/libxlsxwriter/third_party/minizip/Makefile.orig +25 -0
  88. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +6 -0
  89. data/libxlsxwriter/third_party/minizip/MiniZip64_info.txt +74 -0
  90. data/libxlsxwriter/third_party/minizip/README.txt +5 -0
  91. data/libxlsxwriter/third_party/minizip/configure.ac +32 -0
  92. data/libxlsxwriter/third_party/minizip/crypt.h +131 -0
  93. data/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
  94. data/libxlsxwriter/third_party/minizip/ioapi.h +208 -0
  95. data/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
  96. data/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
  97. data/libxlsxwriter/third_party/minizip/make_vms.com +25 -0
  98. data/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
  99. data/libxlsxwriter/third_party/minizip/miniunzip.1 +63 -0
  100. data/libxlsxwriter/third_party/minizip/minizip.1 +46 -0
  101. data/libxlsxwriter/third_party/minizip/minizip.c +520 -0
  102. data/libxlsxwriter/third_party/minizip/minizip.pc.in +12 -0
  103. data/libxlsxwriter/third_party/minizip/mztools.c +291 -0
  104. data/libxlsxwriter/third_party/minizip/mztools.h +37 -0
  105. data/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
  106. data/libxlsxwriter/third_party/minizip/unzip.h +437 -0
  107. data/libxlsxwriter/third_party/minizip/zip.c +2007 -0
  108. data/libxlsxwriter/third_party/minizip/zip.h +367 -0
  109. data/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
  110. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
  111. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
  112. data/libxlsxwriter/version.txt +1 -0
  113. data/test/date_test.rb +22 -0
  114. data/test/default_format_test.rb +19 -0
  115. data/test/format_test.rb +171 -0
  116. data/test/test_helper.rb +52 -0
  117. data/test/tmpfile_test.rb +23 -0
  118. data/test/worksheet_test.rb +86 -0
  119. metadata +182 -0
@@ -0,0 +1,367 @@
1
+ /* zip.h -- IO on .zip files using zlib
2
+ Version 1.1, February 14h, 2010
3
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4
+
5
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6
+
7
+ Modifications for Zip64 support
8
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9
+
10
+ For more info read MiniZip_info.txt
11
+
12
+ ---------------------------------------------------------------------------
13
+
14
+ Condition of use and distribution are the same than zlib :
15
+
16
+ This software is provided 'as-is', without any express or implied
17
+ warranty. In no event will the authors be held liable for any damages
18
+ arising from the use of this software.
19
+
20
+ Permission is granted to anyone to use this software for any purpose,
21
+ including commercial applications, and to alter it and redistribute it
22
+ freely, subject to the following restrictions:
23
+
24
+ 1. The origin of this software must not be misrepresented; you must not
25
+ claim that you wrote the original software. If you use this software
26
+ in a product, an acknowledgment in the product documentation would be
27
+ appreciated but is not required.
28
+ 2. Altered source versions must be plainly marked as such, and must not be
29
+ misrepresented as being the original software.
30
+ 3. This notice may not be removed or altered from any source distribution.
31
+
32
+ ---------------------------------------------------------------------------
33
+
34
+ Changes
35
+
36
+ See header of zip.h
37
+
38
+ */
39
+
40
+ /* Pragma added by libxlsxwriter project to avoid warnings with -pedantic -ansi. */
41
+ #ifndef _WIN32
42
+ #pragma GCC system_header
43
+ #endif
44
+
45
+ #ifndef _zip12_H
46
+ #define _zip12_H
47
+
48
+ #ifdef __cplusplus
49
+ extern "C" {
50
+ #endif
51
+
52
+ /* #define HAVE_BZIP2 */
53
+
54
+ #ifndef _ZLIB_H
55
+ #include "zlib.h"
56
+ #endif
57
+
58
+ #ifndef _ZLIBIOAPI_H
59
+ #include "ioapi.h"
60
+ #endif
61
+
62
+ #ifdef HAVE_BZIP2
63
+ #include "bzlib.h"
64
+ #endif
65
+
66
+ #define Z_BZIP2ED 12
67
+
68
+ #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
69
+ /* like the STRICT of WIN32, we define a pointer that cannot be converted
70
+ from (void*) without cast */
71
+ typedef struct TagzipFile__ { int unused; } zipFile__;
72
+ typedef zipFile__ *zipFile;
73
+ #else
74
+ typedef voidp zipFile;
75
+ #endif
76
+
77
+ #define ZIP_OK (0)
78
+ #define ZIP_EOF (0)
79
+ #define ZIP_ERRNO (Z_ERRNO)
80
+ #define ZIP_PARAMERROR (-102)
81
+ #define ZIP_BADZIPFILE (-103)
82
+ #define ZIP_INTERNALERROR (-104)
83
+
84
+ #ifndef DEF_MEM_LEVEL
85
+ # if MAX_MEM_LEVEL >= 8
86
+ # define DEF_MEM_LEVEL 8
87
+ # else
88
+ # define DEF_MEM_LEVEL MAX_MEM_LEVEL
89
+ # endif
90
+ #endif
91
+ /* default memLevel */
92
+
93
+ /* tm_zip contain date/time info */
94
+ typedef struct tm_zip_s
95
+ {
96
+ uInt tm_sec; /* seconds after the minute - [0,59] */
97
+ uInt tm_min; /* minutes after the hour - [0,59] */
98
+ uInt tm_hour; /* hours since midnight - [0,23] */
99
+ uInt tm_mday; /* day of the month - [1,31] */
100
+ uInt tm_mon; /* months since January - [0,11] */
101
+ uInt tm_year; /* years - [1980..2044] */
102
+ } tm_zip;
103
+
104
+ typedef struct
105
+ {
106
+ tm_zip tmz_date; /* date in understandable format */
107
+ uLong dosDate; /* if dos_date == 0, tmu_date is used */
108
+ /* uLong flag; */ /* general purpose bit flag 2 bytes */
109
+
110
+ uLong internal_fa; /* internal file attributes 2 bytes */
111
+ uLong external_fa; /* external file attributes 4 bytes */
112
+ } zip_fileinfo;
113
+
114
+ typedef const char* zipcharpc;
115
+
116
+
117
+ #define APPEND_STATUS_CREATE (0)
118
+ #define APPEND_STATUS_CREATEAFTER (1)
119
+ #define APPEND_STATUS_ADDINZIP (2)
120
+
121
+ extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
122
+ extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
123
+ /*
124
+ Create a zipfile.
125
+ pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
126
+ an Unix computer "zlib/zlib113.zip".
127
+ if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
128
+ will be created at the end of the file.
129
+ (useful if the file contain a self extractor code)
130
+ if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
131
+ add files in existing zip (be sure you don't add file that doesn't exist)
132
+ If the zipfile cannot be opened, the return value is NULL.
133
+ Else, the return value is a zipFile Handle, usable with other function
134
+ of this zip package.
135
+ */
136
+
137
+ /* Note : there is no delete function into a zipfile.
138
+ If you want delete file into a zipfile, you must open a zipfile, and create another
139
+ Of couse, you can use RAW reading and writing to copy the file you did not want delte
140
+ */
141
+
142
+ extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
143
+ int append,
144
+ zipcharpc* globalcomment,
145
+ zlib_filefunc_def* pzlib_filefunc_def));
146
+
147
+ extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
148
+ int append,
149
+ zipcharpc* globalcomment,
150
+ zlib_filefunc64_def* pzlib_filefunc_def));
151
+
152
+ extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
153
+ const char* filename,
154
+ const zip_fileinfo* zipfi,
155
+ const void* extrafield_local,
156
+ uInt size_extrafield_local,
157
+ const void* extrafield_global,
158
+ uInt size_extrafield_global,
159
+ const char* comment,
160
+ int method,
161
+ int level));
162
+
163
+ extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
164
+ const char* filename,
165
+ const zip_fileinfo* zipfi,
166
+ const void* extrafield_local,
167
+ uInt size_extrafield_local,
168
+ const void* extrafield_global,
169
+ uInt size_extrafield_global,
170
+ const char* comment,
171
+ int method,
172
+ int level,
173
+ int zip64));
174
+
175
+ /*
176
+ Open a file in the ZIP for writing.
177
+ filename : the filename in zip (if NULL, '-' without quote will be used
178
+ *zipfi contain supplemental information
179
+ if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
180
+ contains the extrafield data the the local header
181
+ if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
182
+ contains the extrafield data the the local header
183
+ if comment != NULL, comment contain the comment string
184
+ method contain the compression method (0 for store, Z_DEFLATED for deflate)
185
+ level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
186
+ zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
187
+ this MUST be '1' if the uncompressed size is >= 0xffffffff.
188
+
189
+ */
190
+
191
+
192
+ extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
193
+ const char* filename,
194
+ const zip_fileinfo* zipfi,
195
+ const void* extrafield_local,
196
+ uInt size_extrafield_local,
197
+ const void* extrafield_global,
198
+ uInt size_extrafield_global,
199
+ const char* comment,
200
+ int method,
201
+ int level,
202
+ int raw));
203
+
204
+
205
+ extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
206
+ const char* filename,
207
+ const zip_fileinfo* zipfi,
208
+ const void* extrafield_local,
209
+ uInt size_extrafield_local,
210
+ const void* extrafield_global,
211
+ uInt size_extrafield_global,
212
+ const char* comment,
213
+ int method,
214
+ int level,
215
+ int raw,
216
+ int zip64));
217
+ /*
218
+ Same than zipOpenNewFileInZip, except if raw=1, we write raw file
219
+ */
220
+
221
+ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
222
+ const char* filename,
223
+ const zip_fileinfo* zipfi,
224
+ const void* extrafield_local,
225
+ uInt size_extrafield_local,
226
+ const void* extrafield_global,
227
+ uInt size_extrafield_global,
228
+ const char* comment,
229
+ int method,
230
+ int level,
231
+ int raw,
232
+ int windowBits,
233
+ int memLevel,
234
+ int strategy,
235
+ const char* password,
236
+ uLong crcForCrypting));
237
+
238
+ extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
239
+ const char* filename,
240
+ const zip_fileinfo* zipfi,
241
+ const void* extrafield_local,
242
+ uInt size_extrafield_local,
243
+ const void* extrafield_global,
244
+ uInt size_extrafield_global,
245
+ const char* comment,
246
+ int method,
247
+ int level,
248
+ int raw,
249
+ int windowBits,
250
+ int memLevel,
251
+ int strategy,
252
+ const char* password,
253
+ uLong crcForCrypting,
254
+ int zip64
255
+ ));
256
+
257
+ /*
258
+ Same than zipOpenNewFileInZip2, except
259
+ windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
260
+ password : crypting password (NULL for no crypting)
261
+ crcForCrypting : crc of file to compress (needed for crypting)
262
+ */
263
+
264
+ extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
265
+ const char* filename,
266
+ const zip_fileinfo* zipfi,
267
+ const void* extrafield_local,
268
+ uInt size_extrafield_local,
269
+ const void* extrafield_global,
270
+ uInt size_extrafield_global,
271
+ const char* comment,
272
+ int method,
273
+ int level,
274
+ int raw,
275
+ int windowBits,
276
+ int memLevel,
277
+ int strategy,
278
+ const char* password,
279
+ uLong crcForCrypting,
280
+ uLong versionMadeBy,
281
+ uLong flagBase
282
+ ));
283
+
284
+
285
+ extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
286
+ const char* filename,
287
+ const zip_fileinfo* zipfi,
288
+ const void* extrafield_local,
289
+ uInt size_extrafield_local,
290
+ const void* extrafield_global,
291
+ uInt size_extrafield_global,
292
+ const char* comment,
293
+ int method,
294
+ int level,
295
+ int raw,
296
+ int windowBits,
297
+ int memLevel,
298
+ int strategy,
299
+ const char* password,
300
+ uLong crcForCrypting,
301
+ uLong versionMadeBy,
302
+ uLong flagBase,
303
+ int zip64
304
+ ));
305
+ /*
306
+ Same than zipOpenNewFileInZip4, except
307
+ versionMadeBy : value for Version made by field
308
+ flag : value for flag field (compression level info will be added)
309
+ */
310
+
311
+
312
+ extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
313
+ const void* buf,
314
+ unsigned len));
315
+ /*
316
+ Write data in the zipfile
317
+ */
318
+
319
+ extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
320
+ /*
321
+ Close the current file in the zipfile
322
+ */
323
+
324
+ extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
325
+ uLong uncompressed_size,
326
+ uLong crc32));
327
+
328
+ extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
329
+ ZPOS64_T uncompressed_size,
330
+ uLong crc32));
331
+
332
+ /*
333
+ Close the current file in the zipfile, for file opened with
334
+ parameter raw=1 in zipOpenNewFileInZip2
335
+ uncompressed_size and crc32 are value for the uncompressed size
336
+ */
337
+
338
+ extern int ZEXPORT zipClose OF((zipFile file,
339
+ const char* global_comment));
340
+ /*
341
+ Close the zipfile
342
+ */
343
+
344
+
345
+ extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
346
+ /*
347
+ zipRemoveExtraInfoBlock - Added by Mathias Svensson
348
+
349
+ Remove extra information block from a extra information data for the local file header or central directory header
350
+
351
+ It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
352
+
353
+ 0x0001 is the signature header for the ZIP64 extra information blocks
354
+
355
+ usage.
356
+ Remove ZIP64 Extra information from a central director extra field data
357
+ zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
358
+
359
+ Remove ZIP64 Extra information from a Local File Header extra field data
360
+ zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
361
+ */
362
+
363
+ #ifdef __cplusplus
364
+ }
365
+ #endif
366
+
367
+ #endif /* _zip64_H */
@@ -0,0 +1,42 @@
1
+ ###############################################################################
2
+ #
3
+ # Simplied Makefile to build tmpfileplus for the libxlsxwriter library.
4
+ #
5
+
6
+ # Keep the output quiet by default.
7
+ Q=@
8
+ ifdef V
9
+ Q=
10
+ endif
11
+
12
+ UNAME := $(shell uname)
13
+
14
+ # Check for MinGW/MinGW64/Cygwin environments.
15
+ ifneq (,$(findstring MINGW, $(UNAME)))
16
+ MING_LIKE = y
17
+ endif
18
+ ifneq (,$(findstring MSYS, $(UNAME)))
19
+ MING_LIKE = y
20
+ endif
21
+ ifneq (,$(findstring CYGWIN, $(UNAME)))
22
+ MING_LIKE = y
23
+ endif
24
+
25
+ FPIC = -fPIC
26
+
27
+ # Change make options on MinGW/MinGW64/Cygwin.
28
+ ifdef MING_LIKE
29
+ FPIC =
30
+ CC = gcc
31
+ endif
32
+
33
+ all: tmpfileplus.o tmpfileplus.so
34
+
35
+ %.o : %.c
36
+ $(Q)$(CC) -c $(CFLAGS) $<
37
+
38
+ %.so : %.c
39
+ $(Q)$(CC) $(FPIC) -c $(CFLAGS) $< -o $@
40
+
41
+ clean:
42
+ $(Q)/bin/rm -f *.o *.so
@@ -0,0 +1,342 @@
1
+ /* $Id: tmpfileplus.c $ */
2
+ /*
3
+ * $Date: 2016-06-01 03:31Z $
4
+ * $Revision: 2.0.0 $
5
+ * $Author: dai $
6
+ */
7
+
8
+ /*
9
+ * This Source Code Form is subject to the terms of the Mozilla Public
10
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
11
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12
+ *
13
+ * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
14
+ * <http://www.di-mgt.com.au/contact/>.
15
+ */
16
+
17
+
18
+ /*
19
+ * NAME
20
+ * tmpfileplus - create a unique temporary file
21
+ *
22
+ * SYNOPSIS
23
+ * FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep)
24
+ *
25
+ * DESCRIPTION
26
+ * The tmpfileplus() function opens a unique temporary file in binary
27
+ * read/write (w+b) mode. The file is opened with the O_EXCL flag,
28
+ * guaranteeing that the caller is the only user. The filename will consist
29
+ * of the string given by `prefix` followed by 10 random characters. If
30
+ * `prefix` is NULL, then the string "tmp." will be used instead. The file
31
+ * will be created in an appropriate directory chosen by the first
32
+ * successful attempt in the following sequence:
33
+ *
34
+ * a) The directory given by the `dir` argument (so the caller can specify
35
+ * a secure directory to take precedence).
36
+ *
37
+ * b) The directory name in the environment variables:
38
+ *
39
+ * (i) "TMP" [Windows only]
40
+ * (ii) "TEMP" [Windows only]
41
+ * (iii) "TMPDIR" [Unix only]
42
+ *
43
+ * c) `P_tmpdir` as defined in <stdio.h> [Unix only] (in Windows, this is
44
+ * usually "\", which is no good).
45
+ *
46
+ * d) The current working directory.
47
+ *
48
+ * If a file cannot be created in any of the above directories, then the
49
+ * function fails and NULL is returned.
50
+ *
51
+ * If the argument `pathname` is not a null pointer, then it will point to
52
+ * the full pathname of the file. The pathname is allocated using `malloc`
53
+ * and therefore should be freed by `free`.
54
+ *
55
+ * If `keep` is nonzero and `pathname` is not a null pointer, then the file
56
+ * will be kept after it is closed. Otherwise the file will be
57
+ * automatically deleted when it is closed or the program terminates.
58
+ *
59
+ *
60
+ * RETURN VALUE
61
+ * The tmpfileplus() function returns a pointer to the open file stream,
62
+ * or NULL if a unique file cannot be opened.
63
+ *
64
+ *
65
+ * ERRORS
66
+ * ENOMEM Not enough memory to allocate filename.
67
+ *
68
+ */
69
+
70
+ /* ADDED IN v2.0 */
71
+
72
+ /*
73
+ * NAME
74
+ * tmpfileplus_f - create a unique temporary file with filename stored in a fixed-length buffer
75
+ *
76
+ * SYNOPSIS
77
+ * FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep);
78
+ *
79
+ * DESCRIPTION
80
+ * Same as tmpfileplus() except receives filename in a fixed-length buffer. No allocated memory to free.
81
+
82
+ * ERRORS
83
+ * E2BIG Resulting filename is too big for the buffer `pathnamebuf`.
84
+
85
+ */
86
+
87
+ #include "tmpfileplus.h"
88
+
89
+ #include <stdio.h>
90
+ #include <stdlib.h>
91
+ #include <string.h>
92
+ #include <time.h>
93
+ #include <errno.h>
94
+
95
+ /* Non-ANSI include files that seem to work in both MSVC and Linux */
96
+ #include <sys/types.h>
97
+ #include <sys/stat.h>
98
+ #include <fcntl.h>
99
+
100
+ #ifdef _WIN32
101
+ #include <io.h>
102
+ #else
103
+ #include <unistd.h>
104
+ #endif
105
+
106
+ #ifdef _WIN32
107
+ /* MSVC nags to enforce ISO C++ conformant function names with leading "_",
108
+ * so we define our own function names to avoid whingeing compilers...
109
+ */
110
+ #define OPEN_ _open
111
+ #define FDOPEN_ _fdopen
112
+ #else
113
+ #define OPEN_ open
114
+ #define FDOPEN_ fdopen
115
+ #endif
116
+
117
+
118
+ /* DEBUGGING STUFF */
119
+ #if defined(_DEBUG) && defined(SHOW_DPRINTF)
120
+ #define DPRINTF1(s, a1) printf(s, a1)
121
+ #else
122
+ #define DPRINTF1(s, a1)
123
+ #endif
124
+
125
+
126
+ #ifdef _WIN32
127
+ #define FILE_SEPARATOR "\\"
128
+ #else
129
+ #define FILE_SEPARATOR "/"
130
+ #endif
131
+
132
+ #define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
133
+ #define NRANDCHARS (sizeof(RANDCHARS) - 1)
134
+
135
+ /** Replace each byte in string s with a random character from TEMPCHARS */
136
+ static char *set_randpart(char *s)
137
+ {
138
+ size_t i;
139
+ unsigned int r;
140
+ static unsigned int seed; /* NB static */
141
+
142
+ if (seed == 0)
143
+ { /* First time set our seed using current time and clock */
144
+ seed = ((unsigned)time(NULL)<<8) ^ (unsigned)clock();
145
+ }
146
+ srand(seed++);
147
+ for (i = 0; i < strlen(s); i++)
148
+ {
149
+ r = rand() % NRANDCHARS;
150
+ s[i] = (RANDCHARS)[r];
151
+ }
152
+ return s;
153
+ }
154
+
155
+ /** Return 1 if path is a valid directory otherwise 0 */
156
+ static int is_valid_dir(const char *path)
157
+ {
158
+ struct stat st;
159
+ if ((stat(path, &st) == 0) && (st.st_mode & S_IFDIR))
160
+ return 1;
161
+
162
+ return 0;
163
+ }
164
+
165
+ /** Call getenv and save a copy in buf */
166
+ static char *getenv_save(const char *varname, char *buf, size_t bufsize)
167
+ {
168
+ char *ptr = getenv(varname);
169
+ buf[0] = '\0';
170
+ if (ptr)
171
+ {
172
+ strncpy(buf, ptr, bufsize);
173
+ buf[bufsize-1] = '\0';
174
+ return buf;
175
+ }
176
+ return NULL;
177
+ }
178
+
179
+ /**
180
+ * Try and create a randomly-named file in directory `tmpdir`.
181
+ * If successful, allocate memory and set `tmpname_ptr` to full filepath, and return file pointer;
182
+ * otherwise return NULL.
183
+ * If `keep` is zero then create the file as temporary and it should not exist once closed.
184
+ */
185
+ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmpname_ptr, int keep)
186
+ /* PRE:
187
+ * pfx is not NULL and points to a valid null-terminated string
188
+ * tmpname_ptr is not NULL.
189
+ */
190
+ {
191
+ FILE *fp;
192
+ int fd;
193
+ char randpart[] = "1234567890";
194
+ size_t lentempname;
195
+ int i;
196
+ char *tmpname = NULL;
197
+ int oflag, pmode;
198
+
199
+ /* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed.
200
+ * In Unix, we use the unlink function after opening the file. (This does not work in Windows,
201
+ * which does not allow an open file to be unlinked.)
202
+ */
203
+ #ifdef _WIN32
204
+ /* MSVC flags */
205
+ oflag = _O_BINARY|_O_CREAT|_O_EXCL|_O_RDWR;
206
+ if (!keep)
207
+ oflag |= _O_TEMPORARY;
208
+ pmode = _S_IREAD | _S_IWRITE;
209
+ #else
210
+ /* Standard POSIX flags */
211
+ oflag = O_CREAT|O_EXCL|O_RDWR;
212
+ pmode = S_IRUSR|S_IWUSR;
213
+ #endif
214
+
215
+ if (!tmpdir || !is_valid_dir(tmpdir)) {
216
+ errno = ENOENT;
217
+ return NULL;
218
+ }
219
+
220
+ lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart);
221
+ DPRINTF1("lentempname=%d\n", lentempname);
222
+ tmpname = malloc(lentempname + 1);
223
+ if (!tmpname)
224
+ {
225
+ errno = ENOMEM;
226
+ return NULL;
227
+ }
228
+ /* If we don't manage to create a file after 10 goes, there is something wrong... */
229
+ for (i = 0; i < 10; i++)
230
+ {
231
+ sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart));
232
+ DPRINTF1("[%s]\n", tmpname);
233
+ fd = OPEN_(tmpname, oflag, pmode);
234
+ if (fd != -1) break;
235
+ }
236
+ DPRINTF1("strlen(tmpname)=%d\n", strlen(tmpname));
237
+ if (fd != -1)
238
+ { /* Success, so return user a proper ANSI C file pointer */
239
+ fp = FDOPEN_(fd, "w+b");
240
+ errno = 0;
241
+
242
+ #ifndef _WIN32
243
+ /* [Unix only] And make sure the file will be deleted once closed */
244
+ if (!keep) unlink(tmpname);
245
+ #endif
246
+
247
+ }
248
+ else
249
+ { /* We failed */
250
+ fp = NULL;
251
+ }
252
+ if (!fp)
253
+ {
254
+ free(tmpname);
255
+ tmpname = NULL;
256
+ }
257
+
258
+ *tmpname_ptr = tmpname;
259
+ return fp;
260
+ }
261
+
262
+ /**********************/
263
+ /* EXPORTED FUNCTIONS */
264
+ /**********************/
265
+
266
+ FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep)
267
+ {
268
+ FILE *fp = NULL;
269
+ char *tmpname = NULL;
270
+ char *tmpdir = NULL;
271
+ const char *pfx = (prefix ? prefix : "tmp.");
272
+ char *tempdirs[12] = { 0 };
273
+ #ifdef _WIN32
274
+ char env1[FILENAME_MAX+1] = { 0 };
275
+ char env2[FILENAME_MAX+1] = { 0 };
276
+ #else
277
+ char env3[FILENAME_MAX+1] = { 0 };
278
+ #endif
279
+ int ntempdirs = 0;
280
+ int i;
281
+
282
+ /* Set up a list of temp directories we will try in order */
283
+ i = 0;
284
+ tempdirs[i++] = (char *)dir;
285
+ #ifdef _WIN32
286
+ tempdirs[i++] = getenv_save("TMP", env1, sizeof(env1));
287
+ tempdirs[i++] = getenv_save("TEMP", env2, sizeof(env2));
288
+ #else
289
+ tempdirs[i++] = getenv_save("TMPDIR", env3, sizeof(env3));
290
+ tempdirs[i++] = P_tmpdir;
291
+ #endif
292
+ tempdirs[i++] = ".";
293
+ ntempdirs = i;
294
+
295
+ errno = 0;
296
+
297
+ /* Work through list we set up before, and break once we are successful */
298
+ for (i = 0; i < ntempdirs; i++)
299
+ {
300
+ tmpdir = tempdirs[i];
301
+ DPRINTF1("Trying tmpdir=[%s]\n", tmpdir);
302
+ fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep);
303
+ if (fp) break;
304
+ }
305
+ /* If we succeeded and the user passed a pointer, set it to the alloc'd pathname: the user must free this */
306
+ if (fp && pathname)
307
+ *pathname = tmpname;
308
+ else /* Otherwise, free the alloc'd memory */
309
+ free(tmpname);
310
+
311
+ return fp;
312
+ }
313
+
314
+ /* Same as tmpfileplus() but with fixed length buffer for output filename and no memory allocation */
315
+ FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep)
316
+ {
317
+ char *tmpbuf = NULL;
318
+ FILE *fp;
319
+
320
+ /* If no buffer provided, do the normal way */
321
+ if (!pathnamebuf || (int)pathsize <= 0) {
322
+ return tmpfileplus(dir, prefix, NULL, keep);
323
+ }
324
+ /* Call with a temporary buffer */
325
+ fp = tmpfileplus(dir, prefix, &tmpbuf, keep);
326
+ if (fp && strlen(tmpbuf) > pathsize - 1) {
327
+ /* Succeeded but not enough room in output buffer, so clean up and return an error */
328
+ pathnamebuf[0] = 0;
329
+ fclose(fp);
330
+ if (keep) remove(tmpbuf);
331
+ free(tmpbuf);
332
+ errno = E2BIG;
333
+ return NULL;
334
+ }
335
+ /* Copy name into buffer */
336
+ strcpy(pathnamebuf, tmpbuf);
337
+ free(tmpbuf);
338
+
339
+ return fp;
340
+ }
341
+
342
+