xref: /minix3/minix/commands/loadramdisk/loadramdisk.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /*
2*433d6423SLionel Sambuc loadramdisk.c
3*433d6423SLionel Sambuc 
4*433d6423SLionel Sambuc Copy a device or file specified as argument to /dev/ram
5*433d6423SLionel Sambuc */
6*433d6423SLionel Sambuc 
7*433d6423SLionel Sambuc #include <errno.h>
8*433d6423SLionel Sambuc #include <fcntl.h>
9*433d6423SLionel Sambuc #include <stdio.h>
10*433d6423SLionel Sambuc #include <stdlib.h>
11*433d6423SLionel Sambuc #include <string.h>
12*433d6423SLionel Sambuc #include <unistd.h>
13*433d6423SLionel Sambuc #include <sys/ioctl.h>
14*433d6423SLionel Sambuc 
15*433d6423SLionel Sambuc #define RAM	"/dev/ram"
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc char buf[10240];
18*433d6423SLionel Sambuc 
19*433d6423SLionel Sambuc static unsigned long size_device(int fd);
20*433d6423SLionel Sambuc 
main(int argc,char * argv[])21*433d6423SLionel Sambuc int main(int argc, char *argv[])
22*433d6423SLionel Sambuc {
23*433d6423SLionel Sambuc 	unsigned long off, size;
24*433d6423SLionel Sambuc 	int r, s, fd, ramfd;
25*433d6423SLionel Sambuc 	char *src;
26*433d6423SLionel Sambuc 
27*433d6423SLionel Sambuc 	if (argc != 2)
28*433d6423SLionel Sambuc 	{
29*433d6423SLionel Sambuc 		fprintf(stderr, "Usage: loadramdisk <file>\n");
30*433d6423SLionel Sambuc 		exit(1);
31*433d6423SLionel Sambuc 	}
32*433d6423SLionel Sambuc 	src= argv[1];
33*433d6423SLionel Sambuc 	fd= open(src, O_RDONLY);
34*433d6423SLionel Sambuc 	if (fd < 0)
35*433d6423SLionel Sambuc 	{
36*433d6423SLionel Sambuc 		fprintf(stderr, "Unable to open '%s': %s\n",
37*433d6423SLionel Sambuc 			src, strerror(errno));
38*433d6423SLionel Sambuc 		exit(1);
39*433d6423SLionel Sambuc 	}
40*433d6423SLionel Sambuc 
41*433d6423SLionel Sambuc 	/* Get the size of the device */
42*433d6423SLionel Sambuc 	errno= 0;
43*433d6423SLionel Sambuc 	size= size_device(fd);
44*433d6423SLionel Sambuc 	if (errno != 0)
45*433d6423SLionel Sambuc 	{
46*433d6423SLionel Sambuc 		fprintf(stderr, "Lseek(end) failed on '%s': %s\n",
47*433d6423SLionel Sambuc 			src, strerror(errno));
48*433d6423SLionel Sambuc 		exit(1);
49*433d6423SLionel Sambuc 	}
50*433d6423SLionel Sambuc 	if (lseek(fd, 0, SEEK_SET) != 0)
51*433d6423SLionel Sambuc 	{
52*433d6423SLionel Sambuc 		fprintf(stderr, "Lseek(0) failed on '%s': %s\n",
53*433d6423SLionel Sambuc 			src, strerror(errno));
54*433d6423SLionel Sambuc 		exit(1);
55*433d6423SLionel Sambuc 	}
56*433d6423SLionel Sambuc 
57*433d6423SLionel Sambuc 	ramfd= open(RAM, O_RDWR);
58*433d6423SLionel Sambuc 	if (ramfd < 0)
59*433d6423SLionel Sambuc 	{
60*433d6423SLionel Sambuc 		fprintf(stderr, "Unable to open '%s': %s\n",
61*433d6423SLionel Sambuc 			RAM, strerror(errno));
62*433d6423SLionel Sambuc 		exit(1);
63*433d6423SLionel Sambuc 	}
64*433d6423SLionel Sambuc 	r= ioctl(ramfd, MIOCRAMSIZE, &size);
65*433d6423SLionel Sambuc 	if (r != 0)
66*433d6423SLionel Sambuc 	{
67*433d6423SLionel Sambuc 		fprintf(stderr, "MIOCRAMSIZE %lu failed on '%s': %s\n",
68*433d6423SLionel Sambuc 			size, RAM, strerror(errno));
69*433d6423SLionel Sambuc 		exit(1);
70*433d6423SLionel Sambuc 	}
71*433d6423SLionel Sambuc 
72*433d6423SLionel Sambuc 	off= 0;
73*433d6423SLionel Sambuc 	while (off < size)
74*433d6423SLionel Sambuc 	{
75*433d6423SLionel Sambuc 		r= read(fd, buf, sizeof(buf));
76*433d6423SLionel Sambuc 		if (r <= 0)
77*433d6423SLionel Sambuc 		{
78*433d6423SLionel Sambuc 			fprintf(stderr, "error reading '%s': %s\n",
79*433d6423SLionel Sambuc 				src, r == 0 ? "unexpected EOF" :
80*433d6423SLionel Sambuc 				strerror(errno));
81*433d6423SLionel Sambuc 			exit(1);
82*433d6423SLionel Sambuc 		}
83*433d6423SLionel Sambuc 		s= write(ramfd, buf, r);
84*433d6423SLionel Sambuc 		if (s != r)
85*433d6423SLionel Sambuc 		{
86*433d6423SLionel Sambuc 			fprintf(stderr, "error writing to '%s': %s\n", RAM,
87*433d6423SLionel Sambuc 				s >= 0 ? "short write" : strerror(errno));
88*433d6423SLionel Sambuc 			exit(1);
89*433d6423SLionel Sambuc 		}
90*433d6423SLionel Sambuc 		off += r;
91*433d6423SLionel Sambuc 	}
92*433d6423SLionel Sambuc 	exit(0);
93*433d6423SLionel Sambuc }
94*433d6423SLionel Sambuc 
size_device(int fd)95*433d6423SLionel Sambuc static unsigned long size_device(int fd)
96*433d6423SLionel Sambuc {
97*433d6423SLionel Sambuc 	char b;
98*433d6423SLionel Sambuc 	int r;
99*433d6423SLionel Sambuc 	unsigned long low, mid, high;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	/* Try to find the size of a device using binary search */
102*433d6423SLionel Sambuc 	low= 0;
103*433d6423SLionel Sambuc 	high= -1;
104*433d6423SLionel Sambuc 
105*433d6423SLionel Sambuc 	while (mid= low+(high-low)/2, mid > low)
106*433d6423SLionel Sambuc 	{
107*433d6423SLionel Sambuc 		if (lseek(fd, mid, SEEK_SET) != mid)
108*433d6423SLionel Sambuc 		{
109*433d6423SLionel Sambuc 			fprintf(stderr, "lseek to %lu failed: %s\n",
110*433d6423SLionel Sambuc 				mid, strerror(errno));
111*433d6423SLionel Sambuc 			exit(1);
112*433d6423SLionel Sambuc 		}
113*433d6423SLionel Sambuc 		r= read(fd, &b, 1);
114*433d6423SLionel Sambuc 		if (r < 0)
115*433d6423SLionel Sambuc 		{
116*433d6423SLionel Sambuc 			fprintf(stderr, "read failed at position %lu: %s\n",
117*433d6423SLionel Sambuc 				mid, strerror(errno));
118*433d6423SLionel Sambuc 			exit(1);
119*433d6423SLionel Sambuc 		}
120*433d6423SLionel Sambuc 		if (r > 0)
121*433d6423SLionel Sambuc 			low= mid;
122*433d6423SLionel Sambuc 		else
123*433d6423SLionel Sambuc 			high= mid;
124*433d6423SLionel Sambuc 	}
125*433d6423SLionel Sambuc 	return high;
126*433d6423SLionel Sambuc }
127