• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3625

26 Feb 2025 10:19AM UTC coverage: 63.633% (+0.1%) from 63.485%
#3625

push

travis-ci

web-flow
Merge pull request #29914 from taosdata/feat/TS-5613-3.0

feat:[TS-5613]support bool in cast

148738 of 299799 branches covered (49.61%)

Branch coverage included in aggregate %.

233124 of 300297 relevant lines covered (77.63%)

17654074.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.07
/source/os/src/osFile.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15
#define ALLOW_FORBID_FUNC
16
#include "os.h"
17
#include "osSemaphore.h"
18
#include "tdef.h"
19
#include "zlib.h"
20

21
#ifdef WINDOWS
22
#include <WinBase.h>
23
#include <io.h>
24
#include <ktmw32.h>
25
#include <windows.h>
26
#define F_OK 0
27
#define W_OK 2
28
#define R_OK 4
29

30
#define _SEND_FILE_STEP_ 1024
31

32
#else
33
#include <fcntl.h>
34
#include <sys/file.h>
35

36
#if !defined(_TD_DARWIN_64)
37
#include <sys/sendfile.h>
38
#endif
39
#include <sys/stat.h>
40
#include <unistd.h>
41
#define LINUX_FILE_NO_TEXT_OPTION 0
42
#define O_TEXT                    LINUX_FILE_NO_TEXT_OPTION
43

44
#define _SEND_FILE_STEP_ 1000
45
#endif
46

47
typedef int32_t FileFd;
48

49
#ifdef WINDOWS
50
typedef struct TdFile {
51
  TdThreadRwlock rwlock;
52
  int            refId;
53
  HANDLE         hFile;
54
  FILE          *fp;
55
  int32_t        tdFileOptions;
56
} TdFile;
57
#else
58
typedef struct TdFile {
59
  TdThreadRwlock rwlock;
60
  int            refId;
61
  FileFd         fd;
62
  FILE          *fp;
63
} TdFile;
64
#endif  // WINDOWS
65

66
#define FILE_WITH_LOCK 1
67

68
#ifdef BUILD_WITH_RAND_ERR
69
#define STUB_RAND_IO_ERR(ret)                                \
70
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_FILE)) { \
71
    uint32_t r = taosRand() % tsRandErrDivisor;              \
72
    if ((r + 1) <= tsRandErrChance) {                        \
73
      errno = EIO;                                           \
74
      terrno = TAOS_SYSTEM_ERROR(errno);                     \
75
      return (ret);                                          \
76
    }                                                        \
77
  }
78
#else
79
#define STUB_RAND_IO_ERR(ret)
80
#endif
81

82
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
1,086,137✔
83
  if (inputTmpDir == NULL || fileNamePrefix == NULL) return;
1,086,137!
84
#ifdef WINDOWS
85

86
  char tmpPath[PATH_MAX];
87

88
  int32_t len = (int32_t)strlen(inputTmpDir);
89
  memcpy(tmpPath, inputTmpDir, len);
90

91
  if (tmpPath[len - 1] != '/' && tmpPath[len - 1] != '\\') {
92
    tmpPath[len++] = '\\';
93
  }
94

95
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
96

97
  char rand[8] = {0};
98
  taosRandStr(rand, tListLen(rand) - 1);
99
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
100

101
#else
102

103
  char    tmpPath[PATH_MAX];
104
  int32_t len = strlen(inputTmpDir);
1,086,564✔
105
  (void)memcpy(tmpPath, inputTmpDir, len);
1,086,564✔
106
  static uint64_t seqId = 0;
107

108
  if (tmpPath[len - 1] != '/') {
1,086,564✔
109
    tmpPath[len++] = '/';
1✔
110
  }
111

112
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
1,086,564✔
113

114
  char rand[32] = {0};
1,086,564✔
115

116
  (void)snprintf(rand, sizeof(rand), "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
1,086,564✔
117

118
  (void)snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
1,087,542✔
119

120
#endif
121
}
122

123
int64_t taosCopyFile(const char *from, const char *to) {
75✔
124
  if (from == NULL || to == NULL) {
75✔
125
    terrno = TSDB_CODE_INVALID_PARA;
2✔
126
    return -1;
2✔
127
  }
128
#ifdef WINDOWS
129
  if (CopyFile(from, to, 0)) {
130
    return 1;
131
  } else {
132
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
133
    return -1;
134
  }
135
#else
136
  char    buffer[4096];
137
  int64_t size = 0;
73✔
138
  int64_t bytes;
139
  int32_t code = TSDB_CODE_SUCCESS;
73✔
140

141
  TdFilePtr pFileFrom = NULL;
73✔
142
  TdFilePtr pFileTo = NULL;
73✔
143
  pFileFrom = taosOpenFile(from, TD_FILE_READ);
73✔
144
  if (pFileFrom == NULL) {
73✔
145
    code = terrno;
1✔
146
    goto _err;
1✔
147
  }
148

149
  pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
72✔
150
  if (pFileTo == NULL) {
72✔
151
    code = terrno;
1✔
152
    goto _err;
1✔
153
  }
154

155
  while (true) {
156
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
81✔
157
    if (bytes < 0) {
81!
158
      code = terrno;
×
159
      goto _err;
×
160
    }
161

162
    if (bytes == 0) break;
81!
163

164
    size += bytes;
81✔
165

166
    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) {
81!
167
      code = terrno;
×
168
      goto _err;
×
169
    }
170
    if (bytes < sizeof(buffer)) break;
81✔
171
  }
172

173
  code = taosFsyncFile(pFileTo);
71✔
174
  if (code != 0) {
71!
175
    goto _err;
×
176
  }
177

178
  TAOS_UNUSED(taosCloseFile(&pFileFrom));
71✔
179
  TAOS_UNUSED(taosCloseFile(&pFileTo));
71✔
180

181
  if (code != 0) {
71!
182
    terrno = code;
×
183
    return -1;
×
184
  }
185

186
  return size;
71✔
187

188
_err:
2✔
189

190
  if (pFileFrom != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileFrom));
2✔
191
  if (pFileTo != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileTo));
2!
192
  /* coverity[+retval] */
193
  TAOS_SKIP_ERROR(taosRemoveFile(to));
2✔
194

195
  terrno = code;
2✔
196
  return -1;
2✔
197
#endif
198
}
199

200
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) {
18✔
201
  if (path == NULL) {
18✔
202
    terrno = TSDB_CODE_INVALID_PARA;
1✔
203
    return NULL;
1✔
204
  }
205
  TdFilePtr fp = taosOpenFile(path, tdFileOptions);
17✔
206
  if (!fp) {
17✔
207
    if (terrno == TAOS_SYSTEM_ERROR(ENOENT)) {
1!
208
      // Try to create directory recursively
209
      char s[PATH_MAX];
210
      tstrncpy(s, path, sizeof(s));
1✔
211
      if (taosMulMkDir(taosDirName(s)) != 0) {
1!
212
        return NULL;
1✔
213
      }
214
      fp = taosOpenFile(path, tdFileOptions);
×
215
      if (!fp) {
×
216
        return NULL;
×
217
      }
218
    }
219
  }
220

221
  return fp;
16✔
222
}
223

