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

taosdata / TDengine / #3525

10 Nov 2024 03:50AM UTC coverage: 60.818% (-0.08%) from 60.898%
#3525

push

travis-ci

web-flow
Merge pull request #28709 from taosdata/main

merge: from main to 3.0 branch

118634 of 249004 branches covered (47.64%)

Branch coverage included in aggregate %.

136 of 169 new or added lines in 23 files covered. (80.47%)

542 existing lines in 129 files now uncovered.

199071 of 273386 relevant lines covered (72.82%)

15691647.46 hits per line

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

59.66
/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) {
886,347✔
83
#ifdef WINDOWS
84

85
  char tmpPath[PATH_MAX];
86

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

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

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

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

100
#else
101

102
  char    tmpPath[PATH_MAX];
103
  int32_t len = strlen(inputTmpDir);
886,347✔
104
  (void)memcpy(tmpPath, inputTmpDir, len);
886,347✔
105
  static uint64_t seqId = 0;
106

107
  if (tmpPath[len - 1] != '/') {
886,347!
108
    tmpPath[len++] = '/';
×
109
  }
110

111
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
886,347✔
112

113
  char rand[32] = {0};
886,347✔
114

115
  (void)snprintf(rand, sizeof(rand), "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
886,347✔
116

117
  (void)snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
887,390✔
118

119
#endif
120
}
887,143✔
121

122
int64_t taosCopyFile(const char *from, const char *to) {
52✔
123
#ifdef WINDOWS
124
  if (CopyFile(from, to, 0)) {
125
    return 1;
126
  } else {
127
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
128
    return -1;
129
  }
130
#else
131
  char    buffer[4096];
132
  int64_t size = 0;
52✔
133
  int64_t bytes;
134
  int32_t code = TSDB_CODE_SUCCESS;
52✔
135

136
  // fidfrom = open(from, O_RDONLY);
137
  TdFilePtr pFileFrom = taosOpenFile(from, TD_FILE_READ);
52✔
138
  if (pFileFrom == NULL) {
52!
139
    code = terrno;
×
140
    goto _err;
×
141
  }
142

143
  // fidto = open(to, O_WRONLY | O_CREAT | O_EXCL, 0755);
144
  TdFilePtr pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
52✔
145
  if (pFileTo == NULL) {
52!
146
    code = terrno;
×
147
    goto _err;
×
148
  }
149

150
  while (true) {
151
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
52✔
152
    if (bytes < 0) {
52!
153
      code = terrno;
×
154
      goto _err;
×
155
    }
156

157
    if (bytes == 0) break;
52!
158

159
    size += bytes;
52✔
160

161
    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) {
52!
162
      code = terrno;
×
163
      goto _err;
×
164
    }
165
    if (bytes < sizeof(buffer)) break;
52!
166
  }
167

168
  code = taosFsyncFile(pFileTo);
52✔
169
  if (code != 0) {
52!
170
    goto _err;
×
171
  }
172

173
  TAOS_UNUSED(taosCloseFile(&pFileFrom));
52✔
174
  TAOS_UNUSED(taosCloseFile(&pFileTo));
52✔
175

176
  if (code != 0) {
52!
177
    terrno = code;
×
178
    return -1;
×
179
  }
180

181
  return size;
52✔
182

183
_err:
×
184

185
  if (pFileFrom != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileFrom));
×
186
  if (pFileTo != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileTo));
×
187
  /* coverity[+retval] */
188
  TAOS_SKIP_ERROR(taosRemoveFile(to));
×
189

190
  terrno = code;
×
191
  return -1;
×
192
#endif
193
}
194

195
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) {
×
196
  TdFilePtr fp = taosOpenFile(path, tdFileOptions);
×
197
  if (!fp) {
×
198
    if (terrno == TAOS_SYSTEM_ERROR(ENOENT)) {
×
199
      // Try to create directory recursively
200
      char s[PATH_MAX];
201
      tstrncpy(s, path, sizeof(s));
×
202
      if (taosMulMkDir(taosDirName(s)) != 0) {
×
203
        return NULL;
×
204
      }
205
      fp = taosOpenFile(path, tdFileOptions);
×
206
      if (!fp) {
×
207
        return NULL;
×
208
      }
209
    }
210
  }
211

212
  return fp;
×
213
}
214

215
int32_t taosRemoveFile(const char *path) {
1,209,346✔
216
  int32_t code = remove(path);
1,209,346✔
217
  if (-1 == code) {
1,209,357✔
218
    terrno = TAOS_SYSTEM_ERROR(errno);
887,403✔
219
    return terrno;
887,399✔
220
  }
221
  return code;
321,954✔
222
}
223

224
int32_t taosRenameFile(const char *oldName, const char *newName) {
275,968✔
225
#ifdef WINDOWS
226
  bool finished = false;
227

228
  HANDLE transactionHandle = CreateTransaction(NULL, NULL, 0, 0, 0, INFINITE, NULL);
229
  if (transactionHandle == INVALID_HANDLE_VALUE) {
230
    DWORD error = GetLastError();
231
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
232
    return terrno;
233
  }
234

235
  BOOL result = MoveFileTransacted(oldName, newName, NULL, NULL, MOVEFILE_REPLACE_EXISTING, transactionHandle);
236

237
  if (result) {
238
    finished = CommitTransaction(transactionHandle);
239
    if (!finished) {
240
      DWORD error = GetLastError();
241
      terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
242
    }
243
  } else {
244
    RollbackTransaction(transactionHandle);
245
    DWORD error = GetLastError();
246
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
247
    finished = false;
248
  }
249

250
  CloseHandle(transactionHandle);
251

252
  return finished ? 0 : terrno;
253
#else
254
  int32_t code = rename(oldName, newName);
275,968✔
255
  if (-1 == code) {
275,961✔
256
    terrno = TAOS_SYSTEM_ERROR(errno);
360✔
257
    return terrno;
355✔
258
  }
259

260
  return TSDB_CODE_SUCCESS;
275,601✔
261
#endif
262
}
263

