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

wafwerar's avatar
wafwerar 已提交
19
#ifdef WINDOWS
20
#include <io.h>
wafwerar's avatar
wafwerar 已提交
21 22 23
#define F_OK 0
#define W_OK 2
#define R_OK 4
24

wafwerar's avatar
wafwerar 已提交
25 26
#define _SEND_FILE_STEP_ 1000

27
#else
28 29
#include <fcntl.h>
#include <sys/file.h>
30 31

#if !defined(_TD_DARWIN_64)
L
Liu Jicong 已提交
32
#include <sys/sendfile.h>
33
#endif
34 35 36 37
#include <sys/stat.h>
#include <unistd.h>
#define LINUX_FILE_NO_TEXT_OPTION 0
#define O_TEXT                    LINUX_FILE_NO_TEXT_OPTION
wafwerar's avatar
wafwerar 已提交
38 39

#define _SEND_FILE_STEP_ 1000
40 41
#endif

wafwerar's avatar
wafwerar 已提交
42 43 44 45 46 47 48 49 50 51 52
#if defined(WINDOWS)
typedef int32_t FileFd;
typedef int32_t SocketFd;
#else
typedef int32_t FileFd;
typedef int32_t SocketFd;
#endif

typedef int32_t FileFd;

typedef struct TdFile {
wafwerar's avatar
wafwerar 已提交
53
  TdThreadRwlock rwlock;
L
Liu Jicong 已提交
54 55 56
  int            refId;
  FileFd         fd;
  FILE          *fp;
wafwerar's avatar
wafwerar 已提交
57 58
} * TdFilePtr, TdFile;

59 60
#define FILE_WITH_LOCK 1

wafwerar's avatar
wafwerar 已提交
61 62 63 64 65 66 67 68 69
typedef struct AutoDelFile * AutoDelFilePtr;
typedef struct AutoDelFile {
  char           *name;
  AutoDelFilePtr  lastAutoDelFilePtr;
} AutoDelFile;
static TdThreadMutex autoDelFileLock;
static AutoDelFilePtr nowAutoDelFilePtr = NULL;
static TdThreadOnce autoDelFileInit = PTHREAD_ONCE_INIT;

70
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
wafwerar's avatar
wafwerar 已提交
71
#ifdef WINDOWS
S
Shengliang Guan 已提交
72
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
TD-4088  
Shengliang Guan 已提交
73
  char        tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
74

S
Shengliang Guan 已提交
75 76
  int32_t len = (int32_t)strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
77 78 79

  if (tmpPath[len - 1] != '/' && tmpPath[len - 1] != '\\') {
    tmpPath[len++] = '\\';
80
  }
S
Shengliang Guan 已提交
81

82
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
S
Shengliang Guan 已提交
83 84 85
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
86
  }
S
Shengliang Guan 已提交
87

S
TD-4088  
Shengliang Guan 已提交
88 89
  char rand[8] = {0};
  taosRandStr(rand, tListLen(rand) - 1);
S
Shengliang Guan 已提交
90
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
TD-1912  
Shengliang Guan 已提交
91

S
TD-4088  
Shengliang Guan 已提交
92
#else
S
Shengliang Guan 已提交
93

S
TD-4088  
Shengliang Guan 已提交
94
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
Shengliang Guan 已提交
95

96
  char    tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
97 98
  int32_t len = strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
99
  static uint64_t seqId = 0;
S
Shengliang Guan 已提交
100

S
TD-4088  
Shengliang Guan 已提交
101 102
  if (tmpPath[len - 1] != '/') {
    tmpPath[len++] = '/';
S
TD-1912  
Shengliang Guan 已提交
103
  }
S
Shengliang Guan 已提交
104

S
TD-4088  
Shengliang Guan 已提交
105 106 107 108
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
109 110
  }

S
TD-4088  
Shengliang Guan 已提交
111 112 113
  char rand[32] = {0};

  sprintf(rand, "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
S
Shengliang Guan 已提交
114

S
TD-4088  
Shengliang Guan 已提交
115
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
Shengliang Guan 已提交
116

S
TD-4088  
Shengliang Guan 已提交
117
#endif
S
Shengliang Guan 已提交
118
}
S
TD-4088  
Shengliang Guan 已提交
119