224
int32_t taosRemoveFile(const char *path) {
1,377,803✔
225
  OS_PARAM_CHECK(path);
1,377,803✔
226
  int32_t code = remove(path);
1,377,802✔
227
  if (-1 == code) {
1,377,807✔
228
    terrno = TAOS_SYSTEM_ERROR(errno);
1,087,539✔
229
    return terrno;
1,087,543✔
230
  }
231
  return code;
290,268✔
232
}
233

234
int32_t taosRenameFile(const char *oldName, const char *newName) {
240,375✔
235
  OS_PARAM_CHECK(oldName);
240,375✔
236
  OS_PARAM_CHECK(newName);
240,374✔
237
#ifdef WINDOWS
238
  bool finished = false;
239

240
  HANDLE transactionHandle = CreateTransaction(NULL, NULL, 0, 0, 0, INFINITE, NULL);
241
  if (transactionHandle == INVALID_HANDLE_VALUE) {
242
    DWORD error = GetLastError();
243
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
244
    return terrno;
245
  }
246

247
  BOOL result = MoveFileTransacted(oldName, newName, NULL, NULL, MOVEFILE_REPLACE_EXISTING, transactionHandle);
248

249
  if (result) {
250
    finished = CommitTransaction(transactionHandle);
251
    if (!finished) {
252
      DWORD error = GetLastError();
253
      terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
254
    }
255
  } else {
256
    RollbackTransaction(transactionHandle);
257
    DWORD error = GetLastError();
258
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
259
    finished = false;
260
  }
261

262
  CloseHandle(transactionHandle);
263

264
  return finished ? 0 : terrno;
265
#else
266
  int32_t code = rename(oldName, newName);
240,373✔
267
  if (-1 == code) {
240,366✔
268
    terrno = TAOS_SYSTEM_ERROR(errno);
355✔
269
    return terrno;
358✔
270
  }
271

272
  return TSDB_CODE_SUCCESS;
240,011✔
273
#endif
274
}
275

276
int32_t taosStatFile(const char *path, int64_t *size, int64_t *mtime, int64_t *atime) {
221,138✔
277
  OS_PARAM_CHECK(path);
221,138✔
278
#ifdef WINDOWS
279
  struct _stati64 fileStat;
280
  int32_t         code = _stati64(path, &fileStat);
281
#else
282
  struct stat fileStat;
283
  int32_t     code = stat(path, &fileStat);
221,137✔
284
#endif
285
  if (-1 == code) {
221,165✔
286
    terrno = TAOS_SYSTEM_ERROR(errno);
41,388✔
287
    return terrno;
41,361✔
288
  }
289

290
  if (size != NULL) {
179,777✔
291
    *size = fileStat.st_size;
168,615✔
292
  }
293

294
  if (mtime != NULL) {
179,777✔
295
    *mtime = fileStat.st_mtime;
2,819✔
296
  }
297

298
  if (atime != NULL) {
179,777!
299
    *atime = fileStat.st_atime;
×
300
  }
301

302
  return 0;
179,777✔
303
}
304

305
int32_t taosGetFileDiskID(const char *path, int64_t *diskid) {
2,053✔
306
  OS_PARAM_CHECK(path);
2,053✔
307
#ifdef WINDOWS
308
  struct _stati64 fileStat;
309
  int32_t         code = _stati64(path, &fileStat);
310
#else
311
  struct stat fileStat;
312
  int32_t     code = stat(path, &fileStat);
2,052✔
313
#endif
314
  if (-1 == code) {
2,052✔
315
    terrno = TAOS_SYSTEM_ERROR(errno);
1✔
316
    return terrno;
1✔
317
  }
318

319
  if (diskid != NULL) {
2,051✔
320
    *diskid = fileStat.st_dev;
2,050✔
321
  }
322

323
  return 0;
2,051✔
324
}
325

326
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
34,868✔
327
#ifdef WINDOWS
328
  if (pFile == NULL || pFile->hFile == NULL) {
329
    terrno = TSDB_CODE_INVALID_PARA;
330
    return terrno;
331
  }
332
  BY_HANDLE_FILE_INFORMATION bhfi;
333
  if (GetFileInformationByHandle(pFile->hFile, &bhfi) == FALSE) {
334
    DWORD error = GetLastError();
335
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
336
    return terrno;
337
  }
338

339
  if (stDev != NULL) {
340
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
341
  }
342

343
  if (stIno != NULL) {
344
    *stIno = (int64_t)((((uint64_t)bhfi.nFileIndexHigh) << 32) + bhfi.nFileIndexLow);
345
  }
346

347
#else
348
  if (pFile == NULL || pFile->fd < 0) {
34,868!
349
    terrno = TSDB_CODE_INVALID_PARA;
×
350
    return terrno;
1✔
351
  }
352

353
  struct stat fileStat;
354
  int32_t     code = fstat(pFile->fd, &fileStat);
34,896✔
355
  if (-1 == code) {
34,920✔
356
    terrno = TAOS_SYSTEM_ERROR(errno);
5✔
357
    return terrno;
×
358
  }
359

360
  if (stDev != NULL) {
34,915!
361
    *stDev = fileStat.st_dev;
34,919✔
362
  }
363

364
  if (stIno != NULL) {
34,915✔
365
    *stIno = fileStat.st_ino;
34,913✔
366
  }
367
#endif
368

369
  return 0;
34,915✔
370
}
371

372
FILE *taosOpenFileForStream(const char *path, int32_t tdFileOptions) {
11,551,406✔
373
  if (path == NULL) {
11,551,406✔
374
    terrno = TSDB_CODE_INVALID_PARA;
1✔
375
    return NULL;
1✔
376
  }
377
  char *mode = NULL;
11,551,405✔
378
  if (tdFileOptions & TD_FILE_APPEND) {
11,551,405✔
379
    mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
1,087!
380
  } else if (tdFileOptions & TD_FILE_TRUNC) {
11,550,318✔
381
    mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
1,293✔
382
  } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
11,549,025!
383
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
11,549,025!
384
  } else {
385
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
×
386
  }
387
  if (tdFileOptions & TD_FILE_EXCL) {
11,551,405!
388
    terrno = TSDB_CODE_INVALID_PARA;
×
389
    return NULL;
×
390
  }
391
  FILE *f = fopen(path, mode);
11,551,405✔
392
  if (NULL == f) {
11,551,405✔
393
    terrno = TAOS_SYSTEM_ERROR(errno);
40✔
394
  }
395
  return f;
11,551,405✔
396
}
397

398
#ifdef WINDOWS
399
HANDLE taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
400
  if (path == NULL) {
401
    terrno = TSDB_CODE_INVALID_PARA;
402
    return INVALID_HANDLE_VALUE;
403
  }
404
  DWORD openMode = 0;
405
  DWORD access = 0;
406
  DWORD fileFlag = FILE_ATTRIBUTE_NORMAL;
407
  DWORD shareMode = FILE_SHARE_READ;
408

409
  openMode = OPEN_EXISTING;