264
int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime, int32_t *atime) {
246,405✔
265
#ifdef WINDOWS
266
  struct _stati64 fileStat;
267
  int32_t         code = _stati64(path, &fileStat);
268
#else
269
  struct stat fileStat;
270
  int32_t     code = stat(path, &fileStat);
246,405✔
271
#endif
272
  if (-1 == code) {
246,385✔
273
    terrno = TAOS_SYSTEM_ERROR(errno);
47,683✔
274
    return terrno;
47,667✔
275
  }
276

277
  if (size != NULL) {
198,702✔
278
    *size = fileStat.st_size;
185,686✔
279
  }
280

281
  if (mtime != NULL) {
198,702✔
282
    *mtime = fileStat.st_mtime;
3,385✔
283
  }
284

285
  if (atime != NULL) {
198,702!
286
    *atime = fileStat.st_atime;
×
287
  }
288

289
  return 0;
198,702✔
290
}
291
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
40,551✔
292
#ifdef WINDOWS
293
  if (pFile == NULL || pFile->hFile == NULL) {
294
    terrno = TSDB_CODE_INVALID_PARA;
295
    return terrno;
296
  }
297
  BY_HANDLE_FILE_INFORMATION bhfi;
298
  if (GetFileInformationByHandle(pFile->hFile, &bhfi) == FALSE) {
299
    DWORD error = GetLastError();
300
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
301
    return terrno;
302
  }
303

304
  if (stDev != NULL) {
305
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
306
  }
307

308
  if (stIno != NULL) {
309
    *stIno = (int64_t)((((uint64_t)bhfi.nFileIndexHigh) << 32) + bhfi.nFileIndexLow);
310
  }
311

312
#else
313
  if (pFile == NULL || pFile->fd < 0) {
40,551!
314
    terrno = TSDB_CODE_INVALID_PARA;
×
315
    return terrno;
×
316
  }
317

318
  struct stat fileStat;
319
  int32_t     code = fstat(pFile->fd, &fileStat);
40,603✔
320
  if (-1 == code) {
40,603!
321
    terrno = TAOS_SYSTEM_ERROR(errno);
×
322
    return terrno;
×
323
  }
324

325
  if (stDev != NULL) {
40,625✔
326
    *stDev = fileStat.st_dev;
40,622✔
327
  }
328

329
  if (stIno != NULL) {
40,625✔
330
    *stIno = fileStat.st_ino;
40,622✔
331
  }
332
#endif
333

334
  return 0;
40,625✔
335
}
336

337
FILE *taosOpenFileForStream(const char *path, int32_t tdFileOptions) {
55,434✔
338
  char *mode = NULL;
55,434✔
339
  if (tdFileOptions & TD_FILE_APPEND) {
55,434✔
340
    mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
2,221!
341
  } else if (tdFileOptions & TD_FILE_TRUNC) {
53,213✔
342
    mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
1,265✔
343
  } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
51,948!
344
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
51,948!
345
  } else {
346
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
×
347
  }
348
  if (tdFileOptions & TD_FILE_EXCL) {
55,434!
349
    terrno = TSDB_CODE_INVALID_PARA;
×
350
    return NULL;
×
351
  }
352
  FILE *f = fopen(path, mode);
55,434✔
353
  if (NULL == f) {
55,434✔
354
    terrno = TAOS_SYSTEM_ERROR(errno);
92✔
355
  }
356
  return f;
55,434✔
357
}
358

359
#ifdef WINDOWS
360
HANDLE taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
361
  DWORD openMode = 0;
362
  DWORD access = 0;
363
  DWORD fileFlag = FILE_ATTRIBUTE_NORMAL;
364
  DWORD shareMode = FILE_SHARE_READ;
365

366
  openMode = OPEN_EXISTING;
367
  if (tdFileOptions & TD_FILE_CREATE) {
368
    openMode = OPEN_ALWAYS;
369
  } else if (tdFileOptions & TD_FILE_EXCL) {
370
    openMode = CREATE_NEW;
371
  } else if ((tdFileOptions & TD_FILE_TRUNC)) {
372
    openMode = TRUNCATE_EXISTING;
373
    access |= GENERIC_WRITE;
374
  }
375
  if (tdFileOptions & TD_FILE_APPEND) {
376
    access |= FILE_APPEND_DATA;
377
  }
378
  if (tdFileOptions & TD_FILE_WRITE) {
379
    access |= GENERIC_WRITE;
380
  }
381

382
  shareMode |= FILE_SHARE_WRITE;
383

384
  access |= GENERIC_READ;
385

386
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
387
    fileFlag |= FILE_ATTRIBUTE_TEMPORARY;
388
  }
389
  if (tdFileOptions & TD_FILE_WRITE_THROUGH) {
390
    fileFlag |= FILE_FLAG_WRITE_THROUGH;
391
  }
392

393
  HANDLE h = CreateFile(path, access, shareMode, NULL, openMode, fileFlag, NULL);
394
  if (h != INVALID_HANDLE_VALUE && (tdFileOptions & TD_FILE_APPEND) && (tdFileOptions & TD_FILE_WRITE)) {
395
    SetFilePointer(h, 0, NULL, FILE_END);
396
  }
397
  if (h == INVALID_HANDLE_VALUE) {
398
    DWORD dwError = GetLastError();
399
    terrno = TAOS_SYSTEM_WINAPI_ERROR(dwError);
400
    // LPVOID lpMsgBuf;
401
    // FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPTSTR)&lpMsgBuf,
402
    // 0,
403
    //               NULL);
404
    // printf("CreateFile failed with error %d: %s", dwError, (char *)lpMsgBuf);
405
    // LocalFree(lpMsgBuf);
406
  }
407
  return h;
408
}
409

410
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
411
#if FILE_WITH_LOCK
412
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
413
#endif
414
  if (pFile->hFile == NULL) {
415
#if FILE_WITH_LOCK
416
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
417
#endif
418
    terrno = TSDB_CODE_INVALID_PARA;
419
    return terrno;
420
  }
421

422
  int64_t res = 0;
423
  DWORD bytesRead;
424
  if (!ReadFile(pFile->hFile, buf, count, &bytesRead, NULL)) {
425
    DWORD errCode = GetLastError();
426
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errCode);
427
    res = -1;
428
  } else {
429
    res = bytesRead;
430
  }
431
#if FILE_WITH_LOCK
432
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
433
#endif
434
  return res;
435
}
436

437
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
438
  if (pFile == NULL || pFile->hFile == NULL) {
439
    terrno = TSDB_CODE_INVALID_PARA;
440
    return 0;
441
  }
442
#if FILE_WITH_LOCK
443
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
444
#endif
445

