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

taosdata / TDengine / #3819

01 Apr 2025 09:27AM UTC coverage: 34.076% (+0.01%) from 34.065%
#3819

push

travis-ci

happyguoxy
test:alter gcda dir

148544 of 599532 branches covered (24.78%)

Branch coverage included in aggregate %.

222541 of 489451 relevant lines covered (45.47%)

763329.1 hits per line

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

74.21
/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 X_OK 1
28
#define W_OK 2
29
#define R_OK 4
30

31
#define _SEND_FILE_STEP_ 1024
32

33
#else
34
#include <fcntl.h>
35
#ifndef TD_ASTRA
36
#include <sys/file.h>
37

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

47
#define _SEND_FILE_STEP_ 1000
48
#endif
49

50
typedef int32_t FileFd;
51

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

69
#define FILE_WITH_LOCK 1
70

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

85
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
9✔
86
  if (inputTmpDir == NULL || fileNamePrefix == NULL) return;
9✔
87
#ifdef WINDOWS
88

89
  char tmpPath[PATH_MAX];
90

91
  int32_t len = (int32_t)strlen(inputTmpDir);
92
  memcpy(tmpPath, inputTmpDir, len);
93

94
  if (tmpPath[len - 1] != '/' && tmpPath[len - 1] != '\\') {
95
    tmpPath[len++] = '\\';
96
  }
97

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

100
  char rand[8] = {0};
101
  taosRandStr(rand, tListLen(rand) - 1);
102
  snprintf(dstPath, PATH_MAX, tmpPath, taosGetPId(), rand);
103

104
#else
105

106
  char    tmpPath[PATH_MAX];
107
  int32_t len = strlen(inputTmpDir);
7✔
108
  (void)memcpy(tmpPath, inputTmpDir, len);
7✔
109
  static uint64_t seqId = 0;
110

111
  if (tmpPath[len - 1] != '/') {
7✔
112
    tmpPath[len++] = '/';
1✔
113
  }
114

115
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
7✔
116

117
  char rand[32] = {0};
7✔
118

119
  (void)snprintf(rand, sizeof(rand), "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
7✔
120

121
  (void)snprintf(dstPath, PATH_MAX, tmpPath, taosGetPId(), rand);
7✔
122

123
#endif
124
}
125

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

144
  TdFilePtr pFileFrom = NULL;
25✔
145
  TdFilePtr pFileTo = NULL;
25✔
146
  pFileFrom = taosOpenFile(from, TD_FILE_READ);
25✔
147
  if (pFileFrom == NULL) {
25✔
148
    code = terrno;
1✔
149
    goto _err;
1✔
150
  }
151

152
  pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
24✔
153
  if (pFileTo == NULL) {
24✔
154
    code = terrno;
1✔
155
    goto _err;
1✔
156
  }
157

158
  while (true) {
159
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
33✔
160
    if (bytes < 0) {
33!
161
      code = terrno;
×
162
      goto _err;
×
163
    }
164

165
    if (bytes == 0) break;
33!
166

167
    size += bytes;
33✔
168

169
    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) {
33!
170
      code = terrno;
×
171
      goto _err;
×
172
    }
173
    if (bytes < sizeof(buffer)) break;
33✔
174
  }
175

176
  code = taosFsyncFile(pFileTo);
23✔
177
  if (code != 0) {
23!
178
    goto _err;
×
179
  }
180

181
  TAOS_UNUSED(taosCloseFile(&pFileFrom));
23✔
182
  TAOS_UNUSED(taosCloseFile(&pFileTo));
23✔
183

184
  if (code != 0) {
23!
185
    terrno = code;
×
186
    return -1;
×
187
  }
188

189
  return size;
23✔
190

191
_err:
2✔
192

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

198
  terrno = code;
2✔
199
  return -1;
2✔
200
#endif
201
}
202

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

224
  return fp;
29✔
225
}
226

227
int32_t taosRemoveFile(const char *path) {
6,089✔
228
  OS_PARAM_CHECK(path);
6,089✔
229
  int32_t code = remove(path);
6,088✔
230
  if (-1 == code) {
6,083✔
231
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
3✔
232
    return terrno;
9✔
233
  }
234
  return code;
6,080✔
235
}
236

237
int32_t taosRenameFile(const char *oldName, const char *newName) {
6,945✔
238
  OS_PARAM_CHECK(oldName);
6,945✔
239
  OS_PARAM_CHECK(newName);
6,944✔
240
#ifdef WINDOWS
241
  bool finished = false;
242

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

250
  BOOL result = MoveFileTransacted(oldName, newName, NULL, NULL, MOVEFILE_REPLACE_EXISTING, transactionHandle);
251

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

265
  CloseHandle(transactionHandle);
266

267
  return finished ? 0 : terrno;
268
#else
269
#ifdef TD_ASTRA // TD_ASTRA_TODO
270
  if (taosCheckExistFile(newName)) taosRemoveFile(newName);
271
#endif
272
  int32_t code = rename(oldName, newName);
6,943✔
273
  if (-1 == code) {
6,941✔
274
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
9✔
275
    return terrno;
8✔
276
  }
277

278
  return TSDB_CODE_SUCCESS;
6,932✔
279
#endif
280
}
281

282
int32_t taosStatFile(const char *path, int64_t *size, int64_t *mtime, int64_t *atime) {
6,125✔
283
  OS_PARAM_CHECK(path);
6,125✔
284
#ifdef WINDOWS
285
  struct _stati64 fileStat;
286
  int32_t         code = _stati64(path, &fileStat);
287
#else
288
  struct stat fileStat;
289
  int32_t     code = stat(path, &fileStat);
6,124✔
290
#endif
291
  if (-1 == code) {
6,123✔
292
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
2,569✔
293
    return terrno;
2,571✔
294
  }
295

296
  if (size != NULL) {
3,554✔
297
    *size = fileStat.st_size;
2,577✔
298
  }
299

300
  if (mtime != NULL) {
3,554✔
301
    *mtime = fileStat.st_mtime;
305✔
302
  }
303

304
  if (atime != NULL) {
3,554!
305
    *atime = fileStat.st_atime;
×
306
  }
307

308
  return 0;
3,554✔
309
}
310

311
int32_t taosGetFileDiskID(const char *path, int64_t *diskid) {
64✔
312
  OS_PARAM_CHECK(path);
64✔
313
#ifdef WINDOWS
314
  struct _stati64 fileStat;
315
  int32_t         code = _stati64(path, &fileStat);
316
#else
317
  struct stat fileStat;
318
  int32_t     code = stat(path, &fileStat);
63✔
319
#endif
320
  if (-1 == code) {
63✔
321
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
322
    return terrno;
1✔
323
  }
324

325
  if (diskid != NULL) {
62✔
326
    *diskid = fileStat.st_dev;
61✔
327
  }
328

329
  return 0;
62✔
330
}
331