120
int64_t taosCopyFile(const char *from, const char *to) {
wafwerar's avatar
wafwerar 已提交
121
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
122 123 124 125 126
  if (CopyFile(from, to, 0)) {
    return 1;
  } else {
    return -1;
  }
127 128 129 130 131 132
#else
  char    buffer[4096];
  int64_t size = 0;
  int64_t bytes;

  // fidfrom = open(from, O_RDONLY);
133
  TdFilePtr pFileFrom = taosOpenFile(from, TD_FILE_READ);
134 135 136
  if (pFileFrom == NULL) goto _err;

  // fidto = open(to, O_WRONLY | O_CREAT | O_EXCL, 0755);
137
  TdFilePtr pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  if (pFileTo == NULL) goto _err;

  while (true) {
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
    if (bytes < 0) goto _err;
    if (bytes == 0) break;

    size += bytes;

    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) goto _err;
    if (bytes < sizeof(buffer)) break;
  }

  taosFsyncFile(pFileTo);

  taosCloseFile(&pFileFrom);
  taosCloseFile(&pFileTo);
  return size;

_err:
  if (pFileFrom != NULL) taosCloseFile(&pFileFrom);
  if (pFileTo != NULL) taosCloseFile(&pFileTo);
160
  taosRemoveFile(to);
161 162 163 164
  return -1;
#endif
}

C
Cary Xu 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) {
  TdFilePtr fp = taosOpenFile(path, tdFileOptions);
  if (!fp) {
    if (errno == ENOENT) {
      // Try to create directory recursively
      char *s = strdup(path);
      if (taosMulMkDir(taosDirName(s)) != 0) {
        taosMemoryFree(s);
        return NULL;
      }
      taosMemoryFree(s);
      fp = taosOpenFile(path, tdFileOptions);
      if (!fp) {
        return NULL;
      }
    }
  }
  return fp;
}

185 186
int32_t taosRemoveFile(const char *path) { return remove(path); }

187
int32_t taosRenameFile(const char *oldName, const char *newName) {
wafwerar's avatar
wafwerar 已提交
188
#ifdef WINDOWS
189 190
  bool code = MoveFileEx(oldName, newName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
  if (!code) {
C
Cary Xu 已提交
191
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
192 193
  }

194
  return !code;
195 196 197
#else
  int32_t code = rename(oldName, newName);
  if (code < 0) {
C
Cary Xu 已提交
198
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
199 200 201 202 203 204 205
  }

  return code;
#endif
}

int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) {
206
  struct stat fileStat;
wafwerar's avatar
wafwerar 已提交
207
#ifdef WINDOWS
208
  int32_t code = _stat(path, &fileStat);
209
#else
210
  int32_t code = stat(path, &fileStat);
211
#endif
212 213 214 215 216 217 218 219 220 221 222 223 224 225
  if (code < 0) {
    return code;
  }

  if (size != NULL) {
    *size = fileStat.st_size;
  }

  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }

  return 0;
}
wafwerar's avatar
wafwerar 已提交
226 227 228 229 230
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
231

wafwerar's avatar
wafwerar 已提交
232
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
233 234

  BY_HANDLE_FILE_INFORMATION bhfi;
235
  HANDLE                     handle = (HANDLE)_get_osfhandle(pFile->fd);
wafwerar's avatar
wafwerar 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248
  if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
    printf("taosFStatFile get file info fail.");
    return -1;
  }

  if (stDev != NULL) {
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
  }

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

249
#else
250

wafwerar's avatar
wafwerar 已提交
251 252
  struct stat fileStat;
  int32_t     code = fstat(pFile->fd, &fileStat);
253
  if (code < 0) {
wafwerar's avatar
wafwerar 已提交
254
    printf("taosFStatFile run fstat fail.");
255 256 257 258 259 260 261 262 263 264
    return code;
  }

  if (stDev != NULL) {
    *stDev = fileStat.st_dev;
  }

  if (stIno != NULL) {
    *stIno = fileStat.st_ino;
  }
wafwerar's avatar
wafwerar 已提交
265
#endif
266 267 268

  return 0;
}
269