446
  DWORD bytesWritten;
447
  if (!WriteFile(pFile->hFile, buf, count, &bytesWritten, NULL)) {
448
    errno = GetLastError();
449
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
450
    bytesWritten = -1;
451
  }
452

453
#if FILE_WITH_LOCK
454
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
455
#endif
456
  return bytesWritten;
457
}
458

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

474
  DWORD      ret = 0;
475
  OVERLAPPED ol = {0};
476
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
477
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
478

479
  SetLastError(0);
480
  BOOL result = WriteFile(pFile->hFile, buf, count, &ret, &ol);
481
  if (!result) {
482
    errno = GetLastError();
483
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
484
    ret = -1;
485
  }
486

487
#if FILE_WITH_LOCK
488
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
489
#endif
490
  return ret;
491
}
492

493
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
494
  if (pFile == NULL || pFile->hFile == NULL) {
495
    terrno = TSDB_CODE_INVALID_PARA;
496
    return -1;
497
  }
498
#if FILE_WITH_LOCK
499
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
500
#endif
501

502
  LARGE_INTEGER liOffset;
503
  liOffset.QuadPart = offset;
504
  if (!SetFilePointerEx(pFile->hFile, liOffset, NULL, whence)) {
505
    errno = GetLastError();
506
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
507
    return -1;
508
  }
509

510
  liOffset.QuadPart = 0;
511
  if (!SetFilePointerEx(pFile->hFile, liOffset, &liOffset, FILE_CURRENT)) {
512
    errno = GetLastError();
513
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
514
    return -1;
515
  }
516
#if FILE_WITH_LOCK
517
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
518
#endif
519
  return liOffset.QuadPart;
520
}
521

522
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
523
  if (pFile == NULL || pFile->hFile == NULL) {
524
    terrno = TSDB_CODE_INVALID_PARA;
525
    return terrno;
526
  }
527

528
  if (size != NULL) {
529
    LARGE_INTEGER fileSize;
530
    if (!GetFileSizeEx(pFile->hFile, &fileSize)) {
531
      errno = GetLastError();
532
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
533
      return terrno;  // Error getting file size
534
    }
535
    *size = fileSize.QuadPart;
536
  }
537

538
  if (mtime != NULL) {
539
    FILETIME creationTime, lastAccessTime, lastWriteTime;
540
    if (!GetFileTime(pFile->hFile, &creationTime, &lastAccessTime, &lastWriteTime)) {
541
      errno = GetLastError();
542
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
543
      return terrno;  // Error getting file time
544
    }
545
    // Convert the FILETIME structure to a time_t value
546
    ULARGE_INTEGER ull;
547
    ull.LowPart = lastWriteTime.dwLowDateTime;
548
    ull.HighPart = lastWriteTime.dwHighDateTime;
549
    *mtime = (int32_t)((ull.QuadPart - 116444736000000000ULL) / 10000000ULL);
550
  }
551
  return 0;
552
}
553

554
int32_t taosLockFile(TdFilePtr pFile) {
555
  if (pFile == NULL || pFile->hFile == NULL) {
556
    terrno = TSDB_CODE_INVALID_PARA;
557
    return terrno;
558
  }
559

560
  BOOL          fSuccess = FALSE;
561
  LARGE_INTEGER fileSize;
562
  OVERLAPPED    overlapped = {0};
563

564
  fSuccess = LockFileEx(pFile->hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
565
                        0,           // reserved
566
                        ~0,          // number of bytes to lock low
567
                        ~0,          // number of bytes to lock high
568
                        &overlapped  // overlapped structure
569
  );
570
  if (!fSuccess) {
571
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
572
  }
573
  return 0;
574
}
575

576
int32_t taosUnLockFile(TdFilePtr pFile) {
577
  if (pFile == NULL || pFile->hFile == NULL) {
578
    return 0;
579
  }
580
  BOOL       fSuccess = FALSE;
581
  OVERLAPPED overlapped = {0};
582

583
  fSuccess = UnlockFileEx(pFile->hFile, 0, ~0, ~0, &overlapped);
584
  if (!fSuccess) {
585
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
586
  }
587
  return 0;
588
}
589

590
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
591
  if (pFile == NULL) {
592
    terrno = TSDB_CODE_INVALID_PARA;
593
    return terrno;
594
  }
595
  if (pFile->hFile == NULL) {
596
    printf("Ftruncate file error, hFile was null\n");
597
    terrno = TSDB_CODE_INVALID_PARA;
598
    return terrno;
599
  }
600

601
  LARGE_INTEGER li_0;
602
  li_0.QuadPart = (int64_t)0;
603
  BOOL cur = SetFilePointerEx(pFile->hFile, li_0, NULL, FILE_CURRENT);
604
  if (!cur) {
605
    printf("SetFilePointerEx Error getting current position in file.\n");
606
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
607
    return terrno;
608
  }
609

610
  LARGE_INTEGER li_size;
611
  li_size.QuadPart = l_size;
612
  BOOL cur2 = SetFilePointerEx(pFile->hFile, li_size, NULL, FILE_BEGIN);
613
  if (cur2 == 0) {
614
    int error = GetLastError();
615
    switch (error) {
616
      case ERROR_INVALID_HANDLE:
617
        errno = EBADF;
618
        break;
619
      default:
620
        errno = EIO;
621
        break;
622
    }
623
    terrno = TAOS_SYSTEM_ERROR(errno);
624
    return terrno;
625
  }
626

627
  if (!SetEndOfFile(pFile->hFile)) {
628
    int error = GetLastError();
629
    printf("SetEndOfFile GetLastError is:%d", error);
630
    switch (error) {
631
      case ERROR_INVALID_HANDLE:
632
        errno = EBADF;
633
        break;
634
      default:
635
        errno = EIO;
636
        break;
637
    }
638
    terrno = TAOS_SYSTEM_ERROR(errno);
639
    return terrno;
640
  }
641
  return 0;
642
}
643

644
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
645
  if (pFileOut == NULL || pFileIn == NULL) {
646
    terrno = TSDB_CODE_INVALID_PARA;
647
    return -1;
648
  }
649
  if (pFileIn->hFile == NULL || pFileOut->hFile == NULL) {
650
    terrno = TSDB_CODE_INVALID_PARA;
651
    return -1;
652
  }
653

654
  LARGE_INTEGER fileOffset;