410
  if (tdFileOptions & TD_FILE_CREATE) {
411
    openMode = OPEN_ALWAYS;
412
  } else if (tdFileOptions & TD_FILE_EXCL) {
413
    openMode = CREATE_NEW;
414
  } else if ((tdFileOptions & TD_FILE_TRUNC)) {
415
    openMode = TRUNCATE_EXISTING;
416
    access |= GENERIC_WRITE;
417
  }
418
  if (tdFileOptions & TD_FILE_APPEND) {
419
    access |= FILE_APPEND_DATA;
420
  }
421
  if (tdFileOptions & TD_FILE_WRITE) {
422
    access |= GENERIC_WRITE;
423
  }
424

425
  shareMode |= FILE_SHARE_WRITE;
426

427
  access |= GENERIC_READ;
428

429
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
430
    fileFlag |= FILE_ATTRIBUTE_TEMPORARY;
431
  }
432
  if (tdFileOptions & TD_FILE_WRITE_THROUGH) {
433
    fileFlag |= FILE_FLAG_WRITE_THROUGH;
434
  }
435

436
  HANDLE h = CreateFile(path, access, shareMode, NULL, openMode, fileFlag, NULL);
437
  if (h != INVALID_HANDLE_VALUE && (tdFileOptions & TD_FILE_APPEND) && (tdFileOptions & TD_FILE_WRITE)) {
438
    SetFilePointer(h, 0, NULL, FILE_END);
439
  }
440
  if (h == INVALID_HANDLE_VALUE) {
441
    DWORD dwError = GetLastError();
442
    terrno = TAOS_SYSTEM_WINAPI_ERROR(dwError);
443
    // LPVOID lpMsgBuf;
444
    // FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPTSTR)&lpMsgBuf,
445
    // 0,
446
    //               NULL);
447
    // printf("CreateFile failed with error %d: %s", dwError, (char *)lpMsgBuf);
448
    // LocalFree(lpMsgBuf);
449
  }
450
  return h;
451
}
452

453
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
454
  if (pFile == NULL || buf == NULL) {
455
    terrno = TSDB_CODE_INVALID_PARA;
456
    return terrno;
457
  }
458
#if FILE_WITH_LOCK
459
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
460
#endif
461
  if (pFile->hFile == NULL) {
462
#if FILE_WITH_LOCK
463
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
464
#endif
465
    terrno = TSDB_CODE_INVALID_PARA;
466
    return terrno;
467
  }
468

469
  int64_t res = 0;
470
  DWORD   bytesRead;
471
  if (!ReadFile(pFile->hFile, buf, count, &bytesRead, NULL)) {
472
    DWORD errCode = GetLastError();
473
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errCode);
474
    res = -1;
475
  } else {
476
    res = bytesRead;
477
  }
478
#if FILE_WITH_LOCK
479
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
480
#endif
481
  return res;
482
}
483

484
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
485
  if (pFile == NULL || pFile->hFile == NULL || buf == NULL) {
486
    terrno = TSDB_CODE_INVALID_PARA;
487
    return 0;
488
  }
489
#if FILE_WITH_LOCK
490
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
491
#endif
492

493
  DWORD bytesWritten;
494
  if (!WriteFile(pFile->hFile, buf, count, &bytesWritten, NULL)) {
495
    errno = GetLastError();
496
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
497
    bytesWritten = -1;
498
  }
499

500
#if FILE_WITH_LOCK
501
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
502
#endif
503
  return bytesWritten;
504
}
505

506
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
507
  if (pFile == NULL || buf == NULL) {
508
    terrno = TSDB_CODE_INVALID_PARA;
509
    return 0;
510
  }
511
#if FILE_WITH_LOCK
512
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
513
#endif
514
  if (pFile->hFile == NULL) {
515
#if FILE_WITH_LOCK
516
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
517
#endif
518
    return 0;
519
  }
520

521
  DWORD      ret = 0;
522
  OVERLAPPED ol = {0};
523
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
524
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
525

526
  SetLastError(0);
527
  BOOL result = WriteFile(pFile->hFile, buf, count, &ret, &ol);
528
  if (!result) {
529
    errno = GetLastError();
530
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
531
    ret = -1;
532
  }
533

534
#if FILE_WITH_LOCK
535
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
536
#endif
537
  return ret;
538
}
539

540
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
541
  if (pFile == NULL || pFile->hFile == NULL) {
542
    terrno = TSDB_CODE_INVALID_PARA;
543
    return -1;
544
  }
545
#if FILE_WITH_LOCK
546
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
547
#endif
548

549
  LARGE_INTEGER liOffset;
550
  liOffset.QuadPart = offset;
551
  if (!SetFilePointerEx(pFile->hFile, liOffset, NULL, whence)) {
552
    errno = GetLastError();
553
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
554
    return -1;
555
  }
556

557
  liOffset.QuadPart = 0;
558
  if (!SetFilePointerEx(pFile->hFile, liOffset, &liOffset, FILE_CURRENT)) {
559
    errno = GetLastError();
560
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
561
    return -1;
562
  }
563
#if FILE_WITH_LOCK
564
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
565
#endif
566
  return liOffset.QuadPart;
567
}
568

569
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int64_t *mtime) {
570
  if (pFile == NULL || pFile->hFile == NULL) {
571
    terrno = TSDB_CODE_INVALID_PARA;
572
    return terrno;
573
  }
574

575
  if (size != NULL) {
576
    LARGE_INTEGER fileSize;
577
    if (!GetFileSizeEx(pFile->hFile, &fileSize)) {
578
      errno = GetLastError();
579
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
580
      return terrno;  // Error getting file size
581
    }
582
    *size = fileSize.QuadPart;
583
  }
584

585
  if (mtime != NULL) {
586
    FILETIME creationTime, lastAccessTime, lastWriteTime;
587
    if (!GetFileTime(pFile->hFile, &creationTime, &lastAccessTime, &lastWriteTime)) {
588
      errno = GetLastError();
589
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
590
      return terrno;  // Error getting file time
591
    }
592
    // Convert the FILETIME structure to a time_t value
593
    ULARGE_INTEGER ull;
594
    ull.LowPart = lastWriteTime.dwLowDateTime;
595
    ull.HighPart = lastWriteTime.dwHighDateTime;
596
    *mtime = (int64_t)((ull.QuadPart - 116444736000000000ULL) / 10000000ULL);
597
  }
598
  return 0;
599
}
600

601
int32_t taosLockFile(TdFilePtr pFile) {
602
  if (pFile == NULL || pFile->hFile == NULL) {
603
    terrno = TSDB_CODE_INVALID_PARA;
604
    return terrno;
605
  }
606

607
  BOOL          fSuccess = FALSE;
608
  LARGE_INTEGER fileSize;
609
  OVERLAPPED    overlapped = {0};
610

611
  fSuccess = LockFileEx(pFile->hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
612
                        0,           // reserved
613
                        ~0,          // number of bytes to lock low
614
                        ~0,          // number of bytes to lock high
615
                        &overlapped  // overlapped structure
616
  );
617
  if (!fSuccess) {
618
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
619
  }
620
  return 0;
621
}
622

