int putc(int c, FILE* stream) { g_atomic_lock(&stream->lock); int res = __fputc_unlocked(c, stream); stream->lock = 0; return res; }
int fputc(int c, FILE* stream) { AtomicLock(&stream->lock); int result = __fputc_unlocked(c, stream); stream->lock = 0; return result; }
size_t __fwrite_unlocked(const void* ptr, size_t size, size_t nmemb, FILE* stream) { // check for illegal arguments if (size == 0 || nmemb == 0) { return 0; } // check if stream is writable if ((stream->flags & FILE_FLAG_MODE_WRITE) == 0) { errno = EBADF; stream->flags |= G_FILE_FLAG_ERROR; return EOF; } // if necessary, initialize stream buffer if ((stream->flags & G_FILE_FLAG_BUFFER_SET) == 0) { if (__setdefbuf_unlocked(stream) == EOF) { return EOF; } } // unbuffered files perform direct write if (stream->buffer_mode == _IONBF) { // if the last access was a read, flush it if (stream->flags & G_FILE_FLAG_BUFFER_DIRECTION_READ) { if (__fflush_read_unlocked(stream) == EOF) { return EOF; } } // if stream has no write implementation, return with error if (stream->impl_write == NULL) { errno = EBADF; stream->flags |= G_FILE_FLAG_ERROR; return EOF; } // set stream direction stream->flags |= G_FILE_FLAG_BUFFER_DIRECTION_WRITE; // remove end-of-file stream->flags &= ~G_FILE_FLAG_EOF; // perform writing size_t total = size * nmemb; size_t done = 0; while (done < total) { // call write implementation ssize_t written = stream->impl_write(&(((uint8_t*) ptr)[done]), total, stream); if (written == 0) { stream->flags |= G_FILE_FLAG_EOF; return EOF; } else if (written == -1) { stream->flags |= G_FILE_FLAG_ERROR; return EOF; } done += written; } return done / size; } // for buffered streams, put char-by-char uint8_t* buffer = (uint8_t*) ptr; for (size_t e = 0; e < nmemb; e++) { size_t off = e * size; for (size_t b = 0; b < size; b++) { if (__fputc_unlocked(buffer[off + b], stream) == EOF) { return e; } } } return nmemb; }