655
  fileOffset.QuadPart = *offset;
656

657
  if (!SetFilePointerEx(pFileIn->hFile, fileOffset, &fileOffset, FILE_BEGIN)) {
658
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
659
    return -1;
660
  }
661

662
  int64_t writeLen = 0;
663
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
664

665
  DWORD bytesRead;
666
  DWORD bytesWritten;
667
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
668
    if (!ReadFile(pFileIn->hFile, buffer, _SEND_FILE_STEP_, &bytesRead, NULL)) {
669
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
670
      return writeLen;
671
    }
672

673
    if (bytesRead <= 0) {
674
      return writeLen;
675
    } else if (bytesRead < _SEND_FILE_STEP_) {
676
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
677
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
678
        return -1;
679
      } else {
680
        return (int64_t)(writeLen + bytesRead);
681
      }
682
    } else {
683
      if (!WriteFile(pFileOut->hFile, buffer, _SEND_FILE_STEP_, &bytesWritten, NULL)) {
684
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
685
        return -1;
686
      } else {
687
        writeLen += _SEND_FILE_STEP_;
688
      }
689
    }
690
  }
691

692
  int64_t remain = size - writeLen;
693
  if (remain > 0) {
694
    DWORD bytesRead;
695
    if (!ReadFile(pFileIn->hFile, buffer, (DWORD)remain, &bytesRead, NULL)) {
696
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
697
      return -1;
698
    }
699

700
    if (bytesRead <= 0) {
701
      return writeLen;
702
    } else {
703
      DWORD bytesWritten;
704
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
705
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
706
        return -1;
707
      } else {
708
        writeLen += bytesWritten;
709
      }
710
    }
711
  }
712
  return writeLen;
713
}
714

715
bool lastErrorIsFileNotExist() {
716
  DWORD dwError = GetLastError();
717
  return dwError == ERROR_FILE_NOT_FOUND;
718
}
719

720
#else
721
int taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
22,052,256✔
722
  int access = O_BINARY;
22,052,256✔
723
  access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
22,052,256✔
724
  if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
22,052,256✔
725
    access |= O_RDWR;
591,271✔
726
  } else if (tdFileOptions & TD_FILE_WRITE) {
21,460,985✔
727
    access |= O_WRONLY;
423,618✔
728
  } else if (tdFileOptions & TD_FILE_READ) {
21,037,367!
729
    access |= O_RDONLY;
21,042,661✔
730
  }
731
  access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
22,052,256✔
732
  access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
22,052,256✔
733
  access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
22,052,256✔
734
  access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
22,052,256✔
735
  access |= (tdFileOptions & TD_FILE_CLOEXEC) ? O_CLOEXEC : 0;
22,052,256✔
736

737
  int fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
22,052,256✔
738
  if (-1 == fd) {
22,057,856✔
739
    terrno = TAOS_SYSTEM_ERROR(errno);
24,609✔
740
  }
741
  return fd;
22,061,492✔
742
}
743

744
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
48,027,537✔
745
  STUB_RAND_IO_ERR(terrno)
746
#if FILE_WITH_LOCK
747
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
48,027,537✔
748
#endif
749

750
  if (pFile->fd < 0) {
48,041,945!
751
#if FILE_WITH_LOCK
UNCOV
752
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
753
#endif
754
    terrno = TSDB_CODE_INVALID_PARA;
×
755
    return -1;
×
756
  }
757

758
  int64_t leftbytes = count;
48,042,160✔
759
  int64_t readbytes;
760
  char   *tbuf = (char *)buf;
48,042,160✔
761
  int32_t code = 0;
48,042,160✔
762

763
  while (leftbytes > 0) {
96,073,312✔
764
#ifdef WINDOWS
765
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
766
#else
767
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
48,037,824✔
768
#endif
769
    if (readbytes < 0) {
48,036,033✔
770
      if (errno == EINTR) {
185!
771
        continue;
×
772
      } else {
773
        code = TAOS_SYSTEM_ERROR(errno);
185✔
774
#if FILE_WITH_LOCK
775
        (void)taosThreadRwlockUnlock(&(pFile->rwlock));
185✔
776
#endif
777
        terrno = code;
185✔
778
        return -1;
185✔
779
      }
780
    } else if (readbytes == 0) {
48,035,848✔
781
#if FILE_WITH_LOCK
782
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
4,696✔
783
#endif
784
      return (int64_t)(count - leftbytes);
4,696✔
785
    }
786

787
    leftbytes -= readbytes;
48,031,152✔
788
    tbuf += readbytes;
48,031,152✔
789
  }
790

791
#if FILE_WITH_LOCK
792
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
48,035,488✔
793
#endif
794

795
  return count;
48,039,991✔
796
}
797

798
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
638,386,732✔
799
  STUB_RAND_IO_ERR(terrno)
800
  if (pFile == NULL) {
638,386,732!
801
    terrno = TSDB_CODE_INVALID_PARA;
×
802
    return 0;
×
803
  }
804
#if FILE_WITH_LOCK
805
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
638,386,732✔
806
#endif
807
  if (pFile->fd < 0) {
638,616,591!
808
#if FILE_WITH_LOCK
UNCOV
809
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
810
#endif
811
    terrno = TSDB_CODE_INVALID_PARA;
×
812
    return 0;
×
813
  }
814

815
  int64_t nleft = count;
638,616,877✔
816
  int64_t nwritten = 0;
638,616,877✔
817
  char   *tbuf = (char *)buf;
638,616,877✔
818
  int32_t code = 0;
638,616,877✔
819

820
  while (nleft > 0) {
1,277,230,226✔
821
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
638,615,954✔
822
    if (nwritten < 0) {
638,613,349!
823
      if (errno == EINTR) {
×
824
        continue;
×
825
      }
826
      code = TAOS_SYSTEM_ERROR(errno);
×
827
#if FILE_WITH_LOCK
828
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
829
#endif
830
      terrno = code;
×
831
      return -1;
×
832
    }
833
    nleft -= nwritten;
638,613,349✔
834
    tbuf += nwritten;
638,613,349✔
835
  }
836

837
#if FILE_WITH_LOCK
838
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
638,614,272✔
839
#endif
840

841
  return count;
638,590,274✔
842
}
843

844
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
728,888✔
845
  STUB_RAND_IO_ERR(terrno)