332
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
859✔
333
#ifdef WINDOWS
334
  if (pFile == NULL || pFile->hFile == NULL) {
335
    terrno = TSDB_CODE_INVALID_PARA;
336
    return terrno;
337
  }
338
  BY_HANDLE_FILE_INFORMATION bhfi;
339
  if (GetFileInformationByHandle(pFile->hFile, &bhfi) == FALSE) {
340
    DWORD error = GetLastError();
341
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
342
    return terrno;
343
  }
344

345
  if (stDev != NULL) {
346
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
347
  }
348

349
  if (stIno != NULL) {
350
    *stIno = (int64_t)((((uint64_t)bhfi.nFileIndexHigh) << 32) + bhfi.nFileIndexLow);
351
  }
352

353
#else
354
  if (pFile == NULL || pFile->fd < 0) {
859!
355
    terrno = TSDB_CODE_INVALID_PARA;
×
356
    return terrno;
1✔
357
  }
358

359
  struct stat fileStat;
360
  int32_t     code = fstat(pFile->fd, &fileStat);
859✔
361
  if (-1 == code) {
859!
362
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
363
    return terrno;
×
364
  }
365

366
  if (stDev != NULL) {
859!
367
    *stDev = fileStat.st_dev;
859✔
368
  }
369

370
  if (stIno != NULL) {
859!
371
    *stIno = fileStat.st_ino;
859✔
372
  }
373
#endif
374

375
  return 0;
859✔
376
}
377

378
FILE *taosOpenFileForStream(const char *path, int32_t tdFileOptions) {
481,355✔
379
  if (path == NULL) {
481,355✔
380
    terrno = TSDB_CODE_INVALID_PARA;
1✔
381
    return NULL;
1✔
382
  }
383
  char *mode = NULL;
481,354✔
384
  if (tdFileOptions & TD_FILE_APPEND) {
481,354✔
385
    mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
126!
386
  } else if (tdFileOptions & TD_FILE_TRUNC) {
481,228✔
387
    mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
25✔
388
  } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
481,203!
389
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
481,203!
390
  } else {
391
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
×
392
  }
393
  if (tdFileOptions & TD_FILE_EXCL) {
481,354!
394
    terrno = TSDB_CODE_INVALID_PARA;
×
395
    return NULL;
×
396
  }
397
  FILE *f = fopen(path, mode);
481,354✔
398
  if (NULL == f) {
481,350✔
399
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
665✔
400
  }
401
  return f;
481,350✔
402
}
403

404
#ifdef WINDOWS
405
HANDLE taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
406
  if (path == NULL) {
407
    terrno = TSDB_CODE_INVALID_PARA;
408
    return INVALID_HANDLE_VALUE;
409
  }
410
  DWORD openMode = 0;
411
  DWORD access = 0;
412
  DWORD fileFlag = FILE_ATTRIBUTE_NORMAL;
413
  DWORD shareMode = FILE_SHARE_READ;
414

415
  openMode = OPEN_EXISTING;
416
  if (tdFileOptions & TD_FILE_CREATE) {
417
    openMode = OPEN_ALWAYS;
418
  } else if (tdFileOptions & TD_FILE_EXCL) {
419
    openMode = CREATE_NEW;
420
  } else if ((tdFileOptions & TD_FILE_TRUNC)) {
421
    openMode = TRUNCATE_EXISTING;
422
    access |= GENERIC_WRITE;
423
  }
424
  if (tdFileOptions & TD_FILE_APPEND) {
425
    access |= FILE_APPEND_DATA;
426
  }
427
  if (tdFileOptions & TD_FILE_WRITE) {
428
    access |= GENERIC_WRITE;
429
  }
430

431
  shareMode |= FILE_SHARE_WRITE;
432

433
  access |= GENERIC_READ;
434

435
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
436
    fileFlag |= FILE_ATTRIBUTE_TEMPORARY;
437
  }
438
  if (tdFileOptions & TD_FILE_WRITE_THROUGH) {
439
    fileFlag |= FILE_FLAG_WRITE_THROUGH;
440
  }
441

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

459
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
460
  if (pFile == NULL || buf == NULL) {
461
    terrno = TSDB_CODE_INVALID_PARA;
462
    return terrno;
463
  }
464
#if FILE_WITH_LOCK
465
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
466
#endif
467
  if (pFile->hFile == NULL) {
468
#if FILE_WITH_LOCK
469
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
470
#endif
471
    terrno = TSDB_CODE_INVALID_PARA;
472
    return terrno;
473
  }
474

475
  int64_t res = 0;
476
  DWORD   bytesRead;
477
  if (!ReadFile(pFile->hFile, buf, count, &bytesRead, NULL)) {
478
    DWORD errCode = GetLastError();
479
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errCode);
480
    res = -1;
481
  } else {
482
    res = bytesRead;
483
  }
484
#if FILE_WITH_LOCK
485
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
486
#endif
487
  return res;
488
}
489

490
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
491
  if (pFile == NULL || pFile->hFile == NULL || buf == NULL) {
492
    terrno = TSDB_CODE_INVALID_PARA;
493
    return 0;
494
  }
495
#if FILE_WITH_LOCK
496
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
497
#endif
498

499
  DWORD bytesWritten;
500
  if (!WriteFile(pFile->hFile, buf, count, &bytesWritten, NULL)) {
501
    SET_ERRNO(GetLastError());
502
    terrno = TAOS_SYSTEM_WINAPI_ERROR(ERRNO);
503
    bytesWritten = -1;
504
  }
505

506
#if FILE_WITH_LOCK
507
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
508
#endif
509
  return bytesWritten;
510
}
511

512
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
513
  if (pFile == NULL || buf == NULL) {
514
    terrno = TSDB_CODE_INVALID_PARA;
515
    return 0;
516
  }
517
#if FILE_WITH_LOCK
518
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
519
#endif
520
  if (pFile->hFile == NULL) {
521
#if FILE_WITH_LOCK
522
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
523
#endif
524
    return 0;
525
  }
526

527
  DWORD      ret = 0;
528
  OVERLAPPED ol = {0};
529
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
530
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
531

532
  SetLastError(0);
533
  BOOL result = WriteFile(pFile->hFile, buf, count, &ret, &ol);
534
  if (!result) {
535
    SET_ERRNO(GetLastError());
536
    terrno = TAOS_SYSTEM_WINAPI_ERROR(ERRNO);
537
    ret = -1;
538
  }
539

540
#if FILE_WITH_LOCK
541
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
542
#endif
543
  return ret;
544
}
545

546
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
547
  if (pFile == NULL || pFile->hFile == NULL) {
548
    terrno = TSDB_CODE_INVALID_PARA;
549
    return -1;
550
  }
551
#if FILE_WITH_LOCK
552
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
553
#endif
554

555
  LARGE_INTEGER liOffset;
556
  liOffset.QuadPart = offset;