wafwerar's avatar
wafwerar 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
void autoDelFileList() {
  taosThreadMutexLock(&autoDelFileLock);
  while (nowAutoDelFilePtr != NULL) {
    taosRemoveFile(nowAutoDelFilePtr->name);
    AutoDelFilePtr tmp = nowAutoDelFilePtr->lastAutoDelFilePtr;
    taosMemoryFree(nowAutoDelFilePtr->name);
    taosMemoryFree(nowAutoDelFilePtr);
    nowAutoDelFilePtr = tmp;
  }
  taosThreadMutexUnlock(&autoDelFileLock);
  taosThreadMutexDestroy(&autoDelFileLock);
}

void autoDelFileListInit() {
  taosThreadMutexInit(&autoDelFileLock, NULL);
  atexit(autoDelFileList);
}

void autoDelFileListAdd(const char *path) {
  taosThreadOnce(&autoDelFileInit, autoDelFileListInit);
  taosThreadMutexLock(&autoDelFileLock);
  AutoDelFilePtr tmp = taosMemoryMalloc(sizeof(AutoDelFile));
  tmp->lastAutoDelFilePtr = nowAutoDelFilePtr;
  tmp->name = taosMemoryStrDup(path);
  nowAutoDelFilePtr = tmp;
  taosThreadMutexUnlock(&autoDelFileLock);
}

298
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
L
Liu Jicong 已提交
299
  int   fd = -1;
300 301 302 303 304
  FILE *fp = NULL;
  if (tdFileOptions & TD_FILE_STREAM) {
    char *mode = NULL;
    if (tdFileOptions & TD_FILE_APPEND) {
      mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
L
Liu Jicong 已提交
305
    } else if (tdFileOptions & TD_FILE_TRUNC) {
306
      mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
L
Liu Jicong 已提交
307
    } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
308
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
L
Liu Jicong 已提交
309
    } else {
310 311 312 313 314 315 316 317 318
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
    }
    assert(!(tdFileOptions & TD_FILE_EXCL));
    fp = fopen(path, mode);
    if (fp == NULL) {
      return NULL;
    }
  } else {
    int access = O_BINARY;
319
    access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
320 321 322 323 324 325 326 327 328 329 330
    if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
      access |= O_RDWR;
    } else if (tdFileOptions & TD_FILE_WRITE) {
      access |= O_WRONLY;
    } else if (tdFileOptions & TD_FILE_READ) {
      access |= O_RDONLY;
    }
    access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
    access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
    access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
    access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
L
Liu Jicong 已提交
331 332 333
#ifdef WINDOWS
    fd = _open(path, access, _S_IREAD | _S_IWRITE);
#else
334
    fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
L
Liu Jicong 已提交
335
#endif
336 337 338 339 340
    if (fd == -1) {
      return NULL;
    }
  }

wafwerar's avatar
wafwerar 已提交
341
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
342
  if (pFile == NULL) {
343 344
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
345 346
    return NULL;
  }
347
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
348
  taosThreadRwlockInit(&(pFile->rwlock), NULL);
349
#endif
350 351 352
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
wafwerar's avatar
wafwerar 已提交
353
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
wafwerar's avatar
wafwerar 已提交
354
    autoDelFileListAdd(path);
wafwerar's avatar
wafwerar 已提交
355
  }
356 357 358
  return pFile;
}