846
  if (pFile == NULL) {
728,888!
847
    terrno = TSDB_CODE_INVALID_PARA;
×
848
    return 0;
×
849
  }
850

851
  int32_t code = 0;
728,888✔
852
#if FILE_WITH_LOCK
853
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
728,888✔
854
#endif
855

856
#if FILE_WITH_LOCK
857
  if (pFile->fd < 0) {
729,333!
858
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
859
    return 0;
×
860
  }
861
#endif
862

863
  int64_t ret = pwrite(pFile->fd, buf, count, offset);
729,333✔
864
  if (-1 == ret) {
728,809!
865
    code = TAOS_SYSTEM_ERROR(errno);
×
866
  }
867

868
#if FILE_WITH_LOCK
869
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
728,809✔
870
#endif
871

872
  if (code) {
729,302!
873
    terrno = code;
×
874
  }
875

876
  return ret;
729,343✔
877
}
878

879
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
60,397,868✔
880
  if (pFile == NULL || pFile->fd < 0) {
60,397,868!
881
    terrno = TSDB_CODE_INVALID_PARA;
×
882
    return -1;
×
883
  }
884
#if FILE_WITH_LOCK
885
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
60,404,351✔
886
#endif
887

888
  int32_t code = 0;
60,415,521✔
889

890
  int64_t ret = lseek(pFile->fd, offset, whence);
60,415,521✔
891
  if (-1 == ret) {
60,412,438!
892
    code = TAOS_SYSTEM_ERROR(errno);
×
893
  }
894

895
#if FILE_WITH_LOCK
896
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
60,412,438✔
897
#endif
898

899
  if (code) {
60,415,710✔
900
    terrno = code;
1,184✔
901
    return -1;
×
902
  }
903

904
  return ret;
60,414,526✔
905
}
906

907
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
102,247✔
908
  if (pFile == NULL) {
102,247!
909
    terrno = TSDB_CODE_INVALID_PARA;
×
910
    return terrno;
×
911
  }
912

913
  if (pFile->fd < 0) {
102,247!
914
    terrno = TSDB_CODE_INVALID_PARA;
×
915
    return terrno;
×
916
  }
917

918
  struct stat fileStat;
919
  int32_t     code = fstat(pFile->fd, &fileStat);
102,247✔
920
  if (-1 == code) {
102,268!
921
    terrno = TAOS_SYSTEM_ERROR(errno);
×
922
    return terrno;
×
923
  }
924

925
  if (size != NULL) {
102,278✔
926
    *size = fileStat.st_size;
102,256✔
927
  }
928

929
  if (mtime != NULL) {
102,278!
930
    *mtime = fileStat.st_mtime;
×
931
  }
932

933
  return 0;
102,278✔
934
}
935

936
int32_t taosLockFile(TdFilePtr pFile) {
22,675✔
937
  if (NULL == pFile || pFile->fd < 0) {
22,675!
938
    terrno = TSDB_CODE_INVALID_PARA;
×
939
    return terrno;
×
940
  }
941
  int32_t code = (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
22,675✔
942
  if (-1 == code) {
22,675✔
943
    terrno = TAOS_SYSTEM_ERROR(errno);
15,298✔
944
    return terrno;
15,298✔
945
  }
946
  return 0;
7,377✔
947
}
948

949
int32_t taosUnLockFile(TdFilePtr pFile) {
4,360✔
950
  if (NULL == pFile || pFile->fd < 0) {
4,360!
951
    terrno = TSDB_CODE_INVALID_PARA;
×
952
    return terrno;
×
953
  }
954
  int32_t code = (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
4,360✔
955
  if (-1 == code) {
4,360!
956
    terrno = TAOS_SYSTEM_ERROR(errno);
×
957
    return terrno;
×
958
  }
959
  return 0;
4,360✔
960
}
961

962
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
75✔
963
  if (NULL == pFile || pFile->fd < 0) {
75!
964
    terrno = TSDB_CODE_INVALID_PARA;
×
965
    return terrno;
×
966
  }
967

968
  int32_t code = ftruncate(pFile->fd, l_size);
75✔
969
  if (-1 == code) {
75!
970
    terrno = TAOS_SYSTEM_ERROR(errno);
×
971
    return terrno;
×
972
  }
973
  return 0;
75✔
974
}
975

976
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
19✔
977
  if (pFileOut == NULL || pFileIn == NULL) {
19!
978
    terrno = TSDB_CODE_INVALID_PARA;
×
979
    return -1;
×
980
  }
981
  if (pFileIn->fd < 0 || pFileOut->fd < 0) {
19!
982
    terrno = TSDB_CODE_INVALID_PARA;
×
983
    return -1;
×
984
  }
985

986
#ifdef _TD_DARWIN_64
987
  if (lseek(pFileIn->fd, (int32_t)(*offset), 0) < 0) {
988
    terrno = TAOS_SYSTEM_ERROR(errno);
989
    return -1;
990
  }
991
  int64_t writeLen = 0;
992
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
993

994
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
995
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
996
    if (rlen <= 0) {
997
      return writeLen;
998
    } else if (rlen < _SEND_FILE_STEP_) {
999
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
1000
      return (int64_t)(writeLen + rlen);
1001
    } else {
1002
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
1003
      writeLen += _SEND_FILE_STEP_;
1004
    }
1005
  }
1006

1007
  int64_t remain = size - writeLen;
1008
  if (remain > 0) {
1009
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
1010
    if (rlen <= 0) {
1011
      return writeLen;
1012
    } else {
1013
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
1014
      writeLen += remain;
1015
    }
1016
  }
1017
  return writeLen;
1018

1019
#else  // for linux
1020

1021
  int64_t leftbytes = size;
19✔
1022
  int64_t sentbytes;
1023

1024
  while (leftbytes > 0) {
38✔
1025
#ifdef _TD_ARM_32
1026
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int *)offset, leftbytes);
1027
#else
1028
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
19✔
1029
#endif
1030
    if (sentbytes == -1) {
19!
1031
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
×
1032
        continue;
×
1033
      } else {
1034
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1035
        return -1;
×
1036
      }
1037
    } else if (sentbytes == 0) {
19!
1038
      return (int64_t)(size - leftbytes);
×
1039
    }
1040

1041
    leftbytes -= sentbytes;
19✔
1042
  }
1043

1044
  return size;
19✔
1045
#endif
1046
}
1047

