osFile.c 16.4 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
38 39
#endif

wafwerar's avatar
wafwerar 已提交
40 41 42 43 44 45 46 47 48 49 50
#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 已提交
51
  TdThreadRwlock rwlock;
L
Liu Jicong 已提交
52 53 54
  int            refId;
  FileFd         fd;
  FILE          *fp;
wafwerar's avatar
wafwerar 已提交
55 56
} * TdFilePtr, TdFile;

57 58
#define FILE_WITH_LOCK 1

59
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
wafwerar's avatar
wafwerar 已提交
60
#ifdef WINDOWS
S
Shengliang Guan 已提交
61
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
TD-4088  
Shengliang Guan 已提交
62
  char        tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
63

S
Shengliang Guan 已提交
64 65
  int32_t len = (int32_t)strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
66 67 68

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

71
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
S
TD-4088  
Shengliang Guan 已提交
72
  strcat(tmpPath, tdengineTmpFileNamePrefix);
S
Shengliang Guan 已提交
73 74 75
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
76
  }
S
Shengliang Guan 已提交
77

S
TD-4088  
Shengliang Guan 已提交
78 79
  char rand[8] = {0};
  taosRandStr(rand, tListLen(rand) - 1);
S
Shengliang Guan 已提交
80
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
TD-1912  
Shengliang Guan 已提交
81

S
TD-4088  
Shengliang Guan 已提交
82
#else
S
Shengliang Guan 已提交
83

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

86
  char    tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
87 88
  int32_t len = strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
89
  static uint64_t seqId = 0;
S
Shengliang Guan 已提交
90

S
TD-4088  
Shengliang Guan 已提交
91 92
  if (tmpPath[len - 1] != '/') {
    tmpPath[len++] = '/';
S
TD-1912  
Shengliang Guan 已提交
93
  }
S
Shengliang Guan 已提交
94

S
TD-4088  
Shengliang Guan 已提交
95 96 97 98
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
99 100
  }

S
TD-4088  
Shengliang Guan 已提交
101 102 103
  char rand[32] = {0};

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

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

S
TD-4088  
Shengliang Guan 已提交
107
#endif
S
Shengliang Guan 已提交
108
}
S
TD-4088  
Shengliang Guan 已提交
109

110
int64_t taosCopyFile(const char *from, const char *to) {
wafwerar's avatar
wafwerar 已提交
111
#ifdef WINDOWS
112 113 114 115 116 117 118
  return 0;
#else
  char    buffer[4096];
  int64_t size = 0;
  int64_t bytes;

  // fidfrom = open(from, O_RDONLY);
119
  TdFilePtr pFileFrom = taosOpenFile(from, TD_FILE_READ);
120 121 122
  if (pFileFrom == NULL) goto _err;

  // fidto = open(to, O_WRONLY | O_CREAT | O_EXCL, 0755);
123
  TdFilePtr pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
  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);
146
  taosRemoveFile(to);
147 148 149 150
  return -1;
#endif
}

151 152
int32_t taosRemoveFile(const char *path) { return remove(path); }

153
int32_t taosRenameFile(const char *oldName, const char *newName) {
wafwerar's avatar
wafwerar 已提交
154
#ifdef WINDOWS
155 156
  int32_t code = MoveFileEx(oldName, newName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
  if (code < 0) {
157
    // printf("failed to rename file %s to %s, reason:%s", oldName, newName, strerror(errno));
158 159 160 161 162 163
  }

  return code;
#else
  int32_t code = rename(oldName, newName);
  if (code < 0) {
164
    // printf("failed to rename file %s to %s, reason:%s", oldName, newName, strerror(errno));
165 166 167 168 169 170 171
  }

  return code;
#endif
}

int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) {
wafwerar's avatar
wafwerar 已提交
172
#ifdef WINDOWS
173 174 175
  return 0;
#else
  struct stat fileStat;
L
Liu Jicong 已提交
176
  int32_t     code = stat(path, &fileStat);
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  if (code < 0) {
    return code;
  }

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

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

  return 0;
#endif
}
192
int32_t taosDevInoFile(const char *path, int64_t *stDev, int64_t *stIno) {
wafwerar's avatar
wafwerar 已提交
193
#ifdef WINDOWS
194 195 196
  return 0;
#else
  struct stat fileStat;
L
Liu Jicong 已提交
197
  int32_t     code = stat(path, &fileStat);
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
  if (code < 0) {
    return code;
  }

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

  if (stIno != NULL) {
    *stIno = fileStat.st_ino;
  }

  return 0;
#endif
}
213