623
int32_t taosUnLockFile(TdFilePtr pFile) {
624
  if (pFile == NULL || pFile->hFile == NULL) {
625
    return 0;
626
  }
627
  BOOL       fSuccess = FALSE;
628
  OVERLAPPED overlapped = {0};
629

630
  fSuccess = UnlockFileEx(pFile->hFile, 0, ~0, ~0, &overlapped);
631
  if (!fSuccess) {
632
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
633
  }
634
  return 0;
635
}
636

637
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
638
  if (pFile == NULL) {
639
    terrno = TSDB_CODE_INVALID_PARA;
640
    return terrno;
641
  }
642
  if (pFile->hFile == NULL) {
643
    printf("Ftruncate file error, hFile was null\n");
644
    terrno = TSDB_CODE_INVALID_PARA;
645
    return terrno;
646
  }
647

648
  LARGE_INTEGER li_0;
649
  li_0.QuadPart = (int64_t)0;
650
  BOOL cur = SetFilePointerEx(pFile->hFile, li_0, NULL, FILE_CURRENT);
651
  if (!cur) {
652
    printf("SetFilePointerEx Error getting current position in file.\n");
653
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
654
    return terrno;
655
  }
656

657
  LARGE_INTEGER li_size;
658
  li_size.QuadPart = l_size;
659
  BOOL cur2 = SetFilePointerEx(pFile->hFile, li_size, NULL, FILE_BEGIN);
660
  if (cur2 == 0) {
661
    int error = GetLastError();
662
    switch (error) {
663
      case ERROR_INVALID_HANDLE:
664
        errno = EBADF;
665
        break;
666
      default:
667
        errno = EIO;
668
        break;
669
    }
670
    terrno = TAOS_SYSTEM_ERROR(errno);
671
    return terrno;
672
  }
673

674
  if (!SetEndOfFile(pFile->hFile)) {
675
    int error = GetLastError();
676
    printf("SetEndOfFile GetLastError is:%d", error);
677
    switch (error) {
678
      case ERROR_INVALID_HANDLE:
679
        errno = EBADF;
680
        break;
681
      default:
682
        errno = EIO;
683
        break;
684
    }
685
    terrno = TAOS_SYSTEM_ERROR(errno);
686
    return terrno;
687
  }
688
  return 0;
689
}
690

691
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
692
  if (pFileOut == NULL || pFileIn == NULL) {
693
    terrno = TSDB_CODE_INVALID_PARA;
694
    return -1;
695
  }
696
  if (pFileIn->hFile == NULL || pFileOut->hFile == NULL) {
697
    terrno = TSDB_CODE_INVALID_PARA;
698
    return -1;
699
  }
700

701
  LARGE_INTEGER fileOffset;
702
  fileOffset.QuadPart = *offset;
703

704
  if (!SetFilePointerEx(pFileIn->hFile, fileOffset, &fileOffset, FILE_BEGIN)) {
705
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
706
    return -1;
707
  }
708

709
  int64_t writeLen = 0;
710
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
711

712
  DWORD bytesRead;
713
  DWORD bytesWritten;
714
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
715
    if (!ReadFile(pFileIn->hFile, buffer, _SEND_FILE_STEP_, &bytesRead, NULL)) {
716
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
717
      return writeLen;
718
    }
719

720
    if (bytesRead <= 0) {
721
      return writeLen;
722
    } else if (bytesRead < _SEND_FILE_STEP_) {
723
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
724
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
725
        return -1;
726
      } else {
727
        return (int64_t)(writeLen + bytesRead);
728
      }
729
    } else {
730
      if (!WriteFile(pFileOut->hFile, buffer, _SEND_FILE_STEP_, &bytesWritten, NULL)) {
731
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
732
        return -1;
733
      } else {
734
        writeLen += _SEND_FILE_STEP_;
735
      }
736
    }
737
  }
738

739
  int64_t remain = size - writeLen;
740
  if (remain > 0) {
741
    DWORD bytesRead;
742
    if (!ReadFile(pFileIn->hFile, buffer, (DWORD)remain, &bytesRead, NULL)) {
743
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
744
      return -1;
745
    }
746

747
    if (bytesRead <= 0) {
748
      return writeLen;
749
    } else {
750
      DWORD bytesWritten;
751
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
752
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
753
        return -1;
754
      } else {
755
        writeLen += bytesWritten;
756
      }
757
    }
758
  }
759
  return writeLen;
760
}
761

762
bool lastErrorIsFileNotExist() {
763
  DWORD dwError = GetLastError();
764
  return dwError == ERROR_FILE_NOT_FOUND;
765
}
766

767
#else
768
int taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
16,471,535✔
769
  if (path == NULL) {
16,471,535!
770
    terrno = TSDB_CODE_INVALID_PARA;
×
771
    return -1;
×
772
  }
773
  int access = O_BINARY;
16,471,535✔
774
  access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
16,471,535✔
775
  if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
16,471,535✔
776
    access |= O_RDWR;
519,995✔
777
  } else if (tdFileOptions & TD_FILE_WRITE) {
15,951,540✔
778
    access |= O_WRONLY;
378,517✔
779
  } else if (tdFileOptions & TD_FILE_READ) {
15,573,023!
780
    access |= O_RDONLY;
15,573,178✔
781
  }
782
  access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
16,471,535✔
783
  access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
16,471,535✔
784
  access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
16,471,535✔
785
  access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
16,471,535✔
786
  access |= (tdFileOptions & TD_FILE_CLOEXEC) ? O_CLOEXEC : 0;
16,471,535✔
787

788
  int fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
16,471,535✔
789
  if (-1 == fd) {
16,476,970✔
790
    terrno = TAOS_SYSTEM_ERROR(errno);
24,344✔
791
  }
792
  return fd;
16,478,407✔
793
}
794

795
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
40,291,420✔
796
  if (pFile == NULL || buf == NULL) {
40,291,420!
797
    terrno = TSDB_CODE_INVALID_PARA;
×
798
    return -1;
2✔
799
  }
800
  STUB_RAND_IO_ERR(terrno)
801
#if FILE_WITH_LOCK
802
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
40,295,035✔
803
#endif
804

805
  if (pFile->fd < 0) {
40,300,843!
806
#if FILE_WITH_LOCK
807
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
808
#endif
809
    terrno = TSDB_CODE_INVALID_PARA;
×
810
    return -1;
×
811
  }
812

813
  int64_t leftbytes = count;
40,301,024✔
814
  int64_t readbytes;
815
  char   *tbuf = (char *)buf;
40,301,024✔
816
  int32_t code = 0;
40,301,024✔
817

818
  while (leftbytes > 0) {
80,595,915✔
819
#ifdef WINDOWS
820
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
821
#else
822
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
40,299,535✔
823
#endif
824
    if (readbytes < 0) {
40,299,202✔
825
      if (errno == EINTR) {
106!
826
        continue;
×
827
      } else {
828
        code = TAOS_SYSTEM_ERROR(errno);
106✔
829
#if FILE_WITH_LOCK
830
        (void)taosThreadRwlockUnlock(&(pFile->rwlock));
106✔
831
#endif
832
        terrno = code;
106✔
833
        return -1;
106✔
834
      }
835
    } else if (readbytes == 0) {
40,299,096✔
836
#if FILE_WITH_LOCK
837
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
4,205✔
838
#endif
839
      return (int64_t)(count - leftbytes);
4,205✔
840
    }
841

842
    leftbytes -= readbytes;
40,294,891✔
843
    tbuf += readbytes;
40,294,891✔
844
  }