1048
bool lastErrorIsFileNotExist() { return terrno == TAOS_SYSTEM_ERROR(ENOENT); }
10,185✔
1049

1050
#endif  // WINDOWS
1051

1052
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
22,110,269✔
1053
  STUB_RAND_IO_ERR(NULL)
1054
  FILE *fp = NULL;
22,110,269✔
1055
#ifdef WINDOWS
1056
  HANDLE hFile = NULL;
1057
#else
1058
  int fd = -1;
22,110,269✔
1059
#endif
1060
  if (tdFileOptions & TD_FILE_STREAM) {
22,110,269✔
1061
    fp = taosOpenFileForStream(path, tdFileOptions);
55,434✔
1062
    if (fp == NULL) return NULL;
55,434✔
1063
  } else {
1064
#ifdef WINDOWS
1065
    hFile = taosOpenFileNotStream(path, tdFileOptions);
1066
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
1067
#else
1068
    fd = taosOpenFileNotStream(path, tdFileOptions);
22,054,835✔
1069
    if (fd == -1) return NULL;
22,055,743✔
1070
#endif
1071
  }
1072

1073
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
22,082,840✔
1074
  if (pFile == NULL) {
22,088,318!
1075
#ifdef WINDOWS
1076
    if (hFile != NULL) CloseHandle(hFile);
1077
#else
1078
    if (fd >= 0) (void)close(fd);
×
1079
#endif
1080
    if (fp != NULL) (void)fclose(fp);
×
1081
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
1082
    return NULL;
×
1083
  }
1084

1085
#if FILE_WITH_LOCK
1086
  (void)taosThreadRwlockInit(&(pFile->rwlock), NULL);
22,088,318✔
1087
#endif
1088
  pFile->fp = fp;
22,083,050✔
1089
  pFile->refId = 0;
22,083,050✔
1090

1091
#ifdef WINDOWS
1092
  pFile->hFile = hFile;
1093
  pFile->tdFileOptions = tdFileOptions;
1094
  // do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
1095
  // the file handle, as well as the space on disk.
1096
#else
1097
  pFile->fd = fd;
22,083,050✔
1098
  // Remove it instantly, so when the program exits normally/abnormally, the file
1099
  // will be automatically remove by OS.
1100
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
22,083,050✔
1101
    if (-1 == unlink(path)) {
7,894!
UNCOV
1102
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1103
      (void)close(fd);
×
1104
      taosMemoryFree(pFile);
×
1105
      return NULL;
×
1106
    }
1107
  }
1108
#endif
1109

1110
  return pFile;
22,086,084✔
1111
}
1112

1113
int32_t taosCloseFile(TdFilePtr *ppFile) {
38,515,573✔
1114
  int32_t code = 0;
38,515,573✔
1115
  if (ppFile == NULL || *ppFile == NULL) {
38,515,573!
1116
    return 0;
16,425,221✔
1117
  }
1118
#if FILE_WITH_LOCK
1119
  (void)taosThreadRwlockWrlock(&((*ppFile)->rwlock));
22,090,352✔
1120
#endif
1121
  if ((*ppFile)->fp != NULL) {
22,091,372✔
1122
    TAOS_UNUSED(fflush((*ppFile)->fp));
54,628✔
1123
    TAOS_UNUSED(fclose((*ppFile)->fp));
54,628✔
1124
    (*ppFile)->fp = NULL;
54,628✔
1125
  }
1126
#ifdef WINDOWS
1127
  if ((*ppFile)->hFile != NULL) {
1128
    // FlushFileBuffers((*ppFile)->hFile);
1129
    if (!CloseHandle((*ppFile)->hFile)) {
1130
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1131
      code = -1;
1132
    }
1133
    (*ppFile)->hFile = NULL;
1134
#else
1135
  if ((*ppFile)->fd >= 0) {
22,091,372✔
1136
    // warning: never fsync silently in base lib
1137
    /*fsync((*ppFile)->fd);*/
1138
    code = close((*ppFile)->fd);
22,036,753✔
1139
    if (-1 == code) {
22,038,950!
1140
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1141
    }
1142
    (*ppFile)->fd = -1;
22,039,013✔
1143
#endif
1144
  }
1145
  (*ppFile)->refId = 0;
22,093,632✔
1146
#if FILE_WITH_LOCK
1147
  (void)taosThreadRwlockUnlock(&((*ppFile)->rwlock));
22,093,632✔
1148
  (void)taosThreadRwlockDestroy(&((*ppFile)->rwlock));
22,093,560✔
1149
#endif
1150
  taosMemoryFree(*ppFile);
22,093,318✔
1151
  *ppFile = NULL;
22,092,954✔
1152
  return code;
22,092,954✔
1153
}
1154

1155
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
688,566✔
1156
  STUB_RAND_IO_ERR(terrno)
1157
  if (pFile == NULL) {
688,566!
1158
    terrno = TSDB_CODE_INVALID_PARA;
×
1159
    return -1;
×
1160
  }
1161

1162
  int32_t code = 0;
688,566✔
1163

1164
#ifdef WINDOWS
1165
#if FILE_WITH_LOCK
1166
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
1167
#endif
1168

1169
  if (pFile->hFile == NULL) {
1170
#if FILE_WITH_LOCK
1171
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1172
#endif
1173

1174
    terrno = TSDB_CODE_INVALID_PARA;
1175
    return -1;
1176
  }
1177

1178
  DWORD      ret = 0;
1179
  OVERLAPPED ol = {0};
1180
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
1181
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
1182

1183
  SetLastError(0);
1184
  BOOL result = ReadFile(pFile->hFile, buf, count, &ret, &ol);
1185
  if (!result && GetLastError() != ERROR_HANDLE_EOF) {
1186
    code = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1187
    ret = -1;
1188
  }
1189
#else
1190
#if FILE_WITH_LOCK
1191
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
688,566✔
1192
#endif
1193

1194
  if (pFile->fd < 0) {
688,725!
1195
#if FILE_WITH_LOCK
1196
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
1197
#endif
1198
    terrno = TSDB_CODE_INVALID_PARA;
×
1199
    return -1;
×
1200
  }
1201
  int64_t ret = pread(pFile->fd, buf, count, offset);
688,725✔
1202
  if (-1 == ret) {
688,637!
1203
    code = TAOS_SYSTEM_ERROR(errno);
×
1204
  }
1205
#endif
1206
#if FILE_WITH_LOCK
1207
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
688,637✔
1208
#endif
1209

1210
  if (code) {
688,710!
1211
    terrno = code;
×
1212
    return -1;
×
1213
  }
1214

1215
  return ret;
688,752✔
1216
}
1217