214
void autoDelFileListAdd(const char *path) { return; }
215

216
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
L
Liu Jicong 已提交
217
  int   fd = -1;
218 219 220 221 222
  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 已提交
223
    } else if (tdFileOptions & TD_FILE_TRUNC) {
224
      mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
L
Liu Jicong 已提交
225
    } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
226
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
L
Liu Jicong 已提交
227
    } else {
228 229 230 231 232 233 234 235 236
      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;
237
    access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
238 239 240 241 242 243 244 245 246 247 248
    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 已提交
249 250 251
#ifdef WINDOWS
    fd = _open(path, access, _S_IREAD | _S_IWRITE);
#else
252
    fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
L
Liu Jicong 已提交
253
#endif
254 255 256 257 258
    if (fd == -1) {
      return NULL;
    }
  }

259
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
260 261
    autoDelFileListAdd(path);
  }
262

wafwerar's avatar
wafwerar 已提交
263
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
264
  if (pFile == NULL) {
265 266
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
267 268
    return NULL;
  }
269
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
270
  taosThreadRwlockInit(&(pFile->rwlock), NULL);
271
#endif
272 273 274 275 276 277 278
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
  return pFile;
}

int64_t taosCloseFile(TdFilePtr *ppFile) {
wafwerar's avatar
wafwerar 已提交
279
#ifdef WINDOWS
280 281
  return 0;
#else
282 283 284 285
  if (ppFile == NULL || *ppFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
286
  taosThreadRwlockWrlock(&((*ppFile)->rwlock));
287
#endif
288
  if (ppFile == NULL || *ppFile == NULL) {
289 290
    return 0;
  }
291 292 293 294 295 296 297 298 299 300
  if ((*ppFile)->fp != NULL) {
    fflush((*ppFile)->fp);
    fclose((*ppFile)->fp);
    (*ppFile)->fp = NULL;
  }
  if ((*ppFile)->fd >= 0) {
    fsync((*ppFile)->fd);
    close((*ppFile)->fd);
    (*ppFile)->fd = -1;
  }
301
  (*ppFile)->refId = 0;
302
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
303 304
  taosThreadRwlockUnlock(&((*ppFile)->rwlock));
  taosThreadRwlockDestroy(&((*ppFile)->rwlock));
305
#endif
wafwerar's avatar
wafwerar 已提交
306
  taosMemoryFree(*ppFile);
307 308 309 310 311 312
  *ppFile = NULL;
  return 0;
#endif
}

int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
313
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
314
  taosThreadRwlockRdlock(&(pFile->rwlock));
315
#endif
L
Liu Jicong 已提交
316
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
S
TD-1912  
Shengliang Guan 已提交
317 318
  int64_t leftbytes = count;
  int64_t readbytes;
319
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
320 321

  while (leftbytes > 0) {
322
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
S
Shengliang Guan 已提交
323 324 325 326
    if (readbytes < 0) {
      if (errno == EINTR) {
        continue;
      } else {
327
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
328
        taosThreadRwlockUnlock(&(pFile->rwlock));
329
#endif
S
Shengliang Guan 已提交
330 331 332
        return -1;
      }
    } else if (readbytes == 0) {
333
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
334
      taosThreadRwlockUnlock(&(pFile->rwlock));
335
#endif
S
TD-1912  
Shengliang Guan 已提交
336
      return (int64_t)(count - leftbytes);
S
Shengliang Guan 已提交
337 338 339 340 341 342
    }

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

343
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
344
  taosThreadRwlockUnlock(&(pFile->rwlock));
345
#endif
S
TD-1912  
Shengliang Guan 已提交
346
  return count;
S
Shengliang Guan 已提交
347 348
}

349
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
350
  if (pFile == NULL) {
351 352
    return 0;
  }
353
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
354
  taosThreadRwlockRdlock(&(pFile->rwlock));
355
#endif
L
Liu Jicong 已提交
356
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
357 358
#ifdef WINDOWS
  size_t pos = lseek(pFile->fd, 0, SEEK_CUR);
L
Liu Jicong 已提交
359
  lseek(pFile->fd, offset, SEEK_SET);
wafwerar's avatar
wafwerar 已提交
360 361 362
  int64_t ret = read(pFile->fd, buf, count);
  lseek(pFile->fd, pos, SEEK_SET);
#else
363
  int64_t ret = pread(pFile->fd, buf, count, offset);
wafwerar's avatar
wafwerar 已提交
364
#endif
365
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
366
  taosThreadRwlockUnlock(&(pFile->rwlock));
367 368
#endif
  return ret;
369 370 371
}

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
372
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
373
  taosThreadRwlockWrlock(&(pFile->rwlock));