845

846
#if FILE_WITH_LOCK
847
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
40,296,380✔
848
#endif
849

850
  return count;
40,297,821✔
851
}
852

853
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
567,394,829✔
854
  STUB_RAND_IO_ERR(terrno)
855
  if (pFile == NULL || buf == NULL) {
567,394,829!
856
    terrno = TSDB_CODE_INVALID_PARA;
×
857
    return 0;
2✔
858
  }
859
#if FILE_WITH_LOCK
860
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
567,417,470✔
861
#endif
862
  if (pFile->fd < 0) {
567,640,499!
863
#if FILE_WITH_LOCK
864
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
865
#endif
866
    terrno = TSDB_CODE_INVALID_PARA;
×
867
    return 0;
×
868
  }
869

870
  int64_t nleft = count;
567,640,606✔
871
  int64_t nwritten = 0;
567,640,606✔
872
  char   *tbuf = (char *)buf;
567,640,606✔
873
  int32_t code = 0;
567,640,606✔
874

875
  while (nleft > 0) {
1,135,277,688✔
876
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
567,640,022✔
877
    if (nwritten < 0) {
567,637,083✔
878
      if (errno == EINTR) {
1!
879
        continue;
×
880
      }
881
      code = TAOS_SYSTEM_ERROR(errno);
1✔
882
#if FILE_WITH_LOCK
883
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1✔
884
#endif
885
      terrno = code;
1✔
886
      return -1;
1✔
887
    }
888
    nleft -= nwritten;
567,637,082✔
889
    tbuf += nwritten;
567,637,082✔
890
  }
891

892
#if FILE_WITH_LOCK
893
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
567,637,666✔
894
#endif
895

896
  return count;
567,613,146✔
897
}
898

899
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
648,505✔
900
  STUB_RAND_IO_ERR(terrno)
901
  if (pFile == NULL || buf == NULL) {
648,505!
902
    terrno = TSDB_CODE_INVALID_PARA;
×
903
    return 0;
2✔
904
  }
905

906
  int32_t code = 0;
648,545✔
907
#if FILE_WITH_LOCK
908
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
648,545✔
909
#endif
910

911
#if FILE_WITH_LOCK
912
  if (pFile->fd < 0) {
648,869!
913
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
914
    return 0;
×
915
  }
916
#endif
917

918
  int64_t ret = pwrite(pFile->fd, buf, count, offset);
648,869✔
919
  if (-1 == ret) {
648,412!
920
    code = TAOS_SYSTEM_ERROR(errno);
×
921
  }
922

923
#if FILE_WITH_LOCK
924
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
648,412✔
925
#endif
926

927
  if (code) {
648,807!
928
    terrno = code;
×
929
  }
930

931
  return ret;
648,826✔
932
}
933

934
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
51,031,711✔
935
  if (pFile == NULL || pFile->fd < 0) {
51,031,711!
936
    terrno = TSDB_CODE_INVALID_PARA;
×
937
    return -1;
1✔
938
  }
939
#if FILE_WITH_LOCK
940
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
51,036,647✔
941
#endif
942

943
  int32_t code = 0;
51,044,797✔
944

945
  int64_t ret = lseek(pFile->fd, offset, whence);
51,044,797✔
946
  if (-1 == ret) {
51,044,185!
947
    code = TAOS_SYSTEM_ERROR(errno);
×
948
  }
949

950
#if FILE_WITH_LOCK
951
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
51,044,185✔
952
#endif
953

954
  if (code) {
51,044,990✔
955
    terrno = code;
558✔
956
    return -1;
×
957
  }
958

959
  return ret;
51,044,432✔
960
}
961

962
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int64_t *mtime) {
88,512✔
963
  if (pFile == NULL) {
88,512✔
964
    terrno = TSDB_CODE_INVALID_PARA;
2✔
965
    return terrno;
2✔
966
  }
967

968
  if (pFile->fd < 0) {
88,510!
969
    terrno = TSDB_CODE_INVALID_PARA;
×
970
    return terrno;
×
971
  }
972

973
  struct stat fileStat;
974
  int32_t     code = fstat(pFile->fd, &fileStat);
88,510✔
975
  if (-1 == code) {
88,529✔
976
    terrno = TAOS_SYSTEM_ERROR(errno);
9✔
977
    return terrno;
×
978
  }
979

980
  if (size != NULL) {
88,520✔
981
    *size = fileStat.st_size;
88,519✔
982
  }
983

984
  if (mtime != NULL) {
88,520!
985
    *mtime = fileStat.st_mtime;
×
986
  }
987

988
  return 0;
88,520✔
989
}
990

991
int32_t taosLockFile(TdFilePtr pFile) {
22,018✔
992
  if (NULL == pFile || pFile->fd < 0) {
22,018!
993
    terrno = TSDB_CODE_INVALID_PARA;
2✔
994
    return terrno;
2✔
995
  }
996
  int32_t code = (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
22,016✔
997
  if (-1 == code) {
22,016✔
998
    terrno = TAOS_SYSTEM_ERROR(errno);
16,058✔
999
    return terrno;
16,058✔
1000
  }
1001
  return 0;
5,958✔
1002
}
1003

1004
int32_t taosUnLockFile(TdFilePtr pFile) {
3,615✔
1005
  if (NULL == pFile || pFile->fd < 0) {
3,615!
1006
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1007
    return terrno;
2✔
1008
  }
1009
  int32_t code = (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
3,613✔
1010
  if (-1 == code) {
3,613!
1011
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1012
    return terrno;
×
1013
  }
1014
  return 0;
3,613✔
1015
}
1016

1017
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
193✔
1018
  if (NULL == pFile || pFile->fd < 0) {
193!
1019
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1020
    return terrno;
2✔
1021
  }
1022

1023
  int32_t code = ftruncate(pFile->fd, l_size);
191✔
1024
  if (-1 == code) {
191!
1025
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1026
    return terrno;
×
1027
  }
1028
  return 0;
191✔
1029
}
1030

1031
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
39✔
1032
  if (pFileOut == NULL || pFileIn == NULL) {
39✔
1033
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1034
    return -1;
3✔
1035
  }
1036
  if (pFileIn->fd < 0 || pFileOut->fd < 0) {
36!
1037
    terrno = TSDB_CODE_INVALID_PARA;
×
1038
    return -1;
×
1039
  }
1040

1041
#ifdef _TD_DARWIN_64
1042
  if (lseek(pFileIn->fd, (int32_t)(*offset), 0) < 0) {
1043
    terrno = TAOS_SYSTEM_ERROR(errno);
1044
    return -1;
1045
  }
1046
  int64_t writeLen = 0;
1047
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
1048

1049
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
1050
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
1051
    if (rlen <= 0) {
1052
      return writeLen;
1053
    } else if (rlen < _SEND_FILE_STEP_) {
1054
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
1055
      return (int64_t)(writeLen + rlen);
1056
    } else {
1057
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
1058
      writeLen += _SEND_FILE_STEP_;
1059
    }
1060
  }