L
Liu Jicong 已提交
359 360
int32_t taosCloseFile(TdFilePtr *ppFile) {
  int32_t code = 0;
361 362 363 364
  if (ppFile == NULL || *ppFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
365
  taosThreadRwlockWrlock(&((*ppFile)->rwlock));
366
#endif
367 368 369 370 371 372
  if ((*ppFile)->fp != NULL) {
    fflush((*ppFile)->fp);
    fclose((*ppFile)->fp);
    (*ppFile)->fp = NULL;
  }
  if ((*ppFile)->fd >= 0) {
373
#ifdef WINDOWS
374 375
    HANDLE h = (HANDLE)_get_osfhandle((*ppFile)->fd);
    !FlushFileBuffers(h);
376
#else
L
Liu Jicong 已提交
377 378
    // warning: never fsync silently in base lib
    /*fsync((*ppFile)->fd);*/
379
#endif
L
Liu Jicong 已提交
380
    code = close((*ppFile)->fd);
381 382
    (*ppFile)->fd = -1;
  }
383
  (*ppFile)->refId = 0;
384
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
385 386
  taosThreadRwlockUnlock(&((*ppFile)->rwlock));
  taosThreadRwlockDestroy(&((*ppFile)->rwlock));
387
#endif
wafwerar's avatar
wafwerar 已提交
388
  taosMemoryFree(*ppFile);
389
  *ppFile = NULL;
L
Liu Jicong 已提交
390
  return code;
391 392 393
}

int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
394
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
395
  taosThreadRwlockRdlock(&(pFile->rwlock));
396
#endif
L
Liu Jicong 已提交
397
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
S
TD-1912  
Shengliang Guan 已提交
398 399
  int64_t leftbytes = count;
  int64_t readbytes;
400
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
401 402

  while (leftbytes > 0) {
403
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
404
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
405
#else
406
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
407
#endif
S
Shengliang Guan 已提交
408 409 410 411
    if (readbytes < 0) {
      if (errno == EINTR) {
        continue;
      } else {
412
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
413
        taosThreadRwlockUnlock(&(pFile->rwlock));
414
#endif
S
Shengliang Guan 已提交
415 416 417
        return -1;
      }
    } else if (readbytes == 0) {
418
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
419
      taosThreadRwlockUnlock(&(pFile->rwlock));
420
#endif
S
TD-1912  
Shengliang Guan 已提交
421
      return (int64_t)(count - leftbytes);
S
Shengliang Guan 已提交
422 423 424 425 426 427
    }

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

428
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
429
  taosThreadRwlockUnlock(&(pFile->rwlock));
430
#endif
S
TD-1912  
Shengliang Guan 已提交
431
  return count;
S
Shengliang Guan 已提交
432 433
}

434
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
435
  if (pFile == NULL) {
436 437
    return 0;
  }
438
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
439
  taosThreadRwlockRdlock(&(pFile->rwlock));
440
#endif
L
Liu Jicong 已提交
441
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
442
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
443 444 445 446
  size_t pos = _lseek(pFile->fd, 0, SEEK_CUR);
  _lseek(pFile->fd, offset, SEEK_SET);
  int64_t ret = _read(pFile->fd, buf, count);
  _lseek(pFile->fd, pos, SEEK_SET);
wafwerar's avatar
wafwerar 已提交
447
#else
448
  int64_t ret = pread(pFile->fd, buf, count, offset);
wafwerar's avatar
wafwerar 已提交
449
#endif
450
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
451
  taosThreadRwlockUnlock(&(pFile->rwlock));
452 453
#endif
  return ret;
454 455 456
}

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
wafwerar's avatar
wafwerar 已提交
457 458 459
  if (pFile == NULL) {
    return 0;
  }
460
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
461
  taosThreadRwlockWrlock(&(pFile->rwlock));
462
#endif
L
Liu Jicong 已提交
463
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
464

465
  int64_t nleft = count;
S
TD-1912  
Shengliang Guan 已提交
466
  int64_t nwritten = 0;
467
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
468 469

  while (nleft > 0) {
470
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
S
Shengliang Guan 已提交
471 472 473 474
    if (nwritten < 0) {
      if (errno == EINTR) {
        continue;
      }
475
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
476
      taosThreadRwlockUnlock(&(pFile->rwlock));
477
#endif
S
Shengliang Guan 已提交
478 479 480 481 482
      return -1;
    }
    nleft -= nwritten;
    tbuf += nwritten;
  }
483

484
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
485
  taosThreadRwlockUnlock(&(pFile->rwlock));
486
#endif
487
  return count;
S
Shengliang Guan 已提交
488 489
}

490
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
491
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
492
  taosThreadRwlockRdlock(&(pFile->rwlock));
493
#endif
L
Liu Jicong 已提交
494
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
495 496 497
#ifdef WINDOWS
  int64_t ret = _lseek(pFile->fd, offset, whence);
#else
L
Liu Jicong 已提交
498
  int64_t ret = lseek(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
499
#endif
500
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
501
  taosThreadRwlockUnlock(&(pFile->rwlock));
502 503
#endif
  return ret;
504
}
S
Shengliang Guan 已提交
505

506
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
507 508 509
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
510
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
511

512
  struct stat fileStat;
513
#ifdef WINDOWS
514
  int32_t code = _fstat(pFile->fd, &fileStat);
515
#else
516
  int32_t code = fstat(pFile->fd, &fileStat);
