1 //
2 /**************************************************************************************************
3 * IOWOW library
4 *
5 * MIT License
6 *
7 * Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *************************************************************************************************/
27
28
29 #include "log/iwlog.h"
30 #include "platform/iwp.h"
31 #include "utils/iwutils.h"
32 #include "utils/iwuuid.h"
33 #include <stdio.h>
34
35 #if (defined(_WIN32) || defined(__WIN32__))
36 #include <direct.h>
37 #endif
38
39 unsigned int iwcpuflags = 0;
40 static iwrc _iwp_init_impl(void);
41
42 #if defined(__linux) || defined(__unix) || defined(__APPLE__)
43 #include "unix/unix.c"
44 #elif defined(_WIN32)
45 #include "win32/win32.c"
46 #else
47 #error Unsupported platform
48 #endif
49
50 // Thanks to https://attractivechaos.wordpress.com/2017/09/04/on-cpu-dispatch
x86_simd(void)51 static unsigned int x86_simd(void) {
52
53 #if defined(__i386__) || defined(__amd64__)
54 unsigned int eax, ebx, ecx, edx, flag = 0;
55 # ifdef _MSC_VER
56 int cpuid[4];
57 __cpuid(cpuid, 1);
58 eax = cpuid[0], ebx = cpuid[1], ecx = cpuid[2], edx = cpuid[3];
59 # else
60 __asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
61 # endif
62 if (edx >> 25 & 1) flag |= IWCPU_SSE;
63 if (edx >> 26 & 1) flag |= IWCPU_SSE2;
64 if (ecx >> 0 & 1) flag |= IWCPU_SSE3;
65 if (ecx >> 19 & 1) flag |= IWCPU_SSE4_1;
66 if (ecx >> 20 & 1) flag |= IWCPU_SSE4_2;
67 if (ecx >> 28 & 1) flag |= IWCPU_AVX;
68 if (ebx >> 5 & 1) flag |= IWCPU_AVX2;
69 if (ebx >> 16 & 1) flag |= IWCPU_AVX512F;
70 return flag;
71 #else
72 return 0;
73 #endif
74 }
75
iwp_copy_bytes(HANDLE fh,off_t off,size_t siz,off_t noff)76 iwrc iwp_copy_bytes(HANDLE fh, off_t off, size_t siz, off_t noff) {
77 if (INVALIDHANDLE(fh)) {
78 return IW_ERROR_INVALID_HANDLE;
79 }
80 int overlap = IW_RANGES_OVERLAP(off, off + siz, noff, noff + siz);
81 size_t sp, sp2;
82 iwrc rc = 0;
83 off_t pos = 0;
84 uint8_t buf[4096];
85 if (overlap && noff > off) {
86 // todo resolve it!!
87 return IW_ERROR_OVERFLOW;
88 }
89 #if !defined(__APPLE__) && !defined(_WIN32)
90 if (siz > sizeof(buf)) {
91 posix_fadvise(fh, off, siz, POSIX_FADV_SEQUENTIAL);
92 }
93 #endif
94 while (pos < siz) {
95 rc = iwp_pread(fh, off + pos, buf, MIN(sizeof(buf), (siz - pos)), &sp);
96 if (rc || !sp) {
97 break;
98 } else {
99 rc = iwp_pwrite(fh, noff + pos, buf, sp, &sp2);
100 pos += sp;
101 if (rc) {
102 break;
103 }
104 if (sp != sp2) {
105 rc = IW_ERROR_INVALID_STATE;
106 break;
107 }
108 }
109 }
110 #if !defined(__APPLE__) && !defined(_WIN32)
111 if (siz > sizeof(buf)) {
112 posix_fadvise(fh, off, siz, POSIX_FADV_NORMAL);
113 }
114 #endif
115 return rc;
116 }
117
iwp_allocate_tmpfile_path(const char * prefix)118 char *iwp_allocate_tmpfile_path(const char *prefix) {
119 size_t plen = prefix ? strlen(prefix) : 0;
120 char tmpdir[PATH_MAX + 1];
121 size_t tlen = iwp_tmpdir(tmpdir, sizeof(tmpdir));
122 if (!tlen) return 0;
123 char *res = malloc(tlen + sizeof(IW_PATH_STR) - 1 + plen + IW_UUID_STR_LEN + 1 /*NULL*/);
124 if (!res) return 0;
125 char *wp = res;
126 memcpy(wp, tmpdir, tlen);
127 wp += tlen;
128 memcpy(wp, IW_PATH_STR, sizeof(IW_PATH_STR) - 1);
129 wp += sizeof(IW_PATH_STR) - 1;
130 if (plen && prefix) {
131 memcpy(wp, prefix, plen);
132 wp += plen;
133 }
134 iwu_uuid4_fill(wp);
135 wp += IW_UUID_STR_LEN;
136 *wp = 0;
137 return res;
138 }
139
iwp_mkdirs(const char * path)140 iwrc iwp_mkdirs(const char *path) {
141 /* Adapted from http://stackoverflow.com/a/2336245/119527 */
142 const size_t len = strlen(path);
143 char _path[PATH_MAX];
144 char *p;
145
146 errno = 0;
147 /* Copy string so its mutable */
148 if (len > sizeof(_path) - 1) {
149 errno = ENAMETOOLONG;
150 return iwrc_set_errno(IW_ERROR_ERRNO, errno);
151 }
152 strcpy(_path, path);
153
154 /* Iterate the string */
155 for (p = _path + 1; *p; p++) {
156 if (*p == '/') {
157 /* Temporarily truncate */
158 *p = '\0';
159 #if (defined(_WIN32) || defined(__WIN32__))
160 if (_mkdir(_path) != 0) {
161 #else
162 if (mkdir(_path, S_IRWXU) != 0) {
163 #endif
164 if (errno != EEXIST) {
165 return iwrc_set_errno(IW_ERROR_ERRNO, errno);
166 }
167 }
168 *p = '/';
169 }
170 }
171 #if (defined(_WIN32) || defined(__WIN32__))
172 if (_mkdir(_path) != 0) {
173 #else
174 if (mkdir(_path, S_IRWXU) != 0) {
175 #endif
176 if (errno != EEXIST) {
177 return iwrc_set_errno(IW_ERROR_ERRNO, errno);
178 }
179 }
180 return 0;
181 }
182
183 iwrc iwp_init(void) {
184 iwcpuflags = x86_simd();
185 _iwp_init_impl();
186 return 0;
187 }
188