1061

1062
  int64_t remain = size - writeLen;
1063
  if (remain > 0) {
1064
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
1065
    if (rlen <= 0) {
1066
      return writeLen;
1067
    } else {
1068
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
1069
      writeLen += remain;
1070
    }
1071
  }
1072
  return writeLen;
1073

1074
#else  // for linux
1075

1076
  int64_t leftbytes = size;
36✔
1077
  int64_t sentbytes;
1078

1079
  while (leftbytes > 0) {
72✔
1080
#ifdef _TD_ARM_32
1081
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int *)offset, leftbytes);
1082
#else
1083
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
36✔
1084
#endif
1085
    if (sentbytes == -1) {
36!
1086
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
×
1087
        continue;
×
1088
      } else {
1089
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1090
        return -1;
×
1091
      }
1092
    } else if (sentbytes == 0) {
36!
1093
      return (int64_t)(size - leftbytes);
×
1094
    }
1095

1096
    leftbytes -= sentbytes;
36✔
1097
  }
1098

1099
  return size;
36✔
1100
#endif
1101
}
1102

1103
bool lastErrorIsFileNotExist() { return terrno == TAOS_SYSTEM_ERROR(ENOENT); }
9,328✔
1104

1105
#endif  // WINDOWS
1106

1107
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
28,023,801✔
1108
  if (path == NULL) {
28,023,801✔
1109
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1110
    return NULL;
1✔
1111
  }
1112
  STUB_RAND_IO_ERR(NULL)
1113
  FILE *fp = NULL;
28,023,800✔
1114
#ifdef WINDOWS
1115
  HANDLE hFile = NULL;
1116
#else
1117
  int fd = -1;
28,023,800✔
1118
#endif
1119
  if (tdFileOptions & TD_FILE_STREAM) {
28,023,800✔
1120
    fp = taosOpenFileForStream(path, tdFileOptions);
11,551,405✔
1121
    if (fp == NULL) return NULL;
11,551,405✔
1122
  } else {
1123
#ifdef WINDOWS
1124
    hFile = taosOpenFileNotStream(path, tdFileOptions);
1125
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
1126
#else
1127
    fd = taosOpenFileNotStream(path, tdFileOptions);
16,472,395✔
1128
    if (fd == -1) return NULL;
16,475,608✔
1129
#endif
1130
  }
1131

1132
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
28,001,192!
1133
  if (pFile == NULL) {
28,001,929!
1134
#ifdef WINDOWS
1135
    if (hFile != NULL) CloseHandle(hFile);
1136
#else
1137
    if (fd >= 0) (void)close(fd);
×
1138
#endif
1139
    if (fp != NULL) (void)fclose(fp);
×
1140
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
1141
    return NULL;
×
1142
  }
1143

1144
#if FILE_WITH_LOCK
1145
  (void)taosThreadRwlockInit(&(pFile->rwlock), NULL);
28,001,929✔
1146
#endif
1147
  pFile->fp = fp;
27,997,642✔
1148
  pFile->refId = 0;
27,997,642✔
1149

1150
#ifdef WINDOWS
1151
  pFile->hFile = hFile;
1152
  pFile->tdFileOptions = tdFileOptions;
1153
  // do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
1154
  // the file handle, as well as the space on disk.
1155
#else
1156
  pFile->fd = fd;
27,997,642✔
1157
  // Remove it instantly, so when the program exits normally/abnormally, the file
1158
  // will be automatically remove by OS.
1159
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
27,997,642✔
1160
    if (-1 == unlink(path)) {
5,424✔
1161
      terrno = TAOS_SYSTEM_ERROR(errno);
1,322✔
1162
      (void)close(fd);
×
1163
      taosMemoryFree(pFile);
×
1164
      return NULL;
×
1165
    }
1166
  }
1167
#endif
1168

1169
  return pFile;
27,996,320✔
1170
}
1171

1172
int32_t taosCloseFile(TdFilePtr *ppFile) {
40,563,713✔
1173
  int32_t code = 0;
40,563,713✔
1174
  if (ppFile == NULL || *ppFile == NULL) {
40,563,713!
1175
    return 0;
12,560,111✔
1176
  }
1177
#if FILE_WITH_LOCK
1178
  (void)taosThreadRwlockWrlock(&((*ppFile)->rwlock));
28,003,602✔
1179
#endif
1180
  if ((*ppFile)->fp != NULL) {
28,004,115✔
1181
    TAOS_UNUSED(fflush((*ppFile)->fp));
11,550,619✔
1182
    TAOS_UNUSED(fclose((*ppFile)->fp));
11,550,619✔
1183
    (*ppFile)->fp = NULL;
11,550,619✔
1184
  }
1185
#ifdef WINDOWS
1186
  if ((*ppFile)->hFile != NULL) {
1187
    // FlushFileBuffers((*ppFile)->hFile);
1188
    if (!CloseHandle((*ppFile)->hFile)) {
1189
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1190
      code = -1;
1191
    }
1192
    (*ppFile)->hFile = NULL;
1193
#else
1194
  if ((*ppFile)->fd >= 0) {
28,004,115✔
1195
    // warning: never fsync silently in base lib
1196
    /*fsync((*ppFile)->fd);*/
1197
    code = close((*ppFile)->fd);
16,453,638✔
1198
    if (-1 == code) {
16,454,386!
1199
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1200
    }
1201
    (*ppFile)->fd = -1;
16,454,496✔
1202
#endif
1203
  }
1204
  (*ppFile)->refId = 0;
28,004,973✔
1205
#if FILE_WITH_LOCK
1206
  (void)taosThreadRwlockUnlock(&((*ppFile)->rwlock));
28,004,973✔
1207
  (void)taosThreadRwlockDestroy(&((*ppFile)->rwlock));
28,005,033✔
1208
#endif
1209
  taosMemoryFree(*ppFile);
28,004,675✔
1210
  *ppFile = NULL;
28,004,352✔
1211
  return code;
28,004,352✔
1212
}
1213

1214
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
477,007✔
1215
  STUB_RAND_IO_ERR(terrno)
1216
  if (pFile == NULL) {
477,007✔
1217
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1218
    return -1;
1✔
1219
  }
1220

1221
  int32_t code = 0;
477,006✔
1222

1223
#ifdef WINDOWS
1224
#if FILE_WITH_LOCK
1225
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
1226
#endif
1227

1228
  if (pFile->hFile == NULL) {
1229
#if FILE_WITH_LOCK
1230
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1231
#endif
1232

1233
    terrno = TSDB_CODE_INVALID_PARA;
1234
    return -1;
1235
  }
1236

1237
  DWORD      ret = 0;
1238
  OVERLAPPED ol = {0};
1239
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
1240
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
1241

1242
  SetLastError(0);
1243
  BOOL result = ReadFile(pFile->hFile, buf, count, &ret, &ol);
1244
  if (!result && GetLastError() != ERROR_HANDLE_EOF) {
1245
    code = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1246
    ret = -1;
1247
  }
1248
#else
1249
#if FILE_WITH_LOCK
1250
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
477,006✔
1251
#endif
1252

1253
  if (pFile->fd < 0) {
477,145!
1254
#if FILE_WITH_LOCK
1255
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
1256
#endif
1257
    terrno = TSDB_CODE_INVALID_PARA;
×
1258
    return -1;
×
1259
  }
1260
  int64_t ret = pread(pFile->fd, buf, count, offset);
477,145✔
1261
  if (-1 == ret) {
477,098!
1262
    code = TAOS_SYSTEM_ERROR(errno);
×
1263
  }
1264
#endif
1265
#if FILE_WITH_LOCK
1266
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
477,098✔
1267
#endif
1268

1269
  if (code) {
477,211!
1270
    terrno = code;
×
1271
    return -1;
×
1272
  }
1273

1274
  return ret;
477,221✔
1275
}
1276