557
  if (!SetFilePointerEx(pFile->hFile, liOffset, NULL, whence)) {
558
    SET_ERRNO(GetLastError());
559
    terrno = TAOS_SYSTEM_WINAPI_ERROR(ERRNO);
560
    return -1;
561
  }
562

563
  liOffset.QuadPart = 0;
564
  if (!SetFilePointerEx(pFile->hFile, liOffset, &liOffset, FILE_CURRENT)) {
565
    SET_ERRNO(GetLastError());
566
    terrno = TAOS_SYSTEM_WINAPI_ERROR(ERRNO);
567
    return -1;
568
  }
569
#if FILE_WITH_LOCK
570
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
571
#endif
572
  return liOffset.QuadPart;
573
}
574

575
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int64_t *mtime) {
576
  if (pFile == NULL || pFile->hFile == NULL) {
577
    terrno = TSDB_CODE_INVALID_PARA;
578
    return terrno;
579
  }
580

581
  if (size != NULL) {
582
    LARGE_INTEGER fileSize;
583
    if (!GetFileSizeEx(pFile->hFile, &fileSize)) {
584
      SET_ERRNO(GetLastError());
585
      terrno = TAOS_SYSTEM_WINAPI_ERROR(ERRNO);
586
      return terrno;  // Error getting file size
587
    }
588
    *size = fileSize.QuadPart;
589
  }
590

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

607
int32_t taosLockFile(TdFilePtr pFile) {
608
  if (pFile == NULL || pFile->hFile == NULL) {
609
    terrno = TSDB_CODE_INVALID_PARA;
610
    return terrno;
611
  }
612

613
  BOOL          fSuccess = FALSE;
614
  LARGE_INTEGER fileSize;
615
  OVERLAPPED    overlapped = {0};
616

617
  fSuccess = LockFileEx(pFile->hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
618
                        0,           // reserved
619
                        ~0,          // number of bytes to lock low
620
                        ~0,          // number of bytes to lock high
621
                        &overlapped  // overlapped structure
622
  );
623
  if (!fSuccess) {
624
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
625
  }
626
  return 0;
627
}
628

629
int32_t taosUnLockFile(TdFilePtr pFile) {
630
  if (pFile == NULL || pFile->hFile == NULL) {
631
    return 0;
632
  }
633
  BOOL       fSuccess = FALSE;
634
  OVERLAPPED overlapped = {0};
635

636
  fSuccess = UnlockFileEx(pFile->hFile, 0, ~0, ~0, &overlapped);
637
  if (!fSuccess) {
638
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
639
  }
640
  return 0;
641
}
642

643
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
644
  if (pFile == NULL) {
645
    terrno = TSDB_CODE_INVALID_PARA;
646
    return terrno;
647
  }
648
  if (pFile->hFile == NULL) {
649
    printf("Ftruncate file error, hFile was null\n");
650
    terrno = TSDB_CODE_INVALID_PARA;
651
    return terrno;
652
  }
653

654
  LARGE_INTEGER li_0;
655
  li_0.QuadPart = (int64_t)0;
656
  BOOL cur = SetFilePointerEx(pFile->hFile, li_0, NULL, FILE_CURRENT);
657
  if (!cur) {
658
    printf("SetFilePointerEx Error getting current position in file.\n");
659
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
660
    return terrno;
661
  }
662

663
  LARGE_INTEGER li_size;
664
  li_size.QuadPart = l_size;
665
  BOOL cur2 = SetFilePointerEx(pFile->hFile, li_size, NULL, FILE_BEGIN);
666
  if (cur2 == 0) {
667
    int error = GetLastError();
668
    switch (error) {
669
      case ERROR_INVALID_HANDLE:
670
        SET_ERRNO(EBADF);
671
        break;
672
      default:
673
        SET_ERRNO(EIO);
674
        break;
675
    }
676
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
677
    return terrno;
678
  }
679

680
  if (!SetEndOfFile(pFile->hFile)) {
681
    int error = GetLastError();
682
    printf("SetEndOfFile GetLastError is:%d", error);
683
    switch (error) {
684
      case ERROR_INVALID_HANDLE:
685
        SET_ERRNO(EBADF);
686
        break;
687
      default:
688
        SET_ERRNO(EIO);
689
        break;
690
    }
691
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
692
    return terrno;
693
  }
694
  return 0;
695
}
696

697
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
698
  if (pFileOut == NULL || pFileIn == NULL) {
699
    terrno = TSDB_CODE_INVALID_PARA;
700
    return -1;
701
  }
702
  if (pFileIn->hFile == NULL || pFileOut->hFile == NULL) {
703
    terrno = TSDB_CODE_INVALID_PARA;
704
    return -1;
705
  }
706

707
  LARGE_INTEGER fileOffset;
708
  fileOffset.QuadPart = *offset;
709

710
  if (!SetFilePointerEx(pFileIn->hFile, fileOffset, &fileOffset, FILE_BEGIN)) {
711
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
712
    return -1;
713
  }
714

715
  int64_t writeLen = 0;
716
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
717

718
  DWORD bytesRead;
719
  DWORD bytesWritten;
720
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
721
    if (!ReadFile(pFileIn->hFile, buffer, _SEND_FILE_STEP_, &bytesRead, NULL)) {
722
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
723
      return writeLen;
724
    }
725

726
    if (bytesRead <= 0) {
727
      return writeLen;
728
    } else if (bytesRead < _SEND_FILE_STEP_) {
729
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
730
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
731
        return -1;
732
      } else {
733
        return (int64_t)(writeLen + bytesRead);
734
      }
735
    } else {
736
      if (!WriteFile(pFileOut->hFile, buffer, _SEND_FILE_STEP_, &bytesWritten, NULL)) {
737
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
738
        return -1;
739
      } else {
740
        writeLen += _SEND_FILE_STEP_;
741
      }
742
    }
743
  }
744

745
  int64_t remain = size - writeLen;
746
  if (remain > 0) {
747
    DWORD bytesRead;
748
    if (!ReadFile(pFileIn->hFile, buffer, (DWORD)remain, &bytesRead, NULL)) {
749
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
750
      return -1;
751
    }
752

753
    if (bytesRead <= 0) {
754
      return writeLen;
755
    } else {
756
      DWORD bytesWritten;
757
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
758
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
759
        return -1;
760
      } else {
761
        writeLen += bytesWritten;
762
      }
763
    }
764
  }
765
  return writeLen;
766
}
767

768
bool lastErrorIsFileNotExist() {
769
  DWORD dwError = GetLastError();
770
  return dwError == ERROR_FILE_NOT_FOUND;
771
}
772

773
#else
774
int taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
44,820✔
775
  if (path == NULL) {
44,820!
776
    terrno = TSDB_CODE_INVALID_PARA;
×
777
    return -1;
×
778
  }
779
  int access = O_BINARY;