374
#endif
L
Liu Jicong 已提交
375
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
376

377
  int64_t nleft = count;
S
TD-1912  
Shengliang Guan 已提交
378
  int64_t nwritten = 0;
379
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
380 381

  while (nleft > 0) {
382
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
S
Shengliang Guan 已提交
383 384 385 386
    if (nwritten < 0) {
      if (errno == EINTR) {
        continue;
      }
387
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
388
      taosThreadRwlockUnlock(&(pFile->rwlock));
389
#endif
S
Shengliang Guan 已提交
390 391 392 393 394
      return -1;
    }
    nleft -= nwritten;
    tbuf += nwritten;
  }
395

396
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
397
  taosThreadRwlockUnlock(&(pFile->rwlock));
398
#endif
399
  return count;
S
Shengliang Guan 已提交
400 401
}

402
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
403
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
404
  taosThreadRwlockRdlock(&(pFile->rwlock));
405
#endif
L
Liu Jicong 已提交
406
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
L
Liu Jicong 已提交
407
  int64_t ret = lseek(pFile->fd, offset, whence);
408
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
409
  taosThreadRwlockUnlock(&(pFile->rwlock));
410 411
#endif
  return ret;
412
}
S
Shengliang Guan 已提交
413

414
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
wafwerar's avatar
wafwerar 已提交
415
#ifdef WINDOWS
S
Shengliang Guan 已提交
416 417
  return 0;
#else
L
Liu Jicong 已提交
418
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
419

420
  struct stat fileStat;
L
Liu Jicong 已提交
421
  int32_t     code = fstat(pFile->fd, &fileStat);
422 423 424
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
425

426 427 428
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
429

430 431 432
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
433

434 435 436
  return 0;
#endif
}
H
Hongze Cheng 已提交
437

438
int32_t taosLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
439
#ifdef WINDOWS
440 441
  return 0;
#else
L
Liu Jicong 已提交
442
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
443

444 445 446
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
447

448
int32_t taosUnLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
449
#ifdef WINDOWS
450 451
  return 0;
#else
L
Liu Jicong 已提交
452
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
453

454 455 456 457 458
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
wafwerar's avatar
wafwerar 已提交
459
#ifdef WINDOWS
460 461
  if (pFile->fd < 0) {
    errno = EBADF;
wafwerar's avatar
wafwerar 已提交
462
    printf("%s\n", "fd arg was negative");
463
    return -1;
H
Hongze Cheng 已提交
464 465
  }

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

468 469 470 471
  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 已提交
472
    printf("SetFilePointerEx Error getting current position in file.\n");
473 474
    return -1;
  }
H
Hongze Cheng 已提交
475

476 477 478 479 480
  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 已提交
481
    printf("SetFilePointerEx GetLastError is: %d\n", error);
482 483 484 485 486 487 488 489 490 491 492 493 494
    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 已提交
495
    printf("SetEndOfFile GetLastError is:%d", error);
496 497 498 499 500 501 502 503 504 505 506 507 508
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
509 510 511
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
512
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
513

514 515 516 517 518
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
519
#ifdef WINDOWS
520 521
  if (pFile->fd < 0) {
    errno = EBADF;
wafwerar's avatar
wafwerar 已提交
522
    printf("%s\n", "fd arg was negative");
523 524 525 526 527
    return -1;
  }

  HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);

wafwerar's avatar
wafwerar 已提交
528
  return !FlushFileBuffers(h);
529
#else
530 531 532 533 534
  if (pFile == NULL) {
    return 0;
  }

  if (pFile->fp != NULL) return fflush(pFile->fp);
535
  if (pFile->fd >= 0) return fsync(pFile->fd);
536 537

  return 0;
S
Shengliang Guan 已提交
538
#endif
H
Hongze Cheng 已提交
539 540
}

wafwerar's avatar
wafwerar 已提交
541 542 543
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 已提交
544
  }
wafwerar's avatar
wafwerar 已提交
545
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
546

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

wafwerar's avatar
wafwerar 已提交
549
  lseek(pFileIn->fd, (int32_t)(*offset), 0);
S
TD-4088  
Shengliang Guan 已提交
550 551 552
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

