// Closes a stdio stream after flushing the stream and freeing any buffer // associated with the stream (unless the buffer was set with setbuf). Returns // zero on success; EOF on failure (e.g., if the flush fails, or it is not a // valid fileo or the file is not open, etc.). extern "C" int __cdecl fclose(FILE* const public_stream) { __crt_stdio_stream const stream(public_stream); _VALIDATE_RETURN(stream.valid(), EINVAL, EOF); // If the stream is backed by a string, it requires no synchronization, // flushing, etc., so we can simply free it, which resets all of its // data to the defaults. if (stream.is_string_backed()) { __acrt_stdio_free_stream(stream); return EOF; } int return_value = 0; _lock_file(stream.public_stream()); __try { return_value = _fclose_nolock(stream.public_stream()); } __finally { _unlock_file(stream.public_stream()); } return return_value; }
// Writes the binary int value to the stream, byte-by-byte. On success, returns // the value written; on failure, returns EOF. Note, however, that the value may // be EOF--that is, after all, a valid integer--so be sure to test ferror() and // feof() to check for error conditions. extern "C" int __cdecl _putw(int const value, FILE* const stream) { _VALIDATE_RETURN(stream != nullptr, EINVAL, EOF); int return_value = EOF; _lock_file(stream); __try { char const* const first = reinterpret_cast<char const*>(&value); char const* const last = first + sizeof(value); for (char const* it = first; it != last; ++it) { _fputc_nolock(*it, stream); } if (ferror(stream)) __leave; return_value = value; } __finally { _unlock_file(stream); } return return_value; }
int close(int fd) { FSFile *file = (FSFile*)fd; if (!_valid_file(fd)) return -1; //do reference counting file->refs--; if (file->refs > 0) { return 0; } file->closed = 1; if (file->fs->close) { _lock_file(file); file->fs->close(file->fs, file->device, file->internalfd); _unlock_file(file); } file->magic = 0; Process *p = process_get_current(0); LinkNode *node; for (node=p->open_files.first; node; node=node->next) { if (node->data == file) { klist_remove(&p->open_files, node); kfree(node); break; } } return 0; }
int read(int fd, void *buf, unsigned int bytes) { if (!_valid_file(fd)) { klogf("read: Invalid file %x\n", fd); return -1; } FSFile *file = (FSFile*) fd; _lock_file(file); int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); if (!(file->access & O_RDONLY) || !(file->fs->accessmode(file->fs, file->device) & O_RDONLY)) { klogf("Permission error: %d\n", file->access); _set_error(FILE_PERMISSIONS_ERROR, "Invalid permissions"); _unlock_file(file); return -1; } if (!file->fs->pread) { klogf("Read not supported by filesystem: %x\n", file->fs->pread); _set_error(FILE_TYPE_ERROR, "Read not supported by the filesystem driver"); _unlock_file(file); return -1; } int ret, *cursor = ((file->mode & O_PIPE_MODE) && reverse) ? &file->pipe_rcursor : &file->cursor; ret = file->fs->pread(file->fs, file->device, file->internalfd, buf, bytes, *cursor); if (ret < 0) { _unlock_file(file); file->fs->lasterror_message[sizeof(file->fs->lasterror_message)-1] = 0; strncpy(file->errmsg, file->fs->lasterror_message, sizeof(file->errmsg)-1); file->errno = file->fs->lasterror; klogf("Read error:%d: %s\n", file->fs->lasterror, file->fs->lasterror_message); return -1; } *cursor += ret; //klogf("cursorr: %d, ret: %d\n", *cursor, ret); if (file->mode & O_PIPE_MODE) { struct stat sdata; file->fs->stat(file->fs, file->device, (int)file, &sdata); unsigned int size = sdata.st_size; *cursor = *cursor % size; } _unlock_file(file); return ret; }
wint_t fgetwc(FILE *stream) { StdioObject_t* Object; wint_t Result; int ch; _lock_file(stream); Object = get_ioinfo(stream->_fd); if (Object == NULL) { _unlock_file(stream); _set_errno(EBADFD); return (wint_t)-1; } if ((Object->exflag & (EF_UTF8 | EF_UTF16)) || !(Object->wxflag & WX_TEXT)) { char *p; for (p = (char *)&Result; (wint_t *)p < &Result + 1; p++) { ch = fgetc(stream); if (ch == EOF) { Result = WEOF; break; } *p = (char)ch; } } else { char mbs[MB_LEN_MAX]; int len = 0; ch = fgetc(stream); if (ch != EOF) { mbs[0] = (char)ch; if (_issjis1((unsigned char)mbs[0])) { ch = fgetc(stream); if (ch != EOF) { mbs[1] = (char)ch; len = 2; } } else { len = 1; } } if (!len || mbtowc((wchar_t*)&Result, mbs, len) == -1) Result = WEOF; } _unlock_file(stream); return Result; }
int __cdecl vfwprintf(FILE* file, const wchar_t *format, va_list argptr) { int ret; _lock_file(file); ret = wstreamout(file, format, argptr); _unlock_file(file); return ret; }
int pread(int fd, void *buf, unsigned int bytes, unsigned int off) { if (!_valid_file(fd)) { klogf("pread: Invalid file %x\n", fd); return -1; } FSFile *file = (FSFile*) fd; _lock_file(file); //int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); if (!(file->access & O_RDONLY) || !(file->fs->accessmode(file->fs, file->device) & O_RDONLY)) { klogf("Permission error: %d\n", file->access); _set_error(FILE_PERMISSIONS_ERROR, "Invalid permissions"); _unlock_file(file); return -1; } if (!file->fs->pread) { klogf("Read not supported by filesystem: %x\n", file->fs->pread); _set_error(FILE_TYPE_ERROR, "Read not supported by the filesystem driver"); _unlock_file(file); return -1; } int ret = file->fs->pread(file->fs, file->device, file->internalfd, buf, bytes, off); //wrap around in pipe mode if (ret > 0 && ret < (int)bytes && (file->mode & O_PIPE_MODE)) { ret = file->fs->pread(file->fs, file->device, file->internalfd, buf+ret, bytes-ret, 0); } if (ret < 0) { _unlock_file(file); file->fs->lasterror_message[sizeof(file->fs->lasterror_message)-1] = 0; strncpy(file->errmsg, file->fs->lasterror_message, sizeof(file->errmsg)-1); file->errno = file->fs->lasterror; klogf("Read error:%d: %s\n", file->fs->lasterror, file->fs->lasterror_message); return -1; } //klogf("cursorr: %d, ret: %d\n", *cursor, ret); _unlock_file(file); return ret; }
int fstat(int fd, struct stat *out) { FSFile *file = (FSFile*)fd; if (!out) return -1; if (!_valid_file(fd)) return -1; _lock_file(file); int ret = file->fs->fstat(file->fs, file->device, file->internalfd, out); _unlock_file(file); return ret; }
int flush(int fd) { if (!_valid_file(fd)) return -1; FSFile *file = (FSFile*) fd; _lock_file(file); if (file->fs->flush) { file->fs->flush(file->fs, file->device, file->internalfd); } _unlock_file(file); return 0; }
int write(int fd, void *buf, unsigned int bytes) { if (!_valid_file(fd)) return -1; FSFile *file = (FSFile*) fd; _lock_file(file); int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); if (!(file->access & O_RDONLY) || !(file->fs->accessmode(file->fs, file->device) & O_RDONLY)) { _set_error(FILE_PERMISSIONS_ERROR, "Invalid permissions"); _unlock_file(file); return -1; } if (!file->fs->pread) { _set_error(FILE_TYPE_ERROR, "Read not supported by the filesystem driver"); _unlock_file(file); return -1; } int ret, *cursor = !((file->mode & O_PIPE_MODE) && reverse) ? &file->pipe_rcursor : &file->cursor; ret = file->fs->pwrite(file->fs, file->device, file->internalfd, buf, bytes, *cursor); if (!(file->mode & O_NOSEEK)) { *cursor += ret; } //kprintf("cursorw: %d, ret: %d\n", *cursor, ret); if (file->mode & O_PIPE_MODE) { struct stat sdata; file->fs->stat(file->fs, file->device, (int)file, &sdata); unsigned int size = sdata.st_size; if (*cursor != (int)size) { *cursor = *cursor % size; } } _unlock_file(file); return ret; }
int ftruncate(int fd, size_t size) { if (!_valid_file(fd)) return -1; FSFile *file = (FSFile*) fd; int ret = 0; _lock_file(file); if (file->fs->ftruncate) { ret = file->fs->ftruncate(file->fs, file->device, file->internalfd, fd); } _unlock_file(file); return ret; }
void *mmap(void *addr, size_t length, int prot, int flags, int fd, int offset) { if (!_valid_file(fd)) return NULL; FSFile *file = (FSFile*) fd; void *ret = NULL; _lock_file(file); if (file->fs->mmap) { ret = file->fs->mmap(file->fs, file->device, addr, length, prot, flags, file->internalfd, offset); } _unlock_file(file); return ret; }
char *gets( _In_ char *buf) { int cc; char * buf_start = buf; _lock_file(stdin); for(cc = fgetc(stdin); cc != EOF && cc != '\n'; cc = fgetc(stdin)) if(cc != '\r') *buf++ = (char)cc; *buf = '\0'; _unlock_file(stdin); return buf_start; }
int lseek(int fd, int off, int whence) { if (!_valid_file(fd)) { klogf("lseek: Invalid file %x\n", fd); return -1; } FSFile *file = (FSFile*) fd; int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); int ret = -1, *cursor = ((file->mode & O_PIPE_MODE) && reverse) ? &file->pipe_rcursor : &file->cursor; _lock_file(file); if (file->fs->lseek) { ret = file->fs->lseek(file->fs, file->device, file->internalfd, off, whence); if (ret < 0) { _unlock_file(file); return ret; } *cursor = ret; } else { //adjust internal pointer directly struct stat st = {0,}; file->fs->fstat(file->fs, file->device, file->internalfd, &st); if (whence == SEEK_SET) { *cursor = off; } else if (whence == SEEK_CUR) { *cursor += off; } else if (whence == SEEK_END) { intptr_t newoff = st.st_size - off; if (newoff < 0) newoff = 0; *cursor = newoff; } if (*cursor > st.st_size) { *cursor = st.st_size; } } _unlock_file(file); return ret; }
int _fs_clear_mode(int fd, int mode) { if (!_valid_file(fd)) return -1; FSFile *file = (FSFile*) fd; _lock_file(file); file->mode &= ~mode; if (file->fs->clearmode) { file->fs->clearmode(file->fs, file->device, file->internalfd, mode); } _unlock_file(file); return 0; }
//return 1 if eof, 0 otherwise, or <0, for error int peof(int fd) { FSFile *file = (FSFile*)fd; if (!_valid_file(fd)) return -1; _lock_file(file); //XXX: macroatize me! int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); int *cursor = ((file->mode & O_PIPE_MODE) && reverse) ? &file->pipe_rcursor : &file->cursor; int ret = file->fs->eof ? file->fs->eof(file->fs, file->device, file->internalfd, *cursor) : -1; _unlock_file(file); return ret; }
/////////////////////////////////////////////////////////////////////////////////// //Lock A File /////////////////////////////////////////////////////////////////////////////////// Void FileHandler::LockFile(FilePointer Stream) { if(Stream.fp != NULL) { _lock_file(Stream.fp); return; } else { ///////////////////////////////////////// //Error ///////////////////////////////////////// printf("ERROR: Bad File Pointer"); return; } }
int __cdecl vfwprintf_s(FILE* file, const wchar_t *format, va_list argptr) { int ret; if(!MSVCRT_CHECK_PMT( file != NULL)) { _set_errno(EINVAL); return -1; } _lock_file(file); ret = wstreamout(file, format, argptr); _unlock_file(file); return ret; }
static Integer __cdecl common_ftell(__crt_stdio_stream const stream) throw() { _VALIDATE_RETURN(stream.valid(), EINVAL, -1); Integer return_value = 0; _lock_file(stream.public_stream()); __try { return_value = common_ftell_nolock<Integer>(stream); } __finally { _unlock_file(stream.public_stream()); } return return_value; }
extern "C" wint_t __cdecl fgetwc(FILE* const stream) { _VALIDATE_RETURN(stream != nullptr, EINVAL, WEOF); wint_t return_value = 0; _lock_file(stream); __try { return_value = _fgetwc_nolock(stream); } __finally { _unlock_file(stream); } return return_value; }
int fs_ioctl_handle(int fd, intptr_t req, intptr_t arg) { if (!_valid_file(fd)) { klogf("lseek: Invalid file %x\n", fd); return -1; } FSFile *file = (FSFile*) fd; //int reverse = (!!(file->mode & O_PIPE_MODE)) ^ (!!(file->mode & _O_REVERSE)); int ret = -1; // *cursor = ((file->mode & O_PIPE_MODE) && reverse) ? &file->pipe_rcursor : &file->cursor; _lock_file(file); if (file->fs->ioctl) { ret = file->fs->ioctl(file->fs, file->device, file->internalfd, req, arg); } _unlock_file(file); return ret; }
// Repositions the file pointer of a stream to the specified location, relative // to 'whence', which can be SEEK_SET (the beginning of the file), SEEK_CUR (the // current pointer position), or SEEK_END (the end of the file). The offset may // be negative. Returns 0 on success; returns -1 and sets errno on failure. static int __cdecl common_fseek( __crt_stdio_stream const stream, __int64 const offset, int const whence ) throw() { _VALIDATE_RETURN(stream.valid(), EINVAL, -1); _VALIDATE_RETURN(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END, EINVAL, -1); int return_value = -1; _lock_file(stream.public_stream()); __try { return_value = common_fseek_nolock(stream, offset, whence); } __finally { _unlock_file(stream.public_stream()); } return return_value; }
static errno_t __cdecl common_freopen( FILE** const result, Character const* const file_name, Character const* const mode, __crt_stdio_stream const stream, int const share_flag ) throw() { typedef __acrt_stdio_char_traits<Character> stdio_traits; _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); *result = nullptr; // C11 7.21.5.4/3: "If filename is a null pointer, the freopen function // attempts to change the mode of the stream to that specified by mode, as // if the name of the file currently associated with the stream had been // used. It is implementation-defined which changes of mode are permitted // (if any), and under what circumstances." // // In our implementation, we do not currently support changing the mode // in this way. In the future, we might consider use of ReOpenFile to // implement support for changing the mode. _VALIDATE_RETURN_ERRCODE_NOEXC(file_name != nullptr, EBADF); _VALIDATE_RETURN_ERRCODE(mode != nullptr, EINVAL); _VALIDATE_RETURN_ERRCODE(stream.valid() , EINVAL); // Just as in the common_fsopen function, we do not hard-validate empty // 'file_name' strings in this function: _VALIDATE_RETURN_ERRCODE_NOEXC(*file_name != 0, EINVAL); errno_t return_value = 0; _lock_file(stream.public_stream()); __try { // If the stream is in use, try to close it, ignoring possible errors: if (stream.is_in_use()) _fclose_nolock(stream.public_stream()); stream->_ptr = nullptr; stream->_base = nullptr; stream->_cnt = 0; stream.unset_flags(-1); // We may have called fclose above, which will deallocate the stream. // We still hold the lock on the stream, though, so we can just reset // the allocated flag to retain ownership. stream.set_flags(_IOALLOCATED); *result = stdio_traits::open_file(file_name, mode, share_flag, stream.public_stream()); if (*result == nullptr) { stream.unset_flags(_IOALLOCATED); return_value = errno; } } __finally { _unlock_file(stream.public_stream()); } return return_value; }
int VMPI_ftrylockfile (FILE *stream) { _lock_file(stream); //yep that's cheap ... return 0; }
// ---- C.stdio ---- void VMPI_flockfile (FILE *stream) { _lock_file(stream); }
static void flockfile(FILE* fp) { _lock_file(fp); }