44,820✔
780
  access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
44,820✔
781
  if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
44,820✔
782
    access |= O_RDWR;
14,747✔
783
  } else if (tdFileOptions & TD_FILE_WRITE) {
30,073✔
784
    access |= O_WRONLY;
10,923✔
785
  } else if (tdFileOptions & TD_FILE_READ) {
19,150✔
786
    access |= O_RDONLY;
19,041✔
787
  }
788
  access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
44,820✔
789
  access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
44,820✔
790
  access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
44,820✔
791
  access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
44,820✔
792
  access |= (tdFileOptions & TD_FILE_CLOEXEC) ? O_CLOEXEC : 0;
44,820✔
793

794
  int fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
44,820✔
795
  if (-1 == fd) {
44,818✔
796
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1,163✔
797
  }
798
  return fd;
44,821✔
799
}
800

801
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
667,112✔
802
  if (pFile == NULL || buf == NULL) {
667,112!
803
    terrno = TSDB_CODE_INVALID_PARA;
804
    return -1;
2✔
805
  }
806
  STUB_RAND_IO_ERR(terrno)
807
#if FILE_WITH_LOCK
808
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
667,172✔
809
#endif
810

811
  if (pFile->fd < 0) {
667,532✔
812
#if FILE_WITH_LOCK
813
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
6✔
814
#endif
815
    terrno = TSDB_CODE_INVALID_PARA;
×
816
    return -1;
×
817
  }
818

819
  int64_t leftbytes = count;
667,526✔
820
  int64_t readbytes;
821
  char   *tbuf = (char *)buf;
667,526✔
822
  int32_t code = 0;
667,526✔
823

824
  while (leftbytes > 0) {
1,334,604✔
825
#ifdef WINDOWS
826
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
827
#else
828
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
667,580✔
829
#endif
830
    if (readbytes < 0) {
667,484✔
831
      if (ERRNO == EINTR) {
7!
832
        continue;
×
833
      } else {
834
        code = TAOS_SYSTEM_ERROR(ERRNO);
7✔
835
#if FILE_WITH_LOCK
836
        (void)taosThreadRwlockUnlock(&(pFile->rwlock));
7✔
837
#endif
838
        terrno = code;
7✔
839
        return -1;
7✔
840
      }
841
    } else if (readbytes == 0) {
667,477✔
842
#if FILE_WITH_LOCK
843
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
399✔
844
#endif
845
      return (int64_t)(count - leftbytes);
399✔
846
    }
847

848
    leftbytes -= readbytes;
667,078✔
849
    tbuf += readbytes;
667,078✔
850
  }
851

852
#if FILE_WITH_LOCK
853
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
667,024✔
854
#endif
855

856
  return count;
667,136✔
857
}
858

859
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
9,991,344✔
860
  STUB_RAND_IO_ERR(terrno)
861
  if (pFile == NULL || buf == NULL) {
9,991,344!
862
    terrno = TSDB_CODE_INVALID_PARA;
863
    return 0;
2✔
864
  }
865
#if FILE_WITH_LOCK
866
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
9,991,800✔
867
#endif
868
  if (pFile->fd < 0) {
9,993,511!
869
#if FILE_WITH_LOCK
870
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
871
#endif
872
    terrno = TSDB_CODE_INVALID_PARA;
×
873
    return 0;
×
874
  }
875

876
  int64_t nleft = count;
9,993,512✔
877
  int64_t nwritten = 0;
9,993,512✔
878
  char   *tbuf = (char *)buf;
9,993,512✔
879
  int32_t code = 0;
9,993,512✔
880

881
  while (nleft > 0) {
19,986,938✔
882
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
9,993,484✔
883
    if (nwritten < 0) {
9,993,427✔
884
      if (ERRNO == EINTR) {
1!
885
        continue;
×
886
      }
887
      code = TAOS_SYSTEM_ERROR(ERRNO);
1✔
888
#if FILE_WITH_LOCK
889
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1✔
890
#endif
891
      terrno = code;
1✔
892
      return -1;
1✔
893
    }
894
    nleft -= nwritten;
9,993,426✔
895
    tbuf += nwritten;
9,993,426✔
896
  }
897

898
#if FILE_WITH_LOCK
899
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
9,993,454✔
900
#endif
901

902
  return count;
9,992,996✔
903
}
904

905
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
418,642✔
906
  STUB_RAND_IO_ERR(terrno)
907
  if (pFile == NULL || buf == NULL) {
418,642!
908
    terrno = TSDB_CODE_INVALID_PARA;
909
    return 0;
2✔
910
  }
911

912
  int32_t code = 0;
418,645✔
913
#if FILE_WITH_LOCK
914
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
418,645✔
915
#endif
916

917
#if FILE_WITH_LOCK
918
  if (pFile->fd < 0) {
418,663!
919
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
920
    return 0;
×
921
  }
922
#endif
923
#ifndef TD_ASTRA
924
  int64_t ret = pwrite(pFile->fd, buf, count, offset);
418,663✔
925
  if (-1 == ret) {
418,657!
926
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
927
  }
928
#else  // TD_ASTRA_TODO
929
  int64_t ret = -1;
930
  int64_t cur = lseek(pFile->fd, 0, SEEK_CUR);
931
  if (cur < 0) {
932
    code = TAOS_SYSTEM_ERROR(ERRNO);
933
    goto _exit;
934
  }
935
  if (lseek(pFile->fd, offset, SEEK_SET) < 0) {
936
    code = TAOS_SYSTEM_ERROR(ERRNO);
937
    goto _exit;
938
  }
939
  if ((ret = write(pFile->fd, buf, count)) < 0) {
940
    code = TAOS_SYSTEM_ERROR(ERRNO);
941
    goto _exit;
942
  }
943
_exit:
944
  if (cur >= 0 && lseek(pFile->fd, cur, SEEK_SET) < 0) {
945
    code = TAOS_SYSTEM_ERROR(ERRNO);
946
  }
947
#endif
948
#if FILE_WITH_LOCK
949
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
418,657✔
950
#endif
951

952
  if (code) {
418,662!
953
    terrno = code;
954
  }
955

956
  return ret;
418,664✔
957
}
958

959
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
484,161✔
960
  if (pFile == NULL || pFile->fd < 0) {
484,161!
961
    terrno = TSDB_CODE_INVALID_PARA;
962
    return -1;
1✔
963
  }
964
#if FILE_WITH_LOCK
965
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
484,164✔
966
#endif
967

968
  int32_t code = 0;
484,171✔
969

970
  int64_t ret = lseek(pFile->fd, offset, whence);
484,171✔
971
  if (-1 == ret) {
484,162!
972
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
973
  }
974

975
#if FILE_WITH_LOCK
976
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
484,162✔
977
#endif
978

979
  if (code) {
484,167!
980
    terrno = code;
×
981
    return -1;
×
982
  }
