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) {
wafwerar's avatar
wafwerar 已提交
206
#ifdef WINDOWS
H
Haojun Liao 已提交
207 208
  struct _stati64 fileStat;
  int32_t code = _stati64(path, &fileStat);
209
#else
H
Haojun Liao 已提交
210
  struct stat fileStat;
211
  int32_t code = stat(path, &fileStat);
212
#endif
213 214 215 216 217 218 219 220 221 222 223 224 225 226
  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 已提交
227 228 229 230 231
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.
232

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

  BY_HANDLE_FILE_INFORMATION bhfi;
236
  HANDLE                     handle = (HANDLE)_get_osfhandle(pFile->fd);
wafwerar's avatar
wafwerar 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249
  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);
  }

250
#else
251

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

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

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

  return 0;
}
270

wafwerar's avatar
wafwerar 已提交
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 298
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);
}

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

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

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

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

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

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

564 565 566 567
  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 已提交
568
    printf("SetFilePointerEx Error getting current position in file.\n");
569 570
    return -1;
  }
H
Hongze Cheng 已提交
571

572 573 574 575 576
  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 已提交
577
    printf("SetFilePointerEx GetLastError is: %d\n", error);
578 579 580 581 582 583 584 585 586 587 588 589 590
    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 已提交
591
    printf("SetEndOfFile GetLastError is:%d", error);
592 593 594 595 596 597 598 599 600 601 602 603 604
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

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

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

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

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

wafwerar's avatar
wafwerar 已提交
633 634 635
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 已提交
636
  }
wafwerar's avatar
wafwerar 已提交
637
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
638

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

H
Haojun Liao 已提交
641
  _lseeki64(pFileIn->fd, *offset, 0);
S
TD-4088  
Shengliang Guan 已提交
642 643 644
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

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

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

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

wafwerar's avatar
wafwerar 已提交
672 673 674 675 676 677 678 679 680 681 682 683 684 685
  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 已提交
686
    }
wafwerar's avatar
wafwerar 已提交
687 688 689 690 691 692 693 694 695 696
  }

  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 已提交
697 698
    }
  }
wafwerar's avatar
wafwerar 已提交
699
  return writeLen;
S
TD-4088  
Shengliang Guan 已提交
700 701 702

#else

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

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

    leftbytes -= sentbytes;
  }

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

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

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

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

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

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

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

794 795 796 797 798 799 800 801 802 803 804 805 806 807
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 已提交
808 809 810
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
811
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
812
#endif
813
}
814 815

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