1277
int32_t taosFsyncFile(TdFilePtr pFile) {
1,980,107✔
1278
  if (pFile == NULL) {
1,980,107✔
1279
    return 0;
2,283✔
1280
  }
1281

1282
  int32_t code = 0;
1,977,824✔
1283
  // this implementation is WRONG
1284
  // fflush is not a replacement of fsync
1285
  if (pFile->fp != NULL) {
1,977,824✔
1286
    code = fflush(pFile->fp);
458,180✔
1287
    if (0 != code) {
458,180!
1288
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1289
      return terrno;
×
1290
    }
1291

1292
    return 0;
458,180✔
1293
  }
1294

1295
#ifdef WINDOWS
1296
  if (pFile->hFile != NULL) {
1297
    if (pFile->tdFileOptions & TD_FILE_WRITE_THROUGH) {
1298
      return 0;
1299
    }
1300
    bool ret = FlushFileBuffers(pFile->hFile);
1301
    if (!ret) {
1302
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1303
      return terrno;
1304
    }
1305
    return 0;
1306
  }
1307
#else
1308
  if (pFile->fd >= 0) {
1,519,644!
1309
    code = fsync(pFile->fd);
1,519,863✔
1310
    if (-1 == code) {
1,520,124!
1311
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1312
      return terrno;
×
1313
    }
1314
  }
1315
#endif
1316

1317
  return 0;
1,520,149✔
1318
}
1319

1320
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
165,609,719✔
1321
  if (pFile == NULL || pFile->fp == NULL) {
165,609,719!
1322
    return;
61,451,730✔
1323
  }
1324
  va_list ap;
1325
  va_start(ap, format);
104,157,989✔
1326
  (void)vfprintf(pFile->fp, format, ap);
104,157,989✔
1327
  va_end(ap);
104,242,197✔
1328
}
1329

1330
bool taosValidFile(TdFilePtr pFile) {
3✔
1331
#ifdef WINDOWS
1332
  return pFile != NULL && pFile->hFile != NULL;
1333
#else
1334
  return pFile != NULL && pFile->fd > 0;
3!
1335
#endif
1336
}
1337

1338
int32_t taosUmaskFile(int32_t maskVal) {
10,905✔
1339
#ifdef WINDOWS
1340
  return 0;
1341
#else
1342
  return umask(maskVal);
10,905✔
1343
#endif
1344
}
1345

1346
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
109,298✔
1347
  int64_t ret = -1;
109,298✔
1348
  int32_t code = 0;
109,298✔
1349

1350
  if (pFile == NULL || ptrBuf == NULL) {
109,298✔
1351
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1352
    goto END;
3✔
1353
  }
1354
  if (*ptrBuf != NULL) {
109,295✔
1355
    taosMemoryFreeClear(*ptrBuf);
109,260!
1356
  }
1357

1358
  if (pFile->fp == NULL) {
109,295!
1359
    terrno = TSDB_CODE_INVALID_PARA;
×
1360
    goto END;
×
1361
  }
1362

1363
#if FILE_WITH_LOCK
1364
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
109,295✔
1365
#endif
1366

1367
#ifdef WINDOWS
1368
  size_t bufferSize = 512;
1369
  *ptrBuf = taosMemoryMalloc(bufferSize);
1370
  if (*ptrBuf == NULL) {
1371
    goto END;
1372
  }
1373

1374
  size_t bytesRead = 0;
1375
  size_t totalBytesRead = 0;
1376

1377
  while (1) {
1378
    char *result = fgets(*ptrBuf + totalBytesRead, bufferSize - totalBytesRead, pFile->fp);
1379
    if (result == NULL) {
1380
      if (feof(pFile->fp)) {
1381
        break;
1382
      } else {
1383
        ret = -1;
1384
        terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
1385
        taosMemoryFreeClear(*ptrBuf);
1386
        goto END;
1387
      }
1388
    }
1389
    bytesRead = strlen(*ptrBuf + totalBytesRead);
1390
    totalBytesRead += bytesRead;
1391

1392
    if (totalBytesRead < bufferSize - 1 || (*ptrBuf)[totalBytesRead - 1] == '\n') {
1393
      break;
1394
    }
1395

1396
    bufferSize += 512;
1397
    void *newBuf = taosMemoryRealloc(*ptrBuf, bufferSize);
1398
    if (newBuf == NULL) {
1399
      taosMemoryFreeClear(*ptrBuf);
1400
      goto END;
1401
    }
1402

1403
    *ptrBuf = newBuf;
1404
  }
1405

1406
  (*ptrBuf)[totalBytesRead] = '\0';
1407
  ret = (totalBytesRead > 0 ? totalBytesRead : -1); // -1 means EOF
1408
#else
1409
  size_t len = 0;
109,295✔
1410
  ret = getline(ptrBuf, &len, pFile->fp);
109,295✔
1411
  if (-1 == ret) {
109,295✔
1412
    terrno = TAOS_SYSTEM_ERROR(errno);
35✔
1413
  }
1414
#endif
1415

1416
END:
109,260✔
1417

1418
#if FILE_WITH_LOCK
1419
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
109,298✔
1420
#endif
1421

1422
  return ret;
109,298✔
1423
}
1424

1425
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
40,044,607✔
1426
  if (pFile == NULL || buf == NULL) {
40,044,607✔
1427
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1428
    return terrno;
3✔
1429
  }
1430

1431
  if (pFile->fp == NULL) {
40,044,604!
1432
    terrno = TSDB_CODE_INVALID_PARA;
×
1433
    return terrno;
×
1434
  }
1435

1436
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
40,044,604✔
1437
    if (feof(pFile->fp)) {
18,368!
1438
      return 0;
18,368✔
1439
    } else {
1440
      terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
×
1441
      return terrno;
×
1442
    }
1443
  }
1444

1445
  return strlen(buf);
40,026,236✔
1446
}
1447

1448
int32_t taosEOFFile(TdFilePtr pFile) {
34,953,678✔
1449
  if (pFile == NULL) {
34,953,678✔
1450
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1451
    return -1;
2✔
1452
  }
1453
  if (pFile->fp == NULL) {
34,953,676!
1454
    terrno = TSDB_CODE_INVALID_PARA;
×
1455
    return -1;
×
1456
  }
1457

1458
  return feof(pFile->fp);
34,953,676✔
1459
}
1460