983

984
  return ret;
484,167✔
985
}
986

987
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int64_t *mtime) {
2,756✔
988
  if (pFile == NULL) {
2,756✔
989
    terrno = TSDB_CODE_INVALID_PARA;
2✔
990
    return terrno;
2✔
991
  }
992

993
  if (pFile->fd < 0) {
2,754!
994
    terrno = TSDB_CODE_INVALID_PARA;
×
995
    return terrno;
×
996
  }
997

998
  struct stat fileStat;
999
  int32_t     code = fstat(pFile->fd, &fileStat);
2,754✔
1000
  if (-1 == code) {
2,754✔
1001
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
1002
    return terrno;
×
1003
  }
1004

1005
  if (size != NULL) {
2,753!
1006
    *size = fileStat.st_size;
2,753✔
1007
  }
1008

1009
  if (mtime != NULL) {
2,753!
1010
    *mtime = fileStat.st_mtime;
×
1011
  }
1012

1013
  return 0;
2,753✔
1014
}
1015

1016
int32_t taosLockFile(TdFilePtr pFile) {
1,099✔
1017
  if (NULL == pFile || pFile->fd < 0) {
1,099!
1018
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1019
    return terrno;
2✔
1020
  }
1021
#ifndef TD_ASTRA
1022
  int32_t code = (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
1,097✔
1023
  if (-1 == code) {
1,097✔
1024
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
280✔
1025
    return terrno;
280✔
1026
  }
1027
#else // TD_ASTRA_TODO
1028
  struct flock lock;
1029
  lock.l_type = F_WRLCK;
1030
  lock.l_whence = SEEK_SET;
1031
  lock.l_start = 0;
1032
  lock.l_len = 0;
1033
  int32_t code = fcntl(pFile->fd, F_SETLK, &lock);
1034
  if (-1 == code) {
1035
    //    terrno = TAOS_SYSTEM_ERROR(ERRNO); // TD_ASTRA_TODO
1036
    //    return terrno;                     // TD_ASTRA_TODO
1037
  }
1038
#endif
1039
  return 0;
817✔
1040
}
1041

1042
int32_t taosUnLockFile(TdFilePtr pFile) {
345✔
1043
  if (NULL == pFile || pFile->fd < 0) {
345!
1044
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1045
    return terrno;
2✔
1046
  }
1047
#ifndef TD_ASTRA
1048
  int32_t code = (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
343✔
1049
  if (-1 == code) {
343!
1050
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1051
    return terrno;
×
1052
  }
1053
#else // TD_ASTRA_TODO
1054
  struct flock lock;
1055
  lock.l_type = F_UNLCK;
1056
  lock.l_whence = SEEK_SET;
1057
  lock.l_start = 0;
1058
  lock.l_len = 0;
1059
  int32_t code = fcntl(pFile->fd, F_SETLK, &lock);
1060
  if (-1 == code) {
1061
    //    terrno = TAOS_SYSTEM_ERROR(ERRNO);// TD_ASTRA_TODO
1062
    //    return terrno;// TD_ASTRA_TODO
1063
  }
1064
#endif
1065
  return 0;
343✔
1066
}
1067

1068
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
91✔
1069
  if (NULL == pFile || pFile->fd < 0) {
91!
1070
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1071
    return terrno;
2✔
1072
  }
1073

1074
  int32_t code = ftruncate(pFile->fd, l_size);
89✔
1075
  if (-1 == code) {
89!
1076
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1077
    return terrno;
×
1078
  }
1079
  return 0;
89✔
1080
}
1081

1082
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
3✔
1083
  if (pFileOut == NULL || pFileIn == NULL) {
3!
1084
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1085
    return -1;
3✔
1086
  }
1087
  if (pFileIn->fd < 0 || pFileOut->fd < 0) {
×
1088
    terrno = TSDB_CODE_INVALID_PARA;
×
1089
    return -1;
×
1090
  }
1091

1092
#if defined(_TD_DARWIN_64) || defined(TD_ASTRA)  // TD_ASTRA_TODO
1093
  if (lseek(pFileIn->fd, (int32_t)(*offset), 0) < 0) {
1094
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1095
    return -1;
1096
  }
1097
  int64_t writeLen = 0;
1098
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
1099

1100
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
1101
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
1102
    if (rlen <= 0) {
1103
      return writeLen;
1104
    } else if (rlen < _SEND_FILE_STEP_) {
1105
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
1106
      return (int64_t)(writeLen + rlen);
1107
    } else {
1108
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
1109
      writeLen += _SEND_FILE_STEP_;
1110
    }
1111
  }
1112

1113
  int64_t remain = size - writeLen;
1114
  if (remain > 0) {
1115
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
1116
    if (rlen <= 0) {
1117
      return writeLen;
1118
    } else {
1119
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
1120
      writeLen += remain;
1121
    }
1122
  }
1123
  return writeLen;
1124

1125
#else  // for linux
1126

1127
  int64_t leftbytes = size;
×
1128
  int64_t sentbytes;
1129

1130
  while (leftbytes > 0) {
×
1131
#ifdef _TD_ARM_32
1132
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int *)offset, leftbytes);
1133
#else
1134
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
×
1135
#endif
1136
    if (sentbytes == -1) {
×
1137
      if (ERRNO == EINTR || ERRNO == EAGAIN || ERRNO == EWOULDBLOCK) {
×
1138
        continue;
×
1139
      } else {
1140
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1141
        return -1;
×
1142
      }
1143
    } else if (sentbytes == 0) {
×
1144
      return (int64_t)(size - leftbytes);
×
1145
    }
1146

1147
    leftbytes -= sentbytes;
×
1148
  }
1149

1150
  return size;
×
1151
#endif
1152
}
1153

1154
bool lastErrorIsFileNotExist() { return terrno == TAOS_SYSTEM_ERROR(ENOENT); }
837✔
1155

1156
#endif  // WINDOWS
1157

1158
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
526,177✔
1159
  if (path == NULL) {
526,177✔
1160
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1161
    return NULL;
1✔
1162
  }
1163
  STUB_RAND_IO_ERR(NULL)
1164
  FILE *fp = NULL;
526,176✔
1165
#ifdef WINDOWS
1166
  HANDLE hFile = NULL;
1167
#else
1168
  int fd = -1;
526,176✔
1169
#endif
1170
  if (tdFileOptions & TD_FILE_STREAM) {
526,176✔
1171
    fp = taosOpenFileForStream(path, tdFileOptions);
481,354✔
1172
    if (fp == NULL) return NULL;
481,350✔
1173
  } else {
1174
#ifdef WINDOWS
1175
    hFile = taosOpenFileNotStream(path, tdFileOptions);
1176
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
1177
#else
1178
    fd = taosOpenFileNotStream(path, tdFileOptions);
44,822✔
1179
    if (fd == -1) return NULL;
44,802✔
1180
#endif
1181
  }
1182

1183
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
524,321!
1184
  if (pFile == NULL) {
524,352!
1185
#ifdef WINDOWS
1186
    if (hFile != NULL) CloseHandle(hFile);
1187
#else
1188
    if (fd >= 0) (void)close(fd);
×
1189
#endif
1190
    if (fp != NULL) (void)fclose(fp);
×
1191
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
1192
    return NULL;
×
1193
  }
1194

1195
#if FILE_WITH_LOCK
1196
  (void)taosThreadRwlockInit(&(pFile->rwlock), NULL);
524,352✔
1197
#endif
1198
  pFile->fp = fp;
524,310✔
1199
  pFile->refId = 0;
524,310✔
1200

1201
#ifdef WINDOWS
1202
  pFile->hFile = hFile;
1203
  pFile->tdFileOptions = tdFileOptions;
1204
  // do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
1205
  // the file handle, as well as the space on disk.
1206
#else
1207
  pFile->fd = fd;
524,310✔
1208
  // Remove it instantly, so when the program exits normally/abnormally, the file
1209
  // will be automatically remove by OS.
1210
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
524,310✔
1211
    if (-1 == unlink(path)) {
6✔
1212
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
2✔
1213
      (void)close(fd);
×
1214
      taosMemoryFree(pFile);
×
1215
      return NULL;
×
1216
    }
1217
  }
1218
#endif
1219

1220
  return pFile;
524,308✔
1221
}
1222

1223
int32_t taosCloseFile(TdFilePtr *ppFile) {
645,586✔
1224
  int32_t code = 0;
645,586✔
1225
  if (ppFile == NULL || *ppFile == NULL) {
645,586!
1226
    return 0;
121,501✔
1227
  }
1228
#if FILE_WITH_LOCK
1229
  (void)taosThreadRwlockWrlock(&((*ppFile)->rwlock));
524,085✔
1230
#endif
1231
  if ((*ppFile)->fp != NULL) {
524,071✔
1232
    TAOS_UNUSED(fflush((*ppFile)->fp));
480,668✔
1233
    TAOS_UNUSED(fclose((*ppFile)->fp));
480,667✔
1234
    (*ppFile)->fp = NULL;
480,667✔
1235
  }
1236
#ifdef WINDOWS
1237
  if ((*ppFile)->hFile != NULL) {
1238
    // FlushFileBuffers((*ppFile)->hFile);
1239
    if (!CloseHandle((*ppFile)->hFile)) {
1240
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1241
      code = -1;
1242
    }
1243
    (*ppFile)->hFile = NULL;
1244
#else
1245
  if ((*ppFile)->fd >= 0) {
524,070✔
1246
    // warning: never fsync silently in base lib
1247
    /*fsync((*ppFile)->fd);*/
1248
    code = close((*ppFile)->fd);
43,412✔
1249
    if (-1 == code) {
43,429!
1250
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
1251
    }
1252
    (*ppFile)->fd = -1;
43,437✔
1253
#endif
1254
  }
1255
  (*ppFile)->refId = 0;
524,095✔
1256
#if FILE_WITH_LOCK
1257
  (void)taosThreadRwlockUnlock(&((*ppFile)->rwlock));
524,095✔
1258
  (void)taosThreadRwlockDestroy(&((*ppFile)->rwlock));
524,107✔
1259
#endif
1260
  taosMemoryFree(*ppFile);
524,024!
1261
  *ppFile = NULL;
524,083✔
1262
  return code;
524,083✔
1263
}
1264

1265
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
84,157✔
1266
  STUB_RAND_IO_ERR(terrno)
1267
  if (pFile == NULL) {
84,157✔
1268
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1269
    return -1;
1✔
1270
  }
1271

1272
  int32_t code = 0;
84,156✔
1273

1274
#ifdef WINDOWS
1275
#if FILE_WITH_LOCK
1276
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
1277
#endif
1278

1279
  if (pFile->hFile == NULL) {
1280
#if FILE_WITH_LOCK
1281
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1282
#endif
1283

1284
    terrno = TSDB_CODE_INVALID_PARA;
1285
    return -1;
1286
  }
1287

1288
  DWORD      ret = 0;
1289
  OVERLAPPED ol = {0};
1290
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
1291
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
1292

1293
  SetLastError(0);
1294
  BOOL result = ReadFile(pFile->hFile, buf, count, &ret, &ol);
1295
  if (!result && GetLastError() != ERROR_HANDLE_EOF) {
1296
    code = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1297
    ret = -1;
1298
  }
1299
#else
1300
#if FILE_WITH_LOCK
1301
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
84,156✔
1302
#endif
1303

1304
  if (pFile->fd < 0) {
84,160!
1305
#if FILE_WITH_LOCK
1306
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
1307
#endif
1308
    terrno = TSDB_CODE_INVALID_PARA;
×
1309
    return -1;
×
1310
  }
1311
#ifndef TD_ASTRA
1312
  int64_t ret = pread(pFile->fd, buf, count, offset);
84,160✔
1313
  if (-1 == ret) {
84,160!
1314
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
1315
  }
1316
#else  // TD_ASTRA_TODO
1317
  int64_t ret = -1;
1318
  int64_t cur = lseek(pFile->fd, 0, SEEK_CUR);
1319
  if (cur < 0) {
1320
    code = TAOS_SYSTEM_ERROR(ERRNO);
1321
    goto _exit;
1322
  }
1323
  if (lseek(pFile->fd, offset, SEEK_SET) < 0) {
1324
    code = TAOS_SYSTEM_ERROR(ERRNO);
1325
    goto _exit;
1326
  }
1327
  if ((ret = read(pFile->fd, buf, count)) < 0) {
1328
    code = TAOS_SYSTEM_ERROR(ERRNO);
1329
    goto _exit;
1330
  }
1331
_exit:
1332
  if (cur >= 0 && lseek(pFile->fd, cur, SEEK_SET) < 0) {
1333
    code = TAOS_SYSTEM_ERROR(ERRNO);
1334
  }
1335
#endif
1336
#endif
1337
#if FILE_WITH_LOCK
1338
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
84,160✔
1339
#endif
1340

1341
  if (code) {
84,159!
1342
    terrno = code;
1343
    return -1;
×
1344
  }
1345

1346
  return ret;
84,160✔
1347
}
1348

1349
int32_t taosFsyncFile(TdFilePtr pFile) {
40,815✔
1350
  if (pFile == NULL) {
40,815✔
1351
    return 0;
137✔
1352
  }
1353

1354
  int32_t code = 0;
40,678✔
1355
  // this implementation is WRONG
1356
  // fflush is not a replacement of fsync
1357
  if (pFile->fp != NULL) {
40,678✔
1358
    code = fflush(pFile->fp);
751✔
1359
    if (0 != code) {
751!
1360
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1361
      return terrno;
×
1362
    }
1363

1364
    return 0;
751✔
1365
  }
1366

1367
#ifdef WINDOWS
1368
  if (pFile->hFile != NULL) {
1369
    if (pFile->tdFileOptions & TD_FILE_WRITE_THROUGH) {
1370
      return 0;
1371
    }
1372
    bool ret = FlushFileBuffers(pFile->hFile);
1373
    if (!ret) {
1374
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1375
      return terrno;
1376
    }
1377
    return 0;
1378
  }
1379
#else
1380
  if (pFile->fd >= 0) {
39,927✔
1381
    code = fsync(pFile->fd);
39,925✔
1382
    if (-1 == code) {
39,926!
1383
#ifndef TD_ASTRA
1384
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
1385
#else
1386
      terrno = 0;  // TD_ASTRA_TODO
1387
#endif
1388
      return terrno;
×
1389
    }
1390
  }
1391
#endif
1392

1393
  return 0;
39,937✔
1394
}
1395

1396
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
1,897,309✔
1397
  if (pFile == NULL || pFile->fp == NULL) {
1,897,309!
1398
    return;
900,003✔
1399
  }
1400
  va_list ap;
1401
  va_start(ap, format);
997,306✔
1402
  (void)vfprintf(pFile->fp, format, ap);
997,306✔
1403
  va_end(ap);
997,306✔
1404
}
1405

1406
bool taosValidFile(TdFilePtr pFile) {
3✔
1407
#ifdef WINDOWS
1408
  return pFile != NULL && pFile->hFile != NULL;
1409
#else
1410
  return pFile != NULL && pFile->fd > 0;
3!
1411
#endif
1412
}
1413

1414
int32_t taosUmaskFile(int32_t maskVal) {
1,245✔
1415
#ifdef WINDOWS
1416
  return 0;
1417
#else
1418
  return umask(maskVal);
1,245✔
1419
#endif
1420
}
1421

1422
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
3✔
1423
  int64_t ret = -1;
3✔
1424
  int32_t code = 0;
3✔
1425

1426
  if (pFile == NULL || ptrBuf == NULL) {
3!
1427
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1428
    goto END;
3✔
1429
  }
1430
  if (*ptrBuf != NULL) {
×
1431
    taosMemoryFreeClear(*ptrBuf);
×
1432
  }
1433

1434
  if (pFile->fp == NULL) {
×
1435
    terrno = TSDB_CODE_INVALID_PARA;
×
1436
    goto END;
×
1437
  }
1438

1439
#if FILE_WITH_LOCK
1440
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
×
1441
#endif
1442

1443
#ifdef WINDOWS
1444
  size_t bufferSize = 512;
1445
  *ptrBuf = taosMemoryMalloc(bufferSize);
1446
  if (*ptrBuf == NULL) {
1447
    goto END;
1448
  }
1449

1450
  size_t bytesRead = 0;
1451
  size_t totalBytesRead = 0;
1452

1453
  while (1) {
1454
    char *result = fgets(*ptrBuf + totalBytesRead, bufferSize - totalBytesRead, pFile->fp);
1455
    if (result == NULL) {
1456
      if (feof(pFile->fp)) {
1457
        break;
1458
      } else {
1459
        ret = -1;
1460
        terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
1461
        taosMemoryFreeClear(*ptrBuf);
1462
        goto END;
1463
      }
1464
    }
1465
    bytesRead = strlen(*ptrBuf + totalBytesRead);
1466
    totalBytesRead += bytesRead;
1467

1468
    if (totalBytesRead < bufferSize - 1 || (*ptrBuf)[totalBytesRead - 1] == '\n') {
1469
      break;
1470
    }
1471

1472
    bufferSize += 512;
1473
    void *newBuf = taosMemoryRealloc(*ptrBuf, bufferSize);
1474
    if (newBuf == NULL) {
1475
      taosMemoryFreeClear(*ptrBuf);
1476
      goto END;
1477
    }
1478

1479
    *ptrBuf = newBuf;
1480
  }
1481

1482
  (*ptrBuf)[totalBytesRead] = '\0';
1483
  ret = (totalBytesRead > 0 ? totalBytesRead : -1); // -1 means EOF
1484
#elif defined(TD_ASTRA)
1485
  size_t bufsize = 128;
1486
  if (*ptrBuf == NULL) {
1487
    *ptrBuf = (char *)taosMemoryMalloc(bufsize);
1488
    if (*ptrBuf == NULL) {
1489
      goto END;
1490
    }
1491
  }
1492
  size_t pos = 0;
1493
  int    c;
1494
  while ((c = fgetc(pFile->fp)) != EOF) {
1495
    if (pos + 1 >= bufsize) {
1496
      size_t new_size = bufsize << 1;
1497
      char  *new_line = (char *)taosMemoryRealloc(*ptrBuf, new_size);
1498
      if (new_line == NULL) {
1499
        goto END;
1500
      }
1501
      *ptrBuf = new_line;
1502
      bufsize = new_size;
1503
    }
1504
    (*ptrBuf)[pos++] = (char)c;
1505
    if (c == '\n') {
1506
      break;
1507
    }
1508
  }
1509
  if (pos == 0 && c == EOF) {
1510
    goto END;
1511
  }
1512
  (*ptrBuf)[pos] = '\0';
1513
  ret = pos;
1514
#else
1515
  size_t len = 0;
×
1516
  ret = getline(ptrBuf, &len, pFile->fp);
×
1517
  if (-1 == ret) {
×
1518
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1519
  }
1520
#endif
1521

1522
END:
×
1523

1524
#if FILE_WITH_LOCK
1525
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
3✔
1526
#endif
1527

1528
  return ret;
3✔
1529
}
1530

1531
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
1,283,395✔
1532
  if (pFile == NULL || buf == NULL) {
1,283,395✔
1533
    terrno = TSDB_CODE_INVALID_PARA;
3✔
1534
    return terrno;
3✔
1535
  }
1536

1537
  if (pFile->fp == NULL) {
1,283,392!
1538
    terrno = TSDB_CODE_INVALID_PARA;
×
1539
    return terrno;
×
1540
  }
1541

1542
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
1,283,392✔
1543
    if (feof(pFile->fp)) {
703!
1544
      return 0;
703✔
1545
    } else {
1546
      terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
×
1547
      return terrno;
×
1548
    }
1549
  }
1550

1551
  return strlen(buf);
1,282,687✔
1552
}
1553

1554
int32_t taosEOFFile(TdFilePtr pFile) {
1,193,488✔
1555
  if (pFile == NULL) {
1,193,488✔
1556
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1557
    return -1;
2✔
1558
  }
1559
  if (pFile->fp == NULL) {
1,193,486!
1560
    terrno = TSDB_CODE_INVALID_PARA;
×
1561
    return -1;
×
1562
  }
1563

1564
  return feof(pFile->fp);
1,193,486✔
1565
}
1566

