hFILE *hopen(const char *fname, const char *mode) { if (strncmp(fname, "http://", 7) == 0 || strncmp(fname, "ftp://", 6) == 0) return hopen_net(fname, mode); else if (strncmp(fname, "data:", 5) == 0) return hopen_mem(fname + 5, mode, strlen(fname + 5), 0); // Data must be text for length to be correctly specified else if (strcmp(fname, "-") == 0) return hopen_fd_stdinout(mode); else return hopen_fd(fname, mode); }
hFILE *hopen(const char *fname, const char *mode) { if (strncmp(fname, "http://", 7) == 0 || strncmp(fname, "ftp://", 6) == 0) return hopen_net(fname, mode); else if (strncmp(fname, "data:", 5) == 0) return hopen_mem(fname + 5, mode); else if (strcmp(fname, "-") == 0) return hopen_fd_stdinout(mode); else return hopen_fd(fname, mode); }
static hFILE *hopen_fd(const char *filename, const char *mode) { hFILE_fd *fp = NULL; int fd = open(filename, hfile_oflags(mode), 0666); if (fd < 0) goto error; off_t currentPos = lseek(fd, (size_t)0, SEEK_CUR); // Get the file size off_t fileSize = lseek(fd, (size_t)0, SEEK_END); // Seek back to the begining of file lseek(fd, currentPos, SEEK_SET); size_t lenstr = strlen(filename); // For small files that are not indexes and given rb mode, // we are just going to load them into memory to avoid // repeatedly fetching the same data from disk. if ((fileSize < (1 << 17)) && strcmp(mode, "rb") == 0 && lenstr > 4 && (strcmp(filename + lenstr - 4, ".pbi") != 0 && strcmp(filename + lenstr - 4, ".bai") != 0) ) { char* buffer = malloc(fileSize); ssize_t n = read(fd, buffer, fileSize); if (n < 0) goto error; close(fd); return hopen_mem(buffer, mode, fileSize, 1); } else { fp = (hFILE_fd *) hfile_init(sizeof (hFILE_fd), mode, blksize(fd)); if (fp == NULL) goto error; fp->fd = fd; fp->is_socket = 0; fp->base.backend = &fd_backend; return &fp->base; } error: if (fd >= 0) { int save = errno; (void) close(fd); errno = save; } hfile_destroy((hFILE *) fp); return NULL; }