69 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| #include <unistd.h>
 | |
| #include <stdbool.h>
 | |
| #include <errno.h>
 | |
| #include <linux/kernel.h>
 | |
| #include <internal/lib.h>
 | |
| 
 | |
| unsigned int page_size;
 | |
| 
 | |
| static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 | |
| {
 | |
| 	void *buf_start = buf;
 | |
| 	size_t left = n;
 | |
| 
 | |
| 	while (left) {
 | |
| 		/* buf must be treated as const if !is_read. */
 | |
| 		ssize_t ret = is_read ? read(fd, buf, left) :
 | |
| 					write(fd, buf, left);
 | |
| 
 | |
| 		if (ret < 0 && errno == EINTR)
 | |
| 			continue;
 | |
| 		if (ret <= 0)
 | |
| 			return ret;
 | |
| 
 | |
| 		left -= ret;
 | |
| 		buf  += ret;
 | |
| 	}
 | |
| 
 | |
| 	BUG_ON((size_t)(buf - buf_start) != n);
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Read exactly 'n' bytes or return an error.
 | |
|  */
 | |
| ssize_t readn(int fd, void *buf, size_t n)
 | |
| {
 | |
| 	return ion(true, fd, buf, n);
 | |
| }
 | |
| 
 | |
| ssize_t preadn(int fd, void *buf, size_t n, off_t offs)
 | |
| {
 | |
| 	size_t left = n;
 | |
| 
 | |
| 	while (left) {
 | |
| 		ssize_t ret = pread(fd, buf, left, offs);
 | |
| 
 | |
| 		if (ret < 0 && errno == EINTR)
 | |
| 			continue;
 | |
| 		if (ret <= 0)
 | |
| 			return ret;
 | |
| 
 | |
| 		left -= ret;
 | |
| 		buf  += ret;
 | |
| 		offs += ret;
 | |
| 	}
 | |
| 
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Write exactly 'n' bytes or return an error.
 | |
|  */
 | |
| ssize_t writen(int fd, const void *buf, size_t n)
 | |
| {
 | |
| 	/* ion does not modify buf. */
 | |
| 	return ion(false, fd, (void *)buf, n);
 | |
| }
 |