1567
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
14,057✔
1568
  if (pathname == NULL) {
14,057✔
1569
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1570
    return false;  // invalid parameter
1✔
1571
  }
1572
  int flags = 0;
14,056✔
1573

1574
  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
14,056!
1575
    flags |= F_OK;
14,057✔
1576
  }
1577

1578
  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
14,056✔
1579
    flags |= R_OK;
1,134✔
1580
  }
1581

1582
  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
14,056✔
1583
    flags |= W_OK;
1,134✔
1584
  }
1585

1586
  if (tdFileAccessOptions & TD_FILE_ACCESS_EXEC_OK) {
14,056!
1587
    flags |= X_OK;
×
1588
  }
1589
#ifdef WINDOWS
1590
  return _access(pathname, flags) == 0;
1591
#else
1592
  return access(pathname, flags) == 0;
14,056✔
1593
#endif
1594
}
1595

1596
bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };
12,922✔
1597

1598
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
6✔
1599
  OS_PARAM_CHECK(srcFileName);
6✔
1600
  OS_PARAM_CHECK(destFileName);
5✔
1601
  int32_t   compressSize = 163840;
4✔
1602
  int32_t   ret = 0;
4✔
1603
  int32_t   len = 0;
4✔
1604
  gzFile    dstFp = NULL;
4✔
1605
  TdFilePtr pSrcFile = NULL;
4✔
1606

1607
  char *data = taosMemoryMalloc(compressSize);
4!
1608
  if (NULL == data) {
4!
1609
    return terrno;
×
1610
  }
1611

1612
  pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ | TD_FILE_STREAM);
4✔
1613
  if (pSrcFile == NULL) {
4✔
1614
    ret = terrno;
1✔
1615
    goto cmp_end;
1✔
1616
  }
1617

1618
  int access = O_BINARY | O_WRONLY | O_TRUNC | O_CREAT;
3✔
1619
#ifdef WINDOWS
1620
  int32_t pmode = _S_IREAD | _S_IWRITE;
1621
#else
1622
  int32_t pmode = S_IRWXU | S_IRWXG | S_IRWXO;
3✔
1623
#endif
1624
  int fd = open(destFileName, access, pmode);
3✔
1625
  if (-1 == fd) {
3✔
1626
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
1627
    ret = terrno;
1✔
1628
    goto cmp_end;
1✔
1629
  }
1630

1631
  // Both gzclose() and fclose() will close the associated fd, so they need to have different fds.
1632
  FileFd gzFd = dup(fd);
2✔
1633
  if (-1 == gzFd) {
2!
1634
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1635
    ret = terrno;
×
1636
    goto cmp_end;
×
1637
  }
1638
  dstFp = gzdopen(gzFd, "wb6f");
2✔
1639
  if (dstFp == NULL) {
2!
1640
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1641
    ret = terrno;
×
1642
    (void)close(gzFd);
×
1643
    goto cmp_end;
×
1644
  }
1645

1646
  while (!feof(pSrcFile->fp)) {
4✔
1647
    len = (int32_t)fread(data, 1, compressSize, pSrcFile->fp);
2✔
1648
    if (len > 0) {
2!
1649
      if (gzwrite(dstFp, data, len) == 0) {
2!
1650
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1651
        ret = terrno;
×
1652
        goto cmp_end;
×
1653
      }
1654
    }
1655
  }
1656

1657
cmp_end:
2✔
1658

1659
  if (fd >= 0) {
4✔
1660
    TAOS_SKIP_ERROR(close(fd));
3✔
1661
  }
1662
  if (pSrcFile) {
4✔
1663
    TAOS_SKIP_ERROR(taosCloseFile(&pSrcFile));
3✔
1664
  }
1665

1666
  if (dstFp) {
4✔
1667
    TAOS_SKIP_ERROR(gzclose(dstFp));
2✔
1668
  }
1669

1670
  taosMemoryFree(data);
4!
1671

1672
  return ret;
4✔
1673
}
1674

1675
int32_t taosSetFileHandlesLimit() {
665✔
1676
#ifdef WINDOWS
1677
  const int max_handles = 8192;
1678
  int       res = _setmaxstdio(max_handles);
1679
  return res == max_handles ? 0 : -1;
1680
#endif
1681
  return 0;
665✔
1682
}
1683

1684
int32_t taosLinkFile(char *src, char *dst) {
13✔
1685
#ifndef WINDOWS
1686
  if (-1 == link(src, dst)) {
13✔
1687
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
1688
    return terrno;
1✔
1689
  }
1690
#endif
1691
  return 0;
12✔
1692
}
1693

1694
FILE *taosOpenCFile(const char *filename, const char *mode) {
3✔
1695
  if (filename == NULL || mode == NULL) {
3✔
1696
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1697
    return NULL;
2✔
1698
  }
1699
  STUB_RAND_IO_ERR(NULL)
1700
  FILE *f = fopen(filename, mode);
1✔
1701
  if (NULL == f) {
1!
1702
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
1703
  }
1704
  return f;
1✔
1705
}
1706

1707
int taosSeekCFile(FILE *file, int64_t offset, int whence) {
1✔
1708
  if (NULL == file) {
1!
1709
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1710
    return terrno;
1✔
1711
  }
1712
#ifdef WINDOWS
1713
  return _fseeki64(file, offset, whence);
1714
#else
1715
  int     code = fseeko(file, offset, whence);
×
1716
  if (-1 == code) {
×
1717
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1718
    code = terrno;
×
1719
  }
1720
  return code;
×
1721
#endif
1722
}
1723

1724
size_t taosReadFromCFile(void *buffer, size_t size, size_t count, FILE *stream) {
2✔
1725
  if (buffer == NULL || stream == NULL) {
2!
1726
    terrno = TSDB_CODE_INVALID_PARA;
2✔
1727
    return 0;
2✔
1728
  }
1729
  STUB_RAND_IO_ERR(terrno)
1730
  return fread(buffer, size, count, stream);
×
1731
}
1732

1733
#if 0
1734
size_t taosWriteToCFile(const void *ptr, size_t size, size_t nitems, FILE *stream) {
1735
  STUB_RAND_IO_ERR(terrno)
1736
  return fwrite(ptr, size, nitems, stream);
1737
}
1738
#endif
1739

1740
int taosCloseCFile(FILE *f) { return fclose(f); }
×
1741

1742
int taosSetAutoDelFile(char *path) {
×
1743
#ifdef WINDOWS
1744
  bool succ = SetFileAttributes(path, FILE_ATTRIBUTE_TEMPORARY);
1745
  if (succ) {
1746
    return 0;
1747
  } else {
1748
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1749
    return terrno;
1750
  }
1751
#else
1752
  if (-1 == unlink(path)) {
×
1753
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1754
    return terrno;
×
1755
  }
1756
  return 0;
×
1757
#endif
1758
}
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