osFile.c 18.9 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
}

165 166
int32_t taosRemoveFile(const char *path) { return remove(path); }

167
int32_t taosRenameFile(const char *oldName, const char *newName) {
wafwerar's avatar
wafwerar 已提交
168
#ifdef WINDOWS
169 170
  bool code = MoveFileEx(oldName, newName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
  if (!code) {
C
Cary Xu 已提交
171
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
172 173
  }

174
  return !code;
175 176 177
#else
  int32_t code = rename(oldName, newName);
  if (code < 0) {
C
Cary Xu 已提交
178
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
179 180 181 182 183 184 185
  }

  return code;
#endif
}

int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) {
186
  struct stat fileStat;
wafwerar's avatar
wafwerar 已提交
187
#ifdef WINDOWS
188
  int32_t code = _stat(path, &fileStat);
189
#else
190
  int32_t code = stat(path, &fileStat);
191
#endif
192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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 已提交
206 207 208 209 210
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.
211

wafwerar's avatar
wafwerar 已提交
212
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
213 214

  BY_HANDLE_FILE_INFORMATION bhfi;
215
  HANDLE                     handle = (HANDLE)_get_osfhandle(pFile->fd);
wafwerar's avatar
wafwerar 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228
  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);
  }

229
#else
230

wafwerar's avatar
wafwerar 已提交
231 232
  struct stat fileStat;
  int32_t     code = fstat(pFile->fd, &fileStat);
233
  if (code < 0) {
wafwerar's avatar
wafwerar 已提交
234
    printf("taosFStatFile run fstat fail.");
235 236 237 238 239 240 241 242 243 244
    return code;
  }

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

  if (stIno != NULL) {
    *stIno = fileStat.st_ino;
  }
wafwerar's avatar
wafwerar 已提交
245
#endif
246 247 248

  return 0;
}
249

wafwerar's avatar
wafwerar 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
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);
}

278
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
L
Liu Jicong 已提交
279
  int   fd = -1;
280 281 282 283 284
  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 已提交
285
    } else if (tdFileOptions & TD_FILE_TRUNC) {
286
      mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
L
Liu Jicong 已提交
287
    } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
288
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
L
Liu Jicong 已提交
289
    } else {
290 291 292 293 294 295 296 297 298
      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;
299
    access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
300 301 302 303 304 305 306 307 308 309 310
    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 已提交
311 312 313
#ifdef WINDOWS
    fd = _open(path, access, _S_IREAD | _S_IWRITE);
#else
314
    fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
L
Liu Jicong 已提交
315
#endif
316 317 318 319 320
    if (fd == -1) {
      return NULL;
    }
  }

wafwerar's avatar
wafwerar 已提交
321
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
322
  if (pFile == NULL) {
323 324
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
325 326
    return NULL;
  }
327
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
328
  taosThreadRwlockInit(&(pFile->rwlock), NULL);
329
#endif
330 331 332
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
wafwerar's avatar
wafwerar 已提交
333
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
wafwerar's avatar
wafwerar 已提交
334
    autoDelFileListAdd(path);
wafwerar's avatar
wafwerar 已提交
335
  }
336 337 338
  return pFile;
}