1461
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
499,187✔
1462
  if (pathname == NULL) {
499,187✔
1463
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1464
    return false;  // invalid parameter
1✔
1465
  }
1466
  int flags = 0;
499,186✔
1467

1468
  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
499,186!
1469
    flags |= F_OK;
499,266✔
1470
  }
1471

1472
  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
499,186✔
1473
    flags |= R_OK;
16,898✔
1474
  }
1475

1476
  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
499,186✔
1477
    flags |= W_OK;
16,898✔
1478
  }
1479
#ifdef WINDOWS
1480
  return _access(pathname, flags) == 0;
1481
#else
1482
  return access(pathname, flags) == 0;
499,186✔
1483
#endif
1484
}
1485

1486
bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };
482,196✔
1487

1488
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
7✔
1489
  OS_PARAM_CHECK(srcFileName);
7✔
1490
  OS_PARAM_CHECK(destFileName);
6✔
1491
  int32_t   compressSize = 163840;
5✔
1492
  int32_t   ret = 0;
5✔
1493
  int32_t   len = 0;
5✔
1494
  gzFile    dstFp = NULL;
5✔
1495
  TdFilePtr pSrcFile = NULL;
5✔
1496

1497
  char *data = taosMemoryMalloc(compressSize);
5!
1498
  if (NULL == data) {
5!
1499
    return terrno;
×
1500
  }
1501

1502
  pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ | TD_FILE_STREAM);
5✔
1503
  if (pSrcFile == NULL) {
5✔
1504
    ret = terrno;
1✔
1505
    goto cmp_end;
1✔
1506
  }
1507

1508
  int access = O_BINARY | O_WRONLY | O_TRUNC | O_CREAT;
4✔
1509
#ifdef WINDOWS
1510
  int32_t pmode = _S_IREAD | _S_IWRITE;
1511
#else
1512
  int32_t pmode = S_IRWXU | S_IRWXG | S_IRWXO;
4✔
1513
#endif
1514
  int fd = open(destFileName, access, pmode);
4✔
1515
  if (-1 == fd) {
4✔
1516
    terrno = TAOS_SYSTEM_ERROR(errno);
1✔
1517
    ret = terrno;
1✔
1518
    goto cmp_end;
1✔
1519
  }
1520

1521
  // Both gzclose() and fclose() will close the associated fd, so they need to have different fds.
1522
  FileFd gzFd = dup(fd);
3✔
1523
  if (-1 == gzFd) {
3!
1524
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1525
    ret = terrno;
×
1526
    goto cmp_end;
×
1527
  }
1528
  dstFp = gzdopen(gzFd, "wb6f");
3✔
1529
  if (dstFp == NULL) {
3!
1530
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1531
    ret = terrno;
×
1532
    (void)close(gzFd);
×
1533
    goto cmp_end;
×
1534
  }
1535

1536
  while (!feof(pSrcFile->fp)) {
6✔
1537
    len = (int32_t)fread(data, 1, compressSize, pSrcFile->fp);
3✔
1538
    if (len > 0) {
3!
1539
      if (gzwrite(dstFp, data, len) == 0) {
3!
1540
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1541
        ret = terrno;
×
1542
        goto cmp_end;
×
1543
      }
1544
    }
1545
  }
1546

1547
cmp_end:
3✔
1548

1549
  if (fd >= 0) {
5✔
1550
    TAOS_SKIP_ERROR(close(fd));
4✔
1551
  }
1552
  if (pSrcFile) {
5✔
1553
    TAOS_SKIP_ERROR(taosCloseFile(&pSrcFile));
4✔
1554
  }
1555

1556
  if (dstFp) {
5✔
1557
    TAOS_SKIP_ERROR(gzclose(dstFp));
3✔
1558
  }
1559

1560
  taosMemoryFree(data);
5!
1561

1562
  return ret;
5✔
1563
}
1564

1565
int32_t taosSetFileHandlesLimit() {
9,397✔
1566
#ifdef WINDOWS
1567
  const int max_handles = 8192;
1568
  int       res = _setmaxstdio(max_handles);
1569
  return res == max_handles ? 0 : -1;
1570
#endif
1571
  return 0;
9,397✔
1572
}
1573

1574
int32_t taosLinkFile(char *src, char *dst) {
107✔
1575
#ifndef WINDOWS
1576
  if (-1 == link(src, dst)) {
107✔
1577
    terrno = TAOS_SYSTEM_ERROR(errno);
1✔
1578
    return terrno;
1✔
1579
  }
1580
#endif
1581
  return 0;
106✔
1582
}
1583

1584
FILE *taosOpenCFile(const char *filename, const char *mode) {
1,079,945✔
1585
  if (filename == NULL || mode == NULL) {
1,079,945!
1586
    terrno = TSDB_CODE_INVALID_PARA;
×
1587
    return NULL;
2✔
1588
  }
1589
  STUB_RAND_IO_ERR(NULL)
1590
  FILE *f = fopen(filename, mode);
1,081,654✔
1591
  if (NULL == f) {
1,082,676✔
1592
    terrno = TAOS_SYSTEM_ERROR(errno);
1✔
1593
  }
1594
  return f;
1,082,676✔
1595
}
1596

1597
int taosSeekCFile(FILE *file, int64_t offset, int whence) {
641,181✔
1598
  if (NULL == file) {
641,181✔
1599
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1600
    return terrno;
1✔
1601
  }
1602
#ifdef WINDOWS
1603
  return _fseeki64(file, offset, whence);
1604
#else
1605
  int     code = fseeko(file, offset, whence);
641,180✔
1606
  if (-1 == code) {
641,166!
1607
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1608
    code = terrno;
×
1609
  }
1610
  return code;
641,175✔
1611
#endif
1612
}
1613

1614
size_t taosReadFromCFile(void *buffer, size_t size, size_t count, FILE *stream) {
641,174✔
1615
  if (buffer == NULL || stream == NULL) {
641,174!
1616
    terrno = TSDB_CODE_INVALID_PARA;
×
1617
    return 0;
2✔
1618
  }
1619
  STUB_RAND_IO_ERR(terrno)
1620
  return fread(buffer, size, count, stream);
641,182✔
1621
}
1622

1623
#if 0
1624
size_t taosWriteToCFile(const void *ptr, size_t size, size_t nitems, FILE *stream) {
1625
  STUB_RAND_IO_ERR(terrno)
1626
  return fwrite(ptr, size, nitems, stream);
1627
}
1628
#endif
1629

1630
int taosCloseCFile(FILE *f) { return fclose(f); }
1,082,607✔
1631

1632
int taosSetAutoDelFile(char *path) {
1,082,675✔
1633
#ifdef WINDOWS
1634
  bool succ = SetFileAttributes(path, FILE_ATTRIBUTE_TEMPORARY);
1635
  if (succ) {
1636
    return 0;
1637
  } else {
1638
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1639
    return terrno;
1640
  }
1641
#else
1642
  if (-1 == unlink(path)) {
1,082,675!
1643
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1644
    return terrno;
×
1645
  }
1646
  return 0;
1,082,675✔
1647
#endif
1648
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc