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