wafwerar's avatar
wafwerar 已提交
553 554
  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_);
S
TD-4088  
Shengliang Guan 已提交
555 556 557
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
558
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
S
TD-4088  
Shengliang Guan 已提交
559 560
      return (int64_t)(writeLen + rlen);
    } else {
wafwerar's avatar
wafwerar 已提交
561
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
562 563 564 565
      writeLen += _SEND_FILE_STEP_;
    }
  }

wafwerar's avatar
wafwerar 已提交
566
  int64_t remain = size - writeLen;
S
TD-4088  
Shengliang Guan 已提交
567
  if (remain > 0) {
wafwerar's avatar
wafwerar 已提交
568
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
S
TD-4088  
Shengliang Guan 已提交
569 570 571
    if (rlen <= 0) {
      return writeLen;
    } else {
wafwerar's avatar
wafwerar 已提交
572
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
S
TD-4088  
Shengliang Guan 已提交
573 574 575 576 577 578
      writeLen += remain;
    }
  }
  return writeLen;

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

S
TD-4088  
Shengliang Guan 已提交
580 581 582 583 584
  int r = 0;
  if (offset) {
    r = fseek(in_file, *offset, SEEK_SET);
    if (r == -1) return -1;
  }
wafwerar's avatar
wafwerar 已提交
585
  off_t len = size;
S
TD-4088  
Shengliang Guan 已提交
586
  while (len > 0) {
L
Liu Jicong 已提交
587
    char  buf[1024 * 16];
S
TD-4088  
Shengliang Guan 已提交
588 589 590 591 592 593 594 595 596 597 598 599 600
    off_t n = sizeof(buf);
    if (len < n) n = len;
    size_t m = fread(buf, 1, n, in_file);
    if (m < n) {
      int e = ferror(in_file);
      if (e) return -1;
    }
    if (m == 0) break;
    if (m != fwrite(buf, 1, m, out_file)) {
      return -1;
    }
    len -= m;
  }
wafwerar's avatar
wafwerar 已提交
601
  return size - len;
S
TD-4088  
Shengliang Guan 已提交
602 603 604

#else

S
TD-1912  
Shengliang Guan 已提交
605 606
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
607 608

  while (leftbytes > 0) {
609
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
S
Shengliang Guan 已提交
610
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
611
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
612 613 614 615 616
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
617
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
618 619 620 621 622 623
    }

    leftbytes -= sentbytes;
  }

  return size;
S
Shengliang Guan 已提交
624
#endif
wafwerar's avatar
wafwerar 已提交
625
}
S
Shengliang Guan 已提交
626

627
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
628 629 630 631 632
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

633
  va_list ap;
634
  va_start(ap, format);
635
  vfprintf(pFile->fp, format, ap);
636 637
  va_end(ap);
  fflush(pFile->fp);
S
Shengliang Guan 已提交
638 639
}

640
bool taosValidFile(TdFilePtr pFile) { return pFile != NULL; }
S
Shengliang Guan 已提交
641

642
int32_t taosUmaskFile(int32_t maskVal) {
wafwerar's avatar
wafwerar 已提交
643
#ifdef WINDOWS
S
Shengliang Guan 已提交
644 645
  return 0;
#else
646
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
647
#endif
648 649
}

650
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
wafwerar's avatar
wafwerar 已提交
651
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
L
Liu Jicong 已提交
652
  if (pFile == NULL || ptrBuf == NULL) {
653 654
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
655 656 657
  if (*ptrBuf != NULL) {
    taosMemoryFreeClear(*ptrBuf);
  }
658
  assert(pFile->fp != NULL);
wafwerar's avatar
wafwerar 已提交
659 660 661 662 663 664 665 666 667 668
#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
669 670
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
wafwerar's avatar
wafwerar 已提交
671
#endif
672
}
wafwerar's avatar
wafwerar 已提交
673
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
L
Liu Jicong 已提交
674
  if (pFile == NULL || buf == NULL) {
wafwerar's avatar
wafwerar 已提交
675 676 677 678 679 680 681 682
    return -1;
  }
  assert(pFile->fp != NULL);
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
    return -1;
  }
  return strlen(buf);
}
L
Liu Jicong 已提交
683
int32_t taosEOFFile(TdFilePtr pFile) {
684 685 686 687 688
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
689
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
690
}
691

692 693 694 695 696 697 698 699 700 701 702 703 704 705
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 已提交
706 707 708
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
709
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
710
#endif
711
}
712 713

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