merge of '178eac00dc5aa8338d42e8e203633bec7817bbf6'
[vuplus_openembedded] / packages / klibc / files / losetup.patch
1 Index: klibc-1.5/usr/utils/losetup.c
2 ===================================================================
3 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
4 +++ klibc-1.5/usr/utils/losetup.c       2008-03-07 23:13:38.635692852 +0100
5 @@ -0,0 +1,485 @@
6 +/* Originally from Ted's losetup.c */
7 +
8 +#define LOOPMAJOR      7
9 +
10 +/*
11 + * losetup.c - setup and control loop devices
12 + */
13 +
14 +#include <stdio.h>
15 +#include <string.h>
16 +#include <ctype.h>
17 +#include <fcntl.h>
18 +#include <errno.h>
19 +#include <stdlib.h>
20 +#include <unistd.h>
21 +#include <sys/ioctl.h>
22 +#include <sys/stat.h>
23 +#include <sys/mman.h>
24 +#include <sys/sysmacros.h>
25 +#include <string.h>
26 +
27 +#include "loop.h"
28 +
29 +extern int verbose;
30 +extern char *progname;
31 +extern char *xstrdup (const char *s);  /* not: #include "sundries.h" */
32 +extern void error (const char *fmt, ...);      /* idem */
33 +
34 +/* caller guarantees n > 0 */
35 +void
36 +xstrncpy(char *dest, const char *src, size_t n) {
37 +        strncpy(dest, src, n-1);
38 +        dest[n-1] = 0;
39 +}
40 +
41 +
42 +static int
43 +loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
44 +{
45 +        memset(info, 0, sizeof(*info));
46 +        info->lo_number = info64->lo_number;
47 +        info->lo_device = info64->lo_device;
48 +        info->lo_inode = info64->lo_inode;
49 +        info->lo_rdevice = info64->lo_rdevice;
50 +        info->lo_offset = info64->lo_offset;
51 +        info->lo_encrypt_type = info64->lo_encrypt_type;
52 +        info->lo_encrypt_key_size = info64->lo_encrypt_key_size;
53 +        info->lo_flags = info64->lo_flags;
54 +        info->lo_init[0] = info64->lo_init[0];
55 +        info->lo_init[1] = info64->lo_init[1];
56 +        if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
57 +                memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
58 +        else
59 +                memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
60 +        memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
61 +
62 +        /* error in case values were truncated */
63 +        if (info->lo_device != info64->lo_device ||
64 +            info->lo_rdevice != info64->lo_rdevice ||
65 +            info->lo_inode != info64->lo_inode ||
66 +            info->lo_offset != info64->lo_offset)
67 +                return -EOVERFLOW;
68 +
69 +        return 0;
70 +}
71 +
72 +
73 +static int
74 +show_loop(char *device) {
75 +       struct loop_info loopinfo;
76 +       struct loop_info64 loopinfo64;
77 +       int fd, errsv;
78 +
79 +       if ((fd = open(device, O_RDONLY)) < 0) {
80 +               int errsv = errno;
81 +               fprintf(stderr, "loop: can't open device %s: %s\n",
82 +                       device, strerror (errsv));
83 +               return 2;
84 +       }
85 +
86 +       if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) {
87 +
88 +               loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*';
89 +               loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0;
90 +               loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0;
91 +
92 +               printf("%s: [%04llx]:%llu (%s)",
93 +                      device, loopinfo64.lo_device, loopinfo64.lo_inode,
94 +                      loopinfo64.lo_file_name);
95 +
96 +               if (loopinfo64.lo_offset)
97 +                       printf(", offset %lld", loopinfo64.lo_offset);
98 +
99 +               if (loopinfo64.lo_sizelimit)
100 +                       printf(", sizelimit %lld", loopinfo64.lo_sizelimit);
101 +
102 +               if (loopinfo64.lo_encrypt_type ||
103 +                   loopinfo64.lo_crypt_name[0]) {
104 +                       char *e = loopinfo64.lo_crypt_name;
105 +
106 +                       if (*e == 0 && loopinfo64.lo_encrypt_type == 1)
107 +                               e = "XOR";
108 +                       printf(", encryption %s (type %d)",
109 +                              e, loopinfo64.lo_encrypt_type);
110 +               }
111 +               printf("\n");
112 +               close (fd);
113 +               return 0;
114 +       }
115 +
116 +       if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == 0) {
117 +               printf ("%s: [%04x]:%ld (%s)",
118 +                       device, loopinfo.lo_device, loopinfo.lo_inode,
119 +                       loopinfo.lo_name);
120 +
121 +               if (loopinfo.lo_offset)
122 +                       printf(", offset %d", loopinfo.lo_offset);
123 +
124 +               if (loopinfo.lo_encrypt_type)
125 +                       printf(", encryption type %d\n",
126 +                              loopinfo.lo_encrypt_type);
127 +
128 +               printf("\n");
129 +               close (fd);
130 +               return 0;
131 +       }
132 +
133 +       errsv = errno;
134 +       fprintf(stderr, "loop: can't get info on device %s: %s\n",
135 +               device, strerror (errsv));
136 +       close (fd);
137 +       return 1;
138 +}
139 +
140 +int
141 +is_loop_device (const char *device) {
142 +       struct stat statbuf;
143 +
144 +       return (stat(device, &statbuf) == 0 &&
145 +               S_ISBLK(statbuf.st_mode) &&
146 +               major(statbuf.st_rdev) == LOOPMAJOR);
147 +}
148 +
149 +#define SIZE(a) (sizeof(a)/sizeof(a[0]))
150 +
151 +char *
152 +find_unused_loop_device (void) {
153 +       /* Just creating a device, say in /tmp, is probably a bad idea -
154 +          people might have problems with backup or so.
155 +          So, we just try /dev/loop[0-7]. */
156 +       char dev[20];
157 +       char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
158 +       int i, j, fd, somedev = 0, someloop = 0, permission = 0;
159 +       struct stat statbuf;
160 +       struct loop_info loopinfo;
161 +
162 +       for (j = 0; j < SIZE(loop_formats); j++) {
163 +           for(i = 0; i < 256; i++) {
164 +               sprintf(dev, loop_formats[j], i);
165 +               if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
166 +                       somedev++;
167 +                       fd = open (dev, O_RDONLY);
168 +                       if (fd >= 0) {
169 +                               if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
170 +                                       someloop++;             /* in use */
171 +                               else if (errno == ENXIO) {
172 +                                       close (fd);
173 +                                       return xstrdup(dev);/* probably free */
174 +                               }
175 +                               close (fd);
176 +                       } else if (errno == EACCES)
177 +                               permission++;
178 +
179 +                       continue;/* continue trying as long as devices exist */
180 +               }
181 +               break;
182 +           }
183 +       }
184 +
185 +       if (!somedev)
186 +               error("%s: could not find any device /dev/loop#", progname);
187 +       else if (!someloop && permission)
188 +               error("%s: no permission to look at /dev/loop#", progname);
189 +       else if (!someloop)
190 +               error(
191 +                   "%s: Could not find any loop device. Maybe this kernel "
192 +                   "does not know\n"
193 +                   "       about the loop device? (If so, recompile or "
194 +                   "`modprobe loop'.)", progname);
195 +       else
196 +               error("%s: could not find any free loop device", progname);
197 +       return 0;
198 +}
199 +
200 +/*
201 + * A function to read the passphrase either from the terminal or from
202 + * an open file descriptor.
203 + */
204 +static char *
205 +xgetpass(int pfd, const char *prompt) {
206 +       char *pass;
207 +       int buflen, i;
208 +
209 +       pass = NULL;
210 +       buflen = 0;
211 +       for (i=0; ; i++) {
212 +               if (i >= buflen-1) {
213 +                               /* we're running out of space in the buffer.
214 +                                * Make it bigger: */
215 +                       char *tmppass = pass;
216 +                       buflen += 128;
217 +                       pass = realloc(tmppass, buflen);
218 +                       if (pass == NULL) {
219 +                               /* realloc failed. Stop reading. */
220 +                               error("Out of memory while reading passphrase");
221 +                               pass = tmppass; /* the old buffer hasn't changed */
222 +                               break;
223 +                       }
224 +               }
225 +               if (read(pfd, pass+i, 1) != 1 ||
226 +                   pass[i] == '\n' || pass[i] == 0)
227 +                       break;
228 +       }
229 +
230 +       if (pass == NULL)
231 +               return "";
232 +
233 +       pass[i] = 0;
234 +       return pass;
235 +}
236 +
237 +static int
238 +digits_only(const char *s) {
239 +       while (*s)
240 +               if (!isdigit(*s++))
241 +                       return 0;
242 +       return 1;
243 +}
244 +
245 +int
246 +set_loop(const char *device, const char *file, unsigned long long offset,
247 +        const char *encryption, int pfd, int *loopro) {
248 +       struct loop_info64 loopinfo64;
249 +       int fd, ffd, mode, i;
250 +       char *pass;
251 +
252 +       mode = (*loopro ? O_RDONLY : O_RDWR);
253 +       if ((ffd = open(file, mode)) < 0) {
254 +               if (!*loopro && errno == EROFS)
255 +                       ffd = open(file, mode = O_RDONLY);
256 +               if (ffd < 0) {
257 +                       perror(file);
258 +                       return 1;
259 +               }
260 +       }
261 +       if ((fd = open(device, mode)) < 0) {
262 +               perror (device);
263 +               return 1;
264 +       }
265 +       *loopro = (mode == O_RDONLY);
266 +
267 +       memset(&loopinfo64, 0, sizeof(loopinfo64));
268 +
269 +       xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE);
270 +
271 +       if (encryption && *encryption) {
272 +               if (digits_only(encryption)) {
273 +                       loopinfo64.lo_encrypt_type = atoi(encryption);
274 +               } else {
275 +                       loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
276 +                       snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE,
277 +                                "%s", encryption);
278 +               }
279 +       }
280 +
281 +       loopinfo64.lo_offset = offset;
282 +
283 +
284 +       switch (loopinfo64.lo_encrypt_type) {
285 +       case LO_CRYPT_NONE:
286 +               loopinfo64.lo_encrypt_key_size = 0;
287 +               break;
288 +       case LO_CRYPT_XOR:
289 +               pass = xgetpass(pfd, "Password: ");
290 +               goto gotpass;
291 +       default:
292 +               pass = xgetpass(pfd, "Password: ");
293 +       gotpass:
294 +               memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE);
295 +               xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
296 +               memset(pass, 0, strlen(pass));
297 +               loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
298 +       }
299 +
300 +       if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
301 +               perror("ioctl: LOOP_SET_FD");
302 +               return 1;
303 +       }
304 +       close (ffd);
305 +
306 +       i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64);
307 +       if (i) {
308 +               struct loop_info loopinfo;
309 +               int errsv = errno;
310 +
311 +               i = loop_info64_to_old(&loopinfo64, &loopinfo);
312 +               if (i) {
313 +                       errno = errsv;
314 +                       perror("ioctl: LOOP_SET_STATUS64");
315 +               } else {
316 +                       i = ioctl(fd, LOOP_SET_STATUS, &loopinfo);
317 +                       if (i)
318 +                               perror("ioctl: LOOP_SET_STATUS");
319 +               }
320 +               memset(&loopinfo, 0, sizeof(loopinfo));
321 +       }
322 +       memset(&loopinfo64, 0, sizeof(loopinfo64));
323 +
324 +       if (i) {
325 +               ioctl (fd, LOOP_CLR_FD, 0);
326 +               close (fd);
327 +               return 1;
328 +       }
329 +       close (fd);
330 +
331 +       if (verbose > 1)
332 +               printf("set_loop(%s,%s,%llu): success\n",
333 +                      device, file, offset);
334 +       return 0;
335 +}
336 +
337 +int
338 +del_loop (const char *device) {
339 +       int fd;
340 +
341 +       if ((fd = open (device, O_RDONLY)) < 0) {
342 +               int errsv = errno;
343 +               fprintf(stderr, "loop: can't delete device %s: %s\n",
344 +                       device, strerror (errsv));
345 +               return 1;
346 +       }
347 +       if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
348 +               perror ("ioctl: LOOP_CLR_FD");
349 +               return 1;
350 +       }
351 +       close (fd);
352 +       if (verbose > 1)
353 +               printf("del_loop(%s): success\n", device);
354 +       return 0;
355 +}
356 +
357 +
358 +#include <getopt.h>
359 +#include <stdarg.h>
360 +
361 +int verbose = 0;
362 +char *progname;
363 +
364 +static void
365 +usage(void) {
366 +       fprintf(stderr, "usage:\n\
367 +  %s loop_device                                       # give info\n\
368 +  %s -d loop_device                                    # delete\n\
369 +  %s -f                                                # find unused\n\
370 +  %s [-e encryption] [-o offset] {-f|loop_device} file # setup\n",
371 +               progname, progname, progname, progname);
372 +       exit(1);
373 +}
374 +
375 +char *
376 +xstrdup (const char *s) {
377 +       char *t;
378 +
379 +       if (s == NULL)
380 +               return NULL;
381 +
382 +       t = strdup (s);
383 +
384 +       if (t == NULL) {
385 +               fprintf(stderr, "not enough memory");
386 +               exit(1);
387 +       }
388 +
389 +       return t;
390 +}
391 +
392 +void
393 +error (const char *fmt, ...) {
394 +       va_list args;
395 +
396 +       va_start (args, fmt);
397 +       vfprintf (stderr, fmt, args);
398 +       va_end (args);
399 +       fprintf (stderr, "\n");
400 +}
401 +
402 +int
403 +main(int argc, char **argv) {
404 +       char *p, *offset, *encryption, *passfd, *device, *file;
405 +       int delete, find, c;
406 +       int res = 0;
407 +       int ro = 0;
408 +       int pfd = -1;
409 +       unsigned long long off;
410 +
411 +
412 +       delete = find = 0;
413 +       off = 0;
414 +       offset = encryption = passfd = NULL;
415 +
416 +       progname = argv[0];
417 +       if ((p = strrchr(progname, '/')) != NULL)
418 +               progname = p+1;
419 +
420 +       while ((c = getopt(argc, argv, "de:E:fo:p:v")) != -1) {
421 +               switch (c) {
422 +               case 'd':
423 +                       delete = 1;
424 +                       break;
425 +               case 'E':
426 +               case 'e':
427 +                       encryption = optarg;
428 +                       break;
429 +               case 'f':
430 +                       find = 1;
431 +                       break;
432 +               case 'o':
433 +                       offset = optarg;
434 +                       break;
435 +               case 'p':
436 +                       passfd = optarg;
437 +                       break;
438 +               case 'v':
439 +                       verbose = 1;
440 +                       break;
441 +               default:
442 +                       usage();
443 +               }
444 +       }
445 +
446 +       if (argc == 1) {
447 +               usage();
448 +       } else if (delete) {
449 +               if (argc != optind+1 || encryption || offset || find)
450 +                       usage();
451 +       } else if (find) {
452 +               if (argc < optind || argc > optind+1)
453 +                       usage();
454 +       } else {
455 +               if (argc < optind+1 || argc > optind+2)
456 +                       usage();
457 +       }
458 +
459 +       if (find) {
460 +               device = find_unused_loop_device();
461 +               if (device == NULL)
462 +                       return -1;
463 +               if (verbose)
464 +                       printf("Loop device is %s\n", device);
465 +               if (argc == optind) {
466 +                       printf("%s\n", device);
467 +                       return 0;
468 +               }
469 +               file = argv[optind];
470 +       } else {
471 +               device = argv[optind];
472 +               if (argc == optind+1)
473 +                       file = NULL;
474 +               else
475 +                       file = argv[optind+1];
476 +       }
477 +
478 +       if (delete)
479 +               res = del_loop(device);
480 +       else if (file == NULL)
481 +               res = show_loop(device);
482 +       else {
483 +               if (offset && sscanf(offset, "%llu", &off) != 1)
484 +                       usage();
485 +               if (passfd && sscanf(passfd, "%d", &pfd) != 1)
486 +                       usage();
487 +               res = set_loop(device, file, off, encryption, pfd, &ro);
488 +       }
489 +       return res;
490 +}
491 Index: klibc-1.5/usr/utils/loop.h
492 ===================================================================
493 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
494 +++ klibc-1.5/usr/utils/loop.h  2008-03-07 23:01:49.336694297 +0100
495 @@ -0,0 +1,51 @@
496 +#define LO_CRYPT_NONE  0
497 +#define LO_CRYPT_XOR   1
498 +#define LO_CRYPT_DES   2
499 +#define LO_CRYPT_CRYPTOAPI 18
500 +
501 +#define LOOP_SET_FD            0x4C00
502 +#define LOOP_CLR_FD            0x4C01
503 +#define LOOP_SET_STATUS                0x4C02
504 +#define LOOP_GET_STATUS                0x4C03
505 +#define LOOP_SET_STATUS64      0x4C04
506 +#define LOOP_GET_STATUS64      0x4C05
507 +
508 +#define LO_NAME_SIZE   64
509 +#define LO_KEY_SIZE    32
510 +
511 +#include "my_dev_t.h"
512 +
513 +struct loop_info {
514 +       int             lo_number;
515 +       my_dev_t        lo_device;
516 +       unsigned long   lo_inode;
517 +       my_dev_t        lo_rdevice;
518 +       int             lo_offset;
519 +       int             lo_encrypt_type;
520 +       int             lo_encrypt_key_size;
521 +       int             lo_flags;
522 +       char            lo_name[LO_NAME_SIZE];
523 +       unsigned char   lo_encrypt_key[LO_KEY_SIZE];
524 +       unsigned long   lo_init[2];
525 +       char            reserved[4];
526 +};
527 +
528 +/*
529 + * Where to get __u8, __u32, __u64? Let us use unsigned char/int/long long
530 + * and get punished when someone comes with 128-bit long longs.
531 + */
532 +struct loop_info64 {
533 +       unsigned long long      lo_device;
534 +       unsigned long long      lo_inode;
535 +       unsigned long long      lo_rdevice;
536 +       unsigned long long      lo_offset;
537 +       unsigned long long      lo_sizelimit; /* bytes, 0 == max available */
538 +       unsigned int            lo_number;
539 +       unsigned int            lo_encrypt_type;
540 +       unsigned int            lo_encrypt_key_size;
541 +       unsigned int            lo_flags;
542 +       unsigned char           lo_file_name[LO_NAME_SIZE];
543 +       unsigned char           lo_crypt_name[LO_NAME_SIZE];
544 +       unsigned char           lo_encrypt_key[LO_KEY_SIZE];
545 +       unsigned long long      lo_init[2];
546 +};
547 Index: klibc-1.5/usr/utils/my_dev_t.h
548 ===================================================================
549 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
550 +++ klibc-1.5/usr/utils/my_dev_t.h      2008-03-07 23:03:45.148693283 +0100
551 @@ -0,0 +1,20 @@
552 +/* silliness to get dev_t defined as the kernel defines it */
553 +/* glibc uses a different dev_t */
554 +
555 +#include <linux/posix_types.h>
556 +#include <linux/version.h>
557 +
558 +#ifndef KERNEL_VERSION
559 +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
560 +#endif
561 +
562 +#if LINUX_VERSION_CODE < KERNEL_VERSION(1,3,78)
563 +/* for i386 - alpha uses unsigned int */
564 +#define my_dev_t unsigned short
565 +#else
566 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)
567 +#define my_dev_t __kernel_dev_t
568 +#else
569 +#define my_dev_t __kernel_old_dev_t
570 +#endif
571 +#endif