1218
int32_t taosFsyncFile(TdFilePtr pFile) {
2,162,363✔
1219
  if (pFile == NULL) {
2,162,363✔
1220
    return 0;
2,583✔
1221
  }
1222

1223
  int32_t code = 0;
2,159,780✔
1224
  // this implementation is WRONG
1225
  // fflush is not a replacement of fsync
1226
  if (pFile->fp != NULL) {
2,159,780✔
1227
    code = fflush(pFile->fp);
446,921✔
1228
    if (0 != code) {
446,921!
1229
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1230
      return terrno;
×
1231
    }
1232

1233
    return 0;
446,921✔
1234
  }
1235

1236
#ifdef WINDOWS
1237
  if (pFile->hFile != NULL) {
1238
    if (pFile->tdFileOptions & TD_FILE_WRITE_THROUGH) {
1239
      return 0;
1240
    }
1241
    bool ret = FlushFileBuffers(pFile->hFile);
1242
    if (!ret) {
1243
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1244
      return terrno;
1245
    }
1246
    return 0;
1247
  }
1248
#else
1249
  if (pFile->fd >= 0) {
1,712,859!
1250
    code = fsync(pFile->fd);
1,712,896✔
1251
    if (-1 == code) {
1,713,441!
1252
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1253
      return terrno;
×
1254
    }
1255
  }
1256
#endif
1257

1258
  return 0;
1,713,492✔
1259
}
1260

1261
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
170,861,068✔
1262
  if (pFile == NULL || pFile->fp == NULL) {
170,861,068!
1263
    return;
61,372,427✔
1264
  }
1265
  va_list ap;
1266
  va_start(ap, format);
109,488,641✔
1267
  (void)vfprintf(pFile->fp, format, ap);
109,488,641✔
1268
  va_end(ap);
109,596,339✔
1269
}
1270

1271
bool taosValidFile(TdFilePtr pFile) {
×
1272
#ifdef WINDOWS
1273
  return pFile != NULL && pFile->hFile != NULL;
1274
#else
1275
  return pFile != NULL && pFile->fd > 0;
×
1276
#endif
1277
}
1278

1279
int32_t taosUmaskFile(int32_t maskVal) {
13,059✔
1280
#ifdef WINDOWS
1281
  return 0;
1282
#else
1283
  return umask(maskVal);
13,059✔
1284
#endif
1285
}
1286

1287
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
20,210,177✔
1288
  int64_t ret = -1;
20,210,177✔
1289
  int32_t code = 0;
20,210,177✔
1290

1291
#if FILE_WITH_LOCK
1292
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
20,210,177✔
1293
#endif
1294
  if (pFile == NULL || ptrBuf == NULL) {
20,210,177!
1295
    terrno = TSDB_CODE_INVALID_PARA;
×
1296
    goto END;
×
1297
  }
1298
  if (*ptrBuf != NULL) {
20,210,177✔
1299
    taosMemoryFreeClear(*ptrBuf);
20,210,004!
1300
  }
1301

1302
  if (pFile->fp == NULL) {
20,210,177!
1303
    terrno = TSDB_CODE_INVALID_PARA;
×
1304
    goto END;
×
1305
  }
1306

1307
#ifdef WINDOWS
1308
  size_t bufferSize = 512;
1309
  *ptrBuf = taosMemoryMalloc(bufferSize);
1310
  if (*ptrBuf == NULL) {
1311
    goto END;
1312
  }
1313

1314
  size_t bytesRead = 0;
1315
  size_t totalBytesRead = 0;
1316

1317
  while (1) {
1318
    char *result = fgets(*ptrBuf + totalBytesRead, bufferSize - totalBytesRead, pFile->fp);
1319
    if (result == NULL) {
1320
      if (feof(pFile->fp)) {
1321
        break;
1322
      } else {
1323
        ret = -1;
1324
        terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
1325
        taosMemoryFreeClear(*ptrBuf);
1326
        goto END;
1327
      }
1328
    }
1329
    bytesRead = strlen(*ptrBuf + totalBytesRead);
1330
    totalBytesRead += bytesRead;
1331

1332
    if (totalBytesRead < bufferSize - 1 || (*ptrBuf)[totalBytesRead - 1] == '\n') {
1333
      break;
1334
    }
1335

1336
    bufferSize += 512;
1337
    void *newBuf = taosMemoryRealloc(*ptrBuf, bufferSize);
1338
    if (newBuf == NULL) {
1339
      taosMemoryFreeClear(*ptrBuf);
1340
      goto END;
1341
    }
1342

1343
    *ptrBuf = newBuf;
1344
  }
1345

1346
  (*ptrBuf)[totalBytesRead] = '\0';
1347
  ret = totalBytesRead;
1348
#else
1349
  size_t len = 0;
20,210,177✔
1350
  ret = getline(ptrBuf, &len, pFile->fp);
20,210,177✔
1351
  if (-1 == ret) {
20,210,177✔
1352
    terrno = TAOS_SYSTEM_ERROR(errno);
111✔
1353
  }
1354
#endif
1355

1356
END:
20,210,066✔
1357

1358
#if FILE_WITH_LOCK
1359
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
20,210,177✔
1360
#endif
1361

1362
  return ret;
20,210,177✔
1363
}
1364

1365
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
19,599,900✔
1366
  if (pFile == NULL || buf == NULL) {
19,599,900!
1367
    terrno = TSDB_CODE_INVALID_PARA;
×
1368
    return terrno;
×
1369
  }
1370

1371
  if (pFile->fp == NULL) {
19,599,900!
1372
    terrno = TSDB_CODE_INVALID_PARA;
×
1373
    return terrno;
×
1374
  }
1375

1376
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
19,599,900✔
1377
    if (feof(pFile->fp)) {
21,949!
1378
      return 0;
21,949✔
1379
    } else {
1380
      terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
×
1381
      return terrno;
×
1382
    }
1383
  }
1384

1385
  return strlen(buf);
19,577,951✔
1386
}
1387