L
Liu Jicong 已提交
339 340
int32_t taosCloseFile(TdFilePtr *ppFile) {
  int32_t code = 0;
341 342 343 344
  if (ppFile == NULL || *ppFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
345
  taosThreadRwlockWrlock(&((*ppFile)->rwlock));
346
#endif
347 348 349 350 351 352
  if ((*ppFile)->fp != NULL) {
    fflush((*ppFile)->fp);
    fclose((*ppFile)->fp);
    (*ppFile)->fp = NULL;
  }
  if ((*ppFile)->fd >= 0) {
353
#ifdef WINDOWS
354 355
    HANDLE h = (HANDLE)_get_osfhandle((*ppFile)->fd);
    !FlushFileBuffers(h);
356
#else
L
Liu Jicong 已提交
357 358
    // warning: never fsync silently in base lib
    /*fsync((*ppFile)->fd);*/
359
#endif
L
Liu Jicong 已提交
360
    code = close((*ppFile)->fd);
361 362
    (*ppFile)->fd = -1;
  }
363
  (*ppFile)->refId = 0;
364
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
365 366
  taosThreadRwlockUnlock(&((*ppFile)->rwlock));
  taosThreadRwlockDestroy(&((*ppFile)->rwlock));
367
#endif
wafwerar's avatar
wafwerar 已提交
368
  taosMemoryFree(*ppFile);
369
  *ppFile = NULL;
L
Liu Jicong 已提交
370
  return code;
371 372 373
}

int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
374
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
375
  taosThreadRwlockRdlock(&(pFile->rwlock));
376
#endif
L
Liu Jicong 已提交
377
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
S
TD-1912  
Shengliang Guan 已提交
378 379
  int64_t leftbytes = count;
  int64_t readbytes;
380
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
381 382

  while (leftbytes > 0) {
383
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
384
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
385
#else
386
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
387
#endif
S
Shengliang Guan 已提交
388 389 390 391
    if (readbytes < 0) {
      if (errno == EINTR) {
        continue;
      } else {
392
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
393
        taosThreadRwlockUnlock(&(pFile->rwlock));
394
#endif
S
Shengliang Guan 已提交
395 396 397
        return -1;
      }
    } else if (readbytes == 0) {
398
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
399
      taosThreadRwlockUnlock(&(pFile->rwlock));
400
#endif
S
TD-1912  
Shengliang Guan 已提交
401
      return (int64_t)(count - leftbytes);
S
Shengliang Guan 已提交
402 403 404 405 406 407
    }

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

408
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
409
  taosThreadRwlockUnlock(&(pFile->rwlock));
410
#endif
S
TD-1912  
Shengliang Guan 已提交
411
  return count;
S
Shengliang Guan 已提交
412 413
}

414
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
415
  if (pFile == NULL) {
416 417
    return 0;
  }
418
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
419
  taosThreadRwlockRdlock(&(pFile->rwlock));
420
#endif
L
Liu Jicong 已提交
421
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
422
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
423 424 425 426
  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 已提交
427
#else
428
  int64_t ret = pread(pFile->fd, buf, count, offset);
wafwerar's avatar
wafwerar 已提交
429
#endif
430
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
431
  taosThreadRwlockUnlock(&(pFile->rwlock));
432 433
#endif
  return ret;
434 435 436
}

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
wafwerar's avatar
wafwerar 已提交
437 438 439
  if (pFile == NULL) {
    return 0;
  }
440
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
441
  taosThreadRwlockWrlock(&(pFile->rwlock));
442
#endif
L
Liu Jicong 已提交
443
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
444

445
  int64_t nleft = count;
S
TD-1912  
Shengliang Guan 已提交
446
  int64_t nwritten = 0;
447
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
448 449

  while (nleft > 0) {
450
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
S
Shengliang Guan 已提交
451 452 453 454
    if (nwritten < 0) {
      if (errno == EINTR) {
        continue;
      }
455
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
456
      taosThreadRwlockUnlock(&(pFile->rwlock));
457
#endif
S
Shengliang Guan 已提交
458 459 460 461 462
      return -1;
    }
    nleft -= nwritten;
    tbuf += nwritten;
  }
463

464
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
465
  taosThreadRwlockUnlock(&(pFile->rwlock));
466
#endif
467
  return count;
S
Shengliang Guan 已提交
468 469
}

470
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
471
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
472
  taosThreadRwlockRdlock(&(pFile->rwlock));
473
#endif
L
Liu Jicong 已提交
474
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
475 476 477
#ifdef WINDOWS
  int64_t ret = _lseek(pFile->fd, offset, whence);
#else
L
Liu Jicong 已提交
478
  int64_t ret = lseek(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
479
#endif
480
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
481
  taosThreadRwlockUnlock(&(pFile->rwlock));
482 483
#endif
  return ret;
484
}
S
Shengliang Guan 已提交
485

486
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
487 488 489
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
490
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
491

492
  struct stat fileStat;
493
#ifdef WINDOWS
494
  int32_t code = _fstat(pFile->fd, &fileStat);
495
#else
496
  int32_t code = fstat(pFile->fd, &fileStat);
497
#endif
498 499 500
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
501

502 503 504
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
505

506 507 508
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
509

510 511
  return 0;
}
H
Hongze Cheng 已提交
512

513
int32_t taosLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
514
#ifdef WINDOWS
515 516
  return 0;
#else
L
Liu Jicong 已提交
517
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
518

519 520 521
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
522

523
int32_t taosUnLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
524
#ifdef WINDOWS
525 526
  return 0;
#else
L
Liu Jicong 已提交
527
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
528

529 530 531 532 533
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
wafwerar's avatar
wafwerar 已提交
534
#ifdef WINDOWS
535 536
  if (pFile->fd < 0) {
    errno = EBADF;
537
    printf("Ftruncate file error, fd arg was negative\n");
538
    return -1;
H
Hongze Cheng 已提交
539 540
  }

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

543 544 545 546
  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 已提交
547
    printf("SetFilePointerEx Error getting current position in file.\n");
548 549
    return -1;
  }
H
Hongze Cheng 已提交
550

551 552 553 554 555
  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 已提交
556
    printf("SetFilePointerEx GetLastError is: %d\n", error);
557 558 559 560 561 562 563 564 565 566 567 568 569
    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 已提交