517
#endif
518 519 520
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
521

522 523 524
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
525

526 527 528
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
529

530 531
  return 0;
}
H
Hongze Cheng 已提交
532

533
int32_t taosLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
534
#ifdef WINDOWS
535 536
  return 0;
#else
L
Liu Jicong 已提交
537
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
538

539 540 541
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
542

543
int32_t taosUnLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
544
#ifdef WINDOWS
545 546
  return 0;
#else
L
Liu Jicong 已提交
547
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
548

549 550 551 552 553
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
wafwerar's avatar
wafwerar 已提交
554
#ifdef WINDOWS
555 556
  if (pFile->fd < 0) {
    errno = EBADF;
557
    printf("Ftruncate file error, fd arg was negative\n");
558
    return -1;
H
Hongze Cheng 已提交
559 560
  }

561
  HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
H
Hongze Cheng 已提交
562

563 564 565 566
  LARGE_INTEGER li_0;
  li_0.QuadPart = (int64_t)0;
  BOOL cur = SetFilePointerEx(h, li_0, NULL, FILE_CURRENT);
  if (!cur) {
wafwerar's avatar
wafwerar 已提交
567
    printf("SetFilePointerEx Error getting current position in file.\n");
568 569
    return -1;
  }
H
Hongze Cheng 已提交
570

571 572 573 574 575
  LARGE_INTEGER li_size;
  li_size.QuadPart = l_size;
  BOOL cur2 = SetFilePointerEx(h, li_size, NULL, FILE_BEGIN);
  if (cur2 == 0) {
    int error = GetLastError();
wafwerar's avatar
wafwerar 已提交
576
    printf("SetFilePointerEx GetLastError is: %d\n", error);
577 578 579 580 581 582 583 584 585 586 587 588 589
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  if (!SetEndOfFile(h)) {
    int error = GetLastError();
wafwerar's avatar
wafwerar 已提交
590
    printf("SetEndOfFile GetLastError is:%d", error);
591 592 593 594 595 596 597 598 599 600 601 602 603
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
604 605 606
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
607
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
608

609 610 611 612 613
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
614 615 616 617
  if (pFile == NULL) {
    return 0;
  }

L
Liu Jicong 已提交
618 619
  // this implementation is WRONG
  // fflush is not a replacement of fsync
620
  if (pFile->fp != NULL) return fflush(pFile->fp);
621
  if (pFile->fd >= 0) {
622
#ifdef WINDOWS
623 624
    HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
    return !FlushFileBuffers(h);
625
#else
626
    return fsync(pFile->fd);
627
#endif
628
  }
629
  return 0;
H
Hongze Cheng 已提交
630 631
}

wafwerar's avatar
wafwerar 已提交
632 633 634
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
  if (pFileOut == NULL || pFileIn == NULL) {
    return 0;
S
TD-4088  
Shengliang Guan 已提交
635
  }
wafwerar's avatar
wafwerar 已提交
636
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
637

wafwerar's avatar
wafwerar 已提交
638
#ifdef WINDOWS
S
TD-4088  
Shengliang Guan 已提交
639

wafwerar's avatar
wafwerar 已提交
640
  _lseek(pFileIn->fd, (int32_t)(*offset), 0);
S
TD-4088  
Shengliang Guan 已提交
641 642 643
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

wafwerar's avatar
wafwerar 已提交
644
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
645
    size_t rlen = _read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
646 647 648
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
649
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
S
TD-4088  
Shengliang Guan 已提交
650 651
      return (int64_t)(writeLen + rlen);
    } else {
wafwerar's avatar
wafwerar 已提交
652
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
653 654 655 656
      writeLen += _SEND_FILE_STEP_;
    }
  }

wafwerar's avatar
wafwerar 已提交
657
  int64_t remain = size - writeLen;
S
TD-4088  
Shengliang Guan 已提交
658
  if (remain > 0) {
wafwerar's avatar
wafwerar 已提交
659
    size_t rlen = _read(pFileIn->fd, (void *)buffer, (size_t)remain);
S
TD-4088  
Shengliang Guan 已提交
660 661 662
    if (rlen <= 0) {
      return writeLen;
    } else {
wafwerar's avatar
wafwerar 已提交
663
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
S
TD-4088  
Shengliang Guan 已提交
664 665 666 667 668 669
      writeLen += remain;
    }
  }
  return writeLen;