1388
int32_t taosEOFFile(TdFilePtr pFile) {
1,165,790✔
1389
  if (pFile == NULL) {
1,165,790!
1390
    terrno = TSDB_CODE_INVALID_PARA;
×
1391
    return -1;
×
1392
  }
1393
  if (pFile->fp == NULL) {
1,165,790!
1394
    terrno = TSDB_CODE_INVALID_PARA;
×
1395
    return -1;
×
1396
  }
1397

1398
  return feof(pFile->fp);
1,165,790✔
1399
}
1400

1401
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
536,511✔
1402
  int flags = 0;
536,511✔
1403

1404
  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
536,511!
1405
    flags |= F_OK;
536,536✔
1406
  }
1407

1408
  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
536,511✔
1409
    flags |= R_OK;
19,642✔
1410
  }
1411

1412
  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
536,511✔
1413
    flags |= W_OK;
19,642✔
1414
  }
1415
#ifdef WINDOWS
1416
  return _access(pathname, flags) == 0;
1417
#else
1418
  return access(pathname, flags) == 0;
536,511✔
1419
#endif
1420
}
1421

1422
bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };
516,729✔
1423

1424
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
×
1425
  int32_t   compressSize = 163840;
×
1426
  int32_t   ret = 0;
×
1427
  int32_t   len = 0;
×
1428
  gzFile    dstFp = NULL;
×
1429
  TdFilePtr pSrcFile = NULL;
×
1430

1431
  char *data = taosMemoryMalloc(compressSize);
×
1432
  if (NULL == data) {
×
1433
    return terrno;
×
1434
  }
1435

1436
  pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ | TD_FILE_STREAM);
×
1437
  if (pSrcFile == NULL) {
×
1438
    ret = terrno;
×
1439
    goto cmp_end;
×
1440
  }
1441

1442
  int access = O_BINARY | O_WRONLY | O_TRUNC | O_CREAT;
×
1443
#ifdef WINDOWS
1444
  int32_t pmode = _S_IREAD | _S_IWRITE;
1445
#else
1446
  int32_t pmode = S_IRWXU | S_IRWXG | S_IRWXO;
×
1447
#endif
1448
  int fd = open(destFileName, access, pmode);
×
1449
  if (-1 == fd) {
×
1450
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1451
    ret = terrno;
×
1452
    goto cmp_end;
×
1453
  }
1454

1455
  // Both gzclose() and fclose() will close the associated fd, so they need to have different fds.
1456
  FileFd gzFd = dup(fd);
×
1457
  if (-1 == gzFd) {
×
1458
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1459
    ret = terrno;
×
1460
    goto cmp_end;
×
1461
  }
1462
  dstFp = gzdopen(gzFd, "wb6f");
×
1463
  if (dstFp == NULL) {
×
1464
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1465
    ret = terrno;
×
1466
    (void)close(gzFd);
×
1467
    goto cmp_end;
×
1468
  }
1469

1470
  while (!feof(pSrcFile->fp)) {
×
1471
    len = (int32_t)fread(data, 1, compressSize, pSrcFile->fp);
×
1472
    if (len > 0) {
×
1473
      if (gzwrite(dstFp, data, len) == 0) {
×
1474
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1475
        ret = terrno;
×
1476
        goto cmp_end;
×
1477
      }
1478
    }
1479
  }
1480

1481
cmp_end:
×
1482

1483
  if (fd >= 0) {
×
1484
    TAOS_SKIP_ERROR(close(fd));
×
1485
  }
1486
  if (pSrcFile) {
×
1487
    TAOS_SKIP_ERROR(taosCloseFile(&pSrcFile));
×
1488
  }
1489

1490
  if (dstFp) {
×
1491
    TAOS_SKIP_ERROR(gzclose(dstFp));
×
1492
  }
1493

1494
  taosMemoryFree(data);
×
1495

1496
  return ret;
×
1497
}
1498

1499
int32_t taosSetFileHandlesLimit() {
8,997✔
1500
#ifdef WINDOWS
1501
  const int max_handles = 8192;
1502
  int       res = _setmaxstdio(max_handles);
1503
  return res == max_handles ? 0 : -1;
1504
#endif
1505
  return 0;
8,997✔
1506
}
1507

1508
int32_t taosLinkFile(char *src, char *dst) {
107✔
1509
#ifndef WINDOWS
1510
  if (-1 == link(src, dst)) {
107!
1511
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1512
    return terrno;
×
1513
  }
1514
#endif
1515
  return 0;
107✔
1516
}
1517

1518
FILE *taosOpenCFile(const char *filename, const char *mode) {
877,223✔
1519
  STUB_RAND_IO_ERR(NULL)
1520
  FILE *f = fopen(filename, mode);
877,223✔
1521
  if (NULL == f) {
879,994!
1522
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1523
  }
1524
  return f;
879,994✔
1525
}
1526

1527
int taosSeekCFile(FILE *file, int64_t offset, int whence) {
490,105✔
1528
#ifdef WINDOWS
1529
  return _fseeki64(file, offset, whence);
1530
#else
1531
  int     code = fseeko(file, offset, whence);
490,105✔
1532
  if (-1 == code) {
490,098!
1533
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1534
    code = terrno;
×
1535
  }
1536
  return code;
490,086✔
1537
#endif
1538
}
1539

1540
size_t taosReadFromCFile(void *buffer, size_t size, size_t count, FILE *stream) {
490,099✔
1541
  STUB_RAND_IO_ERR(terrno)
1542
  return fread(buffer, size, count, stream);
490,099✔
1543
}
1544

1545
size_t taosWriteToCFile(const void *ptr, size_t size, size_t nitems, FILE *stream) {
×
1546
  STUB_RAND_IO_ERR(terrno)
1547
  return fwrite(ptr, size, nitems, stream);
×
1548
}
1549

1550
int taosCloseCFile(FILE *f) { return fclose(f); }
879,948✔
1551

1552
int taosSetAutoDelFile(char *path) {
879,994✔
1553
#ifdef WINDOWS
1554
  bool succ = SetFileAttributes(path, FILE_ATTRIBUTE_TEMPORARY);
1555
  if (succ) {
1556
    return 0;
1557
  } else {
1558
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1559
    return terrno;
1560
  }
1561
#else
1562
  if (-1 == unlink(path)) {
879,994!
1563
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1564
    return terrno;
×
1565
  }
1566
  return 0;
879,994✔
1567
#endif
1568
}
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