570
    printf("SetEndOfFile GetLastError is:%d", error);
571 572 573 574 575 576 577 578 579 580 581 582 583
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
584 585 586
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
587
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
588

589 590 591 592 593
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
594 595 596 597
  if (pFile == NULL) {
    return 0;
  }

L
Liu Jicong 已提交
598 599
  // this implementation is WRONG
  // fflush is not a replacement of fsync
600
  if (pFile->fp != NULL) return fflush(pFile->fp);
601
  if (pFile->fd >= 0) {
602
#ifdef WINDOWS
603 604
    HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
    return !FlushFileBuffers(h);
605
#else
606
    return fsync(pFile->fd);
607
#endif
608
  }
609
  return 0;
H
Hongze Cheng 已提交
610 611
}

wafwerar's avatar
wafwerar 已提交
612 613 614
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 已提交
615
  }
wafwerar's avatar
wafwerar 已提交
616
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
617

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

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

wafwerar's avatar
wafwerar 已提交
624
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
625
    size_t rlen = _read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
626 627 628
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
629
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
S
TD-4088  
Shengliang Guan 已提交
630 631
      return (int64_t)(writeLen + rlen);
    } else {
wafwerar's avatar
wafwerar 已提交
632
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
633 634 635 636
      writeLen += _SEND_FILE_STEP_;
    }
  }

wafwerar's avatar
wafwerar 已提交
637
  int64_t remain = size - writeLen;
S
TD-4088  
Shengliang Guan 已提交
638
  if (remain > 0) {
wafwerar's avatar
wafwerar 已提交
639
    size_t rlen = _read(pFileIn->fd, (void *)buffer, (size_t)remain);
S
TD-4088  
Shengliang Guan 已提交
640 641 642
    if (rlen <= 0) {
      return writeLen;
    } else {
wafwerar's avatar
wafwerar 已提交
643
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
S
TD-4088  
Shengliang Guan 已提交
644 645 646 647 648 649
      writeLen += remain;
    }
  }
  return writeLen;

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

wafwerar's avatar
wafwerar 已提交
651 652 653 654 655 656 657 658 659 660 661 662 663 664
  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 已提交
665
    }
wafwerar's avatar
wafwerar 已提交
666 667 668 669 670 671 672 673 674 675
  }

  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 已提交
676 677
    }
  }
wafwerar's avatar
wafwerar 已提交
678
  return writeLen;
S
TD-4088  
Shengliang Guan 已提交
679 680 681

#else

S
TD-1912  
Shengliang Guan 已提交
682 683
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
684 685

  while (leftbytes > 0) {
686
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
S
Shengliang Guan 已提交
687
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
688
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
689 690 691 692 693
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
694
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
695 696 697 698 699 700
    }

    leftbytes -= sentbytes;
  }

  return size;
S
Shengliang Guan 已提交
701
#endif
wafwerar's avatar
wafwerar 已提交
702
}
S
Shengliang Guan 已提交
703

704
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
705 706 707 708 709
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

710
  va_list ap;
711
  va_start(ap, format);
712
  vfprintf(pFile->fp, format, ap);
713 714
  va_end(ap);
  fflush(pFile->fp);
S
Shengliang Guan 已提交
715 716
}

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

719
int32_t taosUmaskFile(int32_t maskVal) {
wafwerar's avatar
wafwerar 已提交
720
#ifdef WINDOWS
S
Shengliang Guan 已提交
721 722
  return 0;
#else
723
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
724
#endif
725 726
}

727
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
wafwerar's avatar
wafwerar 已提交
728
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
L
Liu Jicong 已提交
729
  if (pFile == NULL || ptrBuf == NULL) {
730 731
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
732 733 734
  if (*ptrBuf != NULL) {
    taosMemoryFreeClear(*ptrBuf);
  }
735
  assert(pFile->fp != NULL);
wafwerar's avatar
wafwerar 已提交
736 737 738 739 740 741 742 743 744 745
#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
746 747
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
wafwerar's avatar
wafwerar 已提交
748
#endif
749
}
wafwerar's avatar
wafwerar 已提交
750
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
L
Liu Jicong 已提交
751
  if (pFile == NULL || buf == NULL) {
wafwerar's avatar
wafwerar 已提交
752 753 754 755 756 757 758 759
    return -1;
  }
  assert(pFile->fp != NULL);
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
    return -1;
  }
  return strlen(buf);
}
L
Liu Jicong 已提交
760
int32_t taosEOFFile(TdFilePtr pFile) {
761 762 763 764 765
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
766
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
767
}
768

769 770 771 772 773 774 775 776 777 778 779 780 781 782
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 已提交
783 784 785
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
786
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
787
#endif
788
}
789 790

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