#elif defined(_TD_DARWIN_64)
S
TD-1912  
Shengliang Guan 已提交
670

wafwerar's avatar
wafwerar 已提交
671 672 673 674 675 676 677 678 679 680 681 682 683 684
  lseek(pFileIn->fd, (int32_t)(*offset), 0);
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
      return (int64_t)(writeLen + rlen);
    } else {
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
      writeLen += _SEND_FILE_STEP_;
S
TD-4088  
Shengliang Guan 已提交
685
    }
wafwerar's avatar
wafwerar 已提交
686 687 688 689 690 691 692 693 694 695
  }

  int64_t remain = size - writeLen;
  if (remain > 0) {
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
    if (rlen <= 0) {
      return writeLen;
    } else {
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
      writeLen += remain;
S
TD-4088  
Shengliang Guan 已提交
696 697
    }
  }
wafwerar's avatar
wafwerar 已提交
698
  return writeLen;
S
TD-4088  
Shengliang Guan 已提交
699 700 701

#else

S
TD-1912  
Shengliang Guan 已提交
702 703
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
704 705

  while (leftbytes > 0) {
wafwerar's avatar
wafwerar 已提交
706 707 708
  #ifdef _TD_ARM_32
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int*)offset, leftbytes);
  #else
709
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
wafwerar's avatar
wafwerar 已提交
710
  #endif
S
Shengliang Guan 已提交
711
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
712
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
713 714 715 716 717
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
718
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
719 720 721 722 723 724
    }

    leftbytes -= sentbytes;
  }

  return size;
S
Shengliang Guan 已提交
725
#endif
wafwerar's avatar
wafwerar 已提交
726
}
S
Shengliang Guan 已提交
727

728
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
729 730 731 732 733
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

734
  va_list ap;
735
  va_start(ap, format);
736
  vfprintf(pFile->fp, format, ap);
737 738
  va_end(ap);
  fflush(pFile->fp);
S
Shengliang Guan 已提交
739 740
}

741
bool taosValidFile(TdFilePtr pFile) { return pFile != NULL && pFile->fd > 0; }
S
Shengliang Guan 已提交
742

743
int32_t taosUmaskFile(int32_t maskVal) {
wafwerar's avatar
wafwerar 已提交
744
#ifdef WINDOWS
S
Shengliang Guan 已提交
745 746
  return 0;
#else
747
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
748
#endif
749 750
}

751
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
wafwerar's avatar
wafwerar 已提交
752
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
L
Liu Jicong 已提交
753
  if (pFile == NULL || ptrBuf == NULL) {
754 755
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
756 757 758
  if (*ptrBuf != NULL) {
    taosMemoryFreeClear(*ptrBuf);
  }
759
  assert(pFile->fp != NULL);
wafwerar's avatar
wafwerar 已提交
760 761 762 763 764 765 766 767 768 769
#ifdef WINDOWS
  *ptrBuf = taosMemoryMalloc(1024);
  if (*ptrBuf == NULL) return -1;
  if (fgets(*ptrBuf, 1023, pFile->fp) == NULL) {
    taosMemoryFreeClear(*ptrBuf);
    return -1;
  }
  (*ptrBuf)[1023] = 0;
  return strlen(*ptrBuf);
#else
770 771
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
wafwerar's avatar
wafwerar 已提交
772
#endif
773
}
wafwerar's avatar
wafwerar 已提交
774
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
L
Liu Jicong 已提交
775
  if (pFile == NULL || buf == NULL) {
wafwerar's avatar
wafwerar 已提交
776 777 778 779 780 781 782 783
    return -1;
  }
  assert(pFile->fp != NULL);
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
    return -1;
  }
  return strlen(buf);
}
L
Liu Jicong 已提交
784
int32_t taosEOFFile(TdFilePtr pFile) {
785 786 787 788 789
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
790
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
791
}
792

793 794 795 796 797 798 799 800 801 802 803 804 805 806
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
  int flags = 0;

  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
    flags |= F_OK;
  }

  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
    flags |= R_OK;
  }

  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
    flags |= W_OK;
  }
wafwerar's avatar
wafwerar 已提交
807 808 809
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
810
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
811
#endif
812
}
813 814

bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };