summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rbutil/ipodpatcher/Makefile4
-rw-r--r--rbutil/ipodpatcher/ipodio-posix.c63
-rw-r--r--rbutil/ipodpatcher/ipodio-win32-scsi.c118
-rw-r--r--rbutil/ipodpatcher/ipodio-win32.c4
-rw-r--r--rbutil/ipodpatcher/ipodio.h5
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.c80
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.h2
-rw-r--r--rbutil/ipodpatcher/main.c50
8 files changed, 319 insertions, 7 deletions
diff --git a/rbutil/ipodpatcher/Makefile b/rbutil/ipodpatcher/Makefile
index 263d64ed01..9c32587fa1 100644
--- a/rbutil/ipodpatcher/Makefile
+++ b/rbutil/ipodpatcher/Makefile
@@ -36,8 +36,8 @@ ipodpatcher: $(SRC) ipodio-posix.c $(BOOTSRC)
36 gcc $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC) 36 gcc $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC)
37 strip ipodpatcher 37 strip ipodpatcher
38 38
39ipodpatcher.exe: $(SRC) ipodio-win32.c ipodpatcher-rc.o $(BOOTSRC) 39ipodpatcher.exe: $(SRC) ipodio-win32.c ipodio-win32-scsi.c ipodpatcher-rc.o $(BOOTSRC)
40 $(CC) $(CFLAGS) -o ipodpatcher.exe $(SRC) ipodio-win32.c ipodpatcher-rc.o $(BOOTSRC) 40 $(CC) $(CFLAGS) -o ipodpatcher.exe $(SRC) ipodio-win32.c ipodio-win32-scsi.c ipodpatcher-rc.o $(BOOTSRC)
41 $(CROSS)strip ipodpatcher.exe 41 $(CROSS)strip ipodpatcher.exe
42 42
43ipodpatcher-rc.o: ipodpatcher.rc ipodpatcher.manifest 43ipodpatcher-rc.o: ipodpatcher.rc ipodpatcher.manifest
diff --git a/rbutil/ipodpatcher/ipodio-posix.c b/rbutil/ipodpatcher/ipodio-posix.c
index 6dfb09ed33..be048fc986 100644
--- a/rbutil/ipodpatcher/ipodio-posix.c
+++ b/rbutil/ipodpatcher/ipodio-posix.c
@@ -34,6 +34,9 @@
34#if defined(linux) || defined (__linux) 34#if defined(linux) || defined (__linux)
35#include <sys/mount.h> 35#include <sys/mount.h>
36#include <linux/hdreg.h> 36#include <linux/hdreg.h>
37#include <scsi/scsi_ioctl.h>
38#include <scsi/sg.h>
39
37#define IPOD_SECTORSIZE_IOCTL BLKSSZGET 40#define IPOD_SECTORSIZE_IOCTL BLKSSZGET
38 41
39static void get_geometry(struct ipod_t* ipod) 42static void get_geometry(struct ipod_t* ipod)
@@ -50,6 +53,51 @@ static void get_geometry(struct ipod_t* ipod)
50 } 53 }
51} 54}
52 55
56/* Linux SCSI Inquiry code based on the documentation and example code from
57 http://www.ibm.com/developerworks/linux/library/l-scsi-api/index.html
58*/
59
60int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
61 unsigned char* buf, int bufsize)
62{
63 unsigned char cdb[6];
64 struct sg_io_hdr hdr;
65 unsigned char sense_buffer[255];
66
67 memset(&hdr, 0, sizeof(hdr));
68
69 hdr.interface_id = 'S'; /* this is the only choice we have! */
70 hdr.flags = SG_FLAG_LUN_INHIBIT; /* this would put the LUN to 2nd byte of cdb*/
71
72 /* Set xfer data */
73 hdr.dxferp = buf;
74 hdr.dxfer_len = bufsize;
75
76 /* Set sense data */
77 hdr.sbp = sense_buffer;
78 hdr.mx_sb_len = sizeof(sense_buffer);
79
80 /* Set the cdb format */
81 cdb[0] = 0x12;
82 cdb[1] = 1; /* Enable Vital Product Data (EVPD) */
83 cdb[2] = page_code & 0xff;
84 cdb[3] = 0;
85 cdb[4] = 0xff;
86 cdb[5] = 0; /* For control filed, just use 0 */
87
88 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
89 hdr.cmdp = cdb;
90 hdr.cmd_len = 6;
91
92 int ret = ioctl(ipod->dh, SG_IO, &hdr);
93
94 if (ret < 0) {
95 return -1;
96 } else {
97 return 0;
98 }
99}
100
53#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ 101#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
54 || defined(__bsdi__) || defined(__DragonFly__) 102 || defined(__bsdi__) || defined(__DragonFly__)
55#include <sys/disk.h> 103#include <sys/disk.h>
@@ -63,6 +111,13 @@ static void get_geometry(struct ipod_t* ipod)
63 ipod->sectors_per_track = 63; 111 ipod->sectors_per_track = 63;
64} 112}
65 113
114int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
115 unsigned char* buf, int bufsize)
116{
117 /* TODO: Implement for BSD */
118 return -1;
119}
120
66#elif defined(__APPLE__) && defined(__MACH__) 121#elif defined(__APPLE__) && defined(__MACH__)
67#include <sys/disk.h> 122#include <sys/disk.h>
68#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE 123#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
@@ -75,6 +130,13 @@ static void get_geometry(struct ipod_t* ipod)
75 ipod->sectors_per_track = 63; 130 ipod->sectors_per_track = 63;
76} 131}
77 132
133int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
134 unsigned char* buf, int bufsize)
135{
136 /* TODO: Implement for OS X */
137 return -1;
138}
139
78#else 140#else
79 #error No sector-size detection implemented for this platform 141 #error No sector-size detection implemented for this platform
80#endif 142#endif
@@ -180,3 +242,4 @@ ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
180{ 242{
181 return write(ipod->dh, buf, nbytes); 243 return write(ipod->dh, buf, nbytes);
182} 244}
245
diff --git a/rbutil/ipodpatcher/ipodio-win32-scsi.c b/rbutil/ipodpatcher/ipodio-win32-scsi.c
new file mode 100644
index 0000000000..5843ce5d2f
--- /dev/null
+++ b/rbutil/ipodpatcher/ipodio-win32-scsi.c
@@ -0,0 +1,118 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: ipodio-win32.c 17847 2008-06-28 18:10:04Z bagder $
9 *
10 * Copyright (C) 2009 Dave Chapman
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 *
21 * Based on the getCapsUsingSCSIPassThrough() function from "cddrv.cpp":
22 * - http://www.farmanager.com/svn/trunk/unicode_far/cddrv.cpp
23 *
24 * Copyright (c) 1996 Eugene Roshal
25 * Copyright (c) 2000 Far Group
26 * All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. The name of the authors may not be used to endorse or promote products
37 * derived from this software without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
40 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
43 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 *
50 ****************************************************************************/
51
52#include <windows.h>
53#include <stddef.h>
54#include <stdio.h>
55#include <ddk/ntddscsi.h>
56
57#include "ipodio.h"
58
59typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
60 SCSI_PASS_THROUGH Spt;
61 ULONG Filler; /* realign buffers to double word boundary */
62 UCHAR SenseBuf[32];
63 UCHAR DataBuf[512];
64} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
65
66int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
67 unsigned char* buf, int bufsize)
68{
69 SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
70 ULONG length;
71 DWORD returned;
72 BOOL status;
73
74 if (bufsize > 255) {
75 fprintf(stderr,"[ERR] Invalid bufsize in ipod_scsi_inquiry\n");
76 return -1;
77 }
78
79 memset(&sptwb, 0, sizeof(sptwb));
80
81 sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH);
82 sptwb.Spt.PathId = 0;
83 sptwb.Spt.TargetId = 1;
84 sptwb.Spt.Lun = 0;
85 sptwb.Spt.CdbLength = 6;
86 sptwb.Spt.SenseInfoLength = 32; /* sbuf size */;
87 sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;
88 sptwb.Spt.DataTransferLength = bufsize;
89 sptwb.Spt.TimeOutValue = 2; /* 2 seconds */
90 sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);
91 sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);
92 length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) +
93 sptwb.Spt.DataTransferLength;
94
95 /* Set cdb info */
96 sptwb.Spt.Cdb[0] = 0x12; /* SCSI Inquiry */
97 sptwb.Spt.Cdb[1] = 1;
98 sptwb.Spt.Cdb[2] = page_code;
99 sptwb.Spt.Cdb[3] = 0;
100 sptwb.Spt.Cdb[4] = bufsize;
101 sptwb.Spt.Cdb[5] = 0;
102
103 status = DeviceIoControl(ipod->dh,
104 IOCTL_SCSI_PASS_THROUGH,
105 &sptwb,
106 sizeof(SCSI_PASS_THROUGH),
107 &sptwb,
108 length,
109 &returned,
110 FALSE);
111
112 if (status) {
113 memcpy(buf, sptwb.DataBuf, returned);
114 return 0;
115 } else {
116 return -1;
117 }
118}
diff --git a/rbutil/ipodpatcher/ipodio-win32.c b/rbutil/ipodpatcher/ipodio-win32.c
index ceec4a3d6c..5125c070f8 100644
--- a/rbutil/ipodpatcher/ipodio-win32.c
+++ b/rbutil/ipodpatcher/ipodio-win32.c
@@ -32,10 +32,9 @@
32#include <stdlib.h> 32#include <stdlib.h>
33#include <sys/types.h> 33#include <sys/types.h>
34#include <sys/stat.h> 34#include <sys/stat.h>
35#ifdef __WIN32__
36#include <windows.h> 35#include <windows.h>
36#include <stddef.h>
37#include <winioctl.h> 37#include <winioctl.h>
38#endif
39 38
40#include "ipodio.h" 39#include "ipodio.h"
41 40
@@ -201,3 +200,4 @@ ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
201 200
202 return count; 201 return count;
203} 202}
203
diff --git a/rbutil/ipodpatcher/ipodio.h b/rbutil/ipodpatcher/ipodio.h
index dbd3d5e1ff..e0692ca6d9 100644
--- a/rbutil/ipodpatcher/ipodio.h
+++ b/rbutil/ipodpatcher/ipodio.h
@@ -80,6 +80,9 @@ struct ipod_t {
80 char* modelstr; 80 char* modelstr;
81 char* targetname; 81 char* targetname;
82 int macpod; 82 int macpod;
83 char* xmlinfo; /* The XML Device Information (if available) */
84 int xmlinfo_len;
85 int ramsize; /* The amount of RAM in the ipod (if available) */
83#ifdef WITH_BOOTOBJS 86#ifdef WITH_BOOTOBJS
84 unsigned char* bootloader; 87 unsigned char* bootloader;
85 int bootloader_len; 88 int bootloader_len;
@@ -91,6 +94,8 @@ int ipod_open(struct ipod_t* ipod, int silent);
91int ipod_reopen_rw(struct ipod_t* ipod); 94int ipod_reopen_rw(struct ipod_t* ipod);
92int ipod_close(struct ipod_t* ipod); 95int ipod_close(struct ipod_t* ipod);
93int ipod_seek(struct ipod_t* ipod, unsigned long pos); 96int ipod_seek(struct ipod_t* ipod, unsigned long pos);
97int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
98 unsigned char* buf, int bufsize);
94ssize_t ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes); 99ssize_t ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes);
95ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes); 100ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes);
96int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); 101int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize);
diff --git a/rbutil/ipodpatcher/ipodpatcher.c b/rbutil/ipodpatcher/ipodpatcher.c
index dd650506a1..1a5268bb6d 100644
--- a/rbutil/ipodpatcher/ipodpatcher.c
+++ b/rbutil/ipodpatcher/ipodpatcher.c
@@ -1401,6 +1401,86 @@ int write_dos_partition_table(struct ipod_t* ipod)
1401 return 0; 1401 return 0;
1402} 1402}
1403 1403
1404/* Get the XML Device Information, as documented here:
1405
1406 http://www.ipodlinux.org/wiki/Device_Information
1407*/
1408
1409int ipod_get_xmlinfo(struct ipod_t* ipod)
1410{
1411 unsigned char hdr[255];
1412 unsigned char buf[255];
1413 char* p;
1414 int psize;
1415 int npages;
1416 int i;
1417
1418 if (ipod_scsi_inquiry(ipod, 0xc0, buf, sizeof(buf)) < 0)
1419 {
1420 fprintf(stderr,"[ERR] Sending SCSI Command failed.\n");
1421 return -1;
1422 }
1423
1424 /* Reading directly into hdr[] causes problems (for an unknown reason) on
1425 win32 */
1426 memcpy(hdr, buf, sizeof(hdr));
1427
1428 npages = hdr[3];
1429
1430 psize = npages * 0xf8; /* Hopefully this is enough. */
1431
1432 ipod->xmlinfo = malloc(psize);
1433 ipod->xmlinfo_len = 0;
1434
1435 if (ipod->xmlinfo == NULL) {
1436 fprintf(stderr,"[ERR] Could not allocate RAM for xmlinfo\n");
1437 return -1;
1438 }
1439
1440 p = ipod->xmlinfo;
1441
1442 for (i=0; i < npages; i++) {
1443 if (ipod_scsi_inquiry(ipod, hdr[i+4], buf, sizeof(buf)) < 0) {
1444 fprintf(stderr,"[ERR] Sending SCSI Command failed.\n");
1445 return -1;
1446 }
1447
1448 if ((buf[3] + ipod->xmlinfo_len) > psize) {
1449 fprintf(stderr,"[ERR] Ran out of memory reading xmlinfo\n");
1450 free(ipod->xmlinfo);
1451 ipod->xmlinfo = NULL;
1452 ipod->xmlinfo_len = 0;
1453 return -1;
1454 }
1455
1456 memcpy(p, buf + 4, buf[3]);
1457 p += buf[3];
1458 ipod->xmlinfo_len += buf[3];
1459 }
1460
1461 /* NULL-terminate the XML info */
1462 *p = 0;
1463
1464 fprintf(stderr,"[INFO] Read XML info (%d bytes)\n",ipod->xmlinfo_len);
1465
1466 return 0;
1467}
1468
1469void ipod_get_ramsize(struct ipod_t* ipod)
1470{
1471 const char needle[] = "<key>RAM</key>\n<integer>";
1472 char* p;
1473
1474 if (ipod->xmlinfo == NULL)
1475 return;
1476
1477 p = strstr(ipod->xmlinfo, needle);
1478
1479 if (p) {
1480 ipod->ramsize = atoi(p + sizeof(needle) - 1);
1481 }
1482}
1483
1404#ifndef RBUTIL 1484#ifndef RBUTIL
1405 1485
1406static inline uint32_t getuint32le(unsigned char* buf) 1486static inline uint32_t getuint32le(unsigned char* buf)
diff --git a/rbutil/ipodpatcher/ipodpatcher.h b/rbutil/ipodpatcher/ipodpatcher.h
index bb80ba3758..3fbb83ca9e 100644
--- a/rbutil/ipodpatcher/ipodpatcher.h
+++ b/rbutil/ipodpatcher/ipodpatcher.h
@@ -54,6 +54,8 @@ int list_images(struct ipod_t* ipod);
54int getmodel(struct ipod_t* ipod, int ipod_version); 54int getmodel(struct ipod_t* ipod, int ipod_version);
55int ipod_scan(struct ipod_t* ipod); 55int ipod_scan(struct ipod_t* ipod);
56int write_dos_partition_table(struct ipod_t* ipod); 56int write_dos_partition_table(struct ipod_t* ipod);
57int ipod_get_xmlinfo(struct ipod_t* ipod);
58void ipod_get_ramsize(struct ipod_t* ipod);
57int read_aupd(struct ipod_t* ipod, char* filename); 59int read_aupd(struct ipod_t* ipod, char* filename);
58int write_aupd(struct ipod_t* ipod, char* filename); 60int write_aupd(struct ipod_t* ipod, char* filename);
59off_t filesize(int fd); 61off_t filesize(int fd);
diff --git a/rbutil/ipodpatcher/main.c b/rbutil/ipodpatcher/main.c
index 88ac3a60e1..1dcb916240 100644
--- a/rbutil/ipodpatcher/main.c
+++ b/rbutil/ipodpatcher/main.c
@@ -50,6 +50,7 @@ enum {
50 READ_PARTITION, 50 READ_PARTITION,
51 WRITE_PARTITION, 51 WRITE_PARTITION,
52 FORMAT_PARTITION, 52 FORMAT_PARTITION,
53 DUMP_XML,
53 CONVERT_TO_FAT32 54 CONVERT_TO_FAT32
54}; 55};
55 56
@@ -93,6 +94,7 @@ void print_usage(void)
93 fprintf(stderr," -c, --convert\n"); 94 fprintf(stderr," -c, --convert\n");
94 fprintf(stderr," --read-aupd filename.bin\n"); 95 fprintf(stderr," --read-aupd filename.bin\n");
95 fprintf(stderr," --write-aupd filename.bin\n"); 96 fprintf(stderr," --write-aupd filename.bin\n");
97 fprintf(stderr," -x --dump-xml filename.xml\n");
96 fprintf(stderr,"\n"); 98 fprintf(stderr,"\n");
97 99
98#ifdef __WIN32__ 100#ifdef __WIN32__
@@ -315,6 +317,13 @@ int main(int argc, char* argv[])
315 if (i == argc) { print_usage(); return 1; } 317 if (i == argc) { print_usage(); return 1; }
316 filename=argv[i]; 318 filename=argv[i];
317 i++; 319 i++;
320 } else if ((strcmp(argv[i],"-x")==0) ||
321 (strcmp(argv[i],"--dump-xml")==0)) {
322 action = DUMP_XML;
323 i++;
324 if (i == argc) { print_usage(); return 1; }
325 filename=argv[i];
326 i++;
318 } else if ((strcmp(argv[i],"-c")==0) || 327 } else if ((strcmp(argv[i],"-c")==0) ||
319 (strcmp(argv[i],"--convert")==0)) { 328 (strcmp(argv[i],"--convert")==0)) {
320 action = CONVERT_TO_FAT32; 329 action = CONVERT_TO_FAT32;
@@ -361,8 +370,26 @@ int main(int argc, char* argv[])
361 return -1; 370 return -1;
362 } 371 }
363 372
364 printf("[INFO] Ipod model: %s (\"%s\")\n",ipod.modelstr, 373#ifdef __WIN32__
365 ipod.macpod ? "macpod" : "winpod"); 374 /* Windows requires the ipod in R/W mode for SCSI Inquiry */
375 if (ipod_reopen_rw(&ipod) < 0) {
376 return 5;
377 }
378#endif
379
380
381 /* Read the XML info, and if successful, look for the ramsize
382 (only available for some models - set to 0 if not known) */
383
384 ipod.ramsize = 0;
385
386 if (ipod_get_xmlinfo(&ipod) == 0) {
387 ipod_get_ramsize(&ipod);
388 }
389
390 printf("[INFO] Ipod model: %s ",ipod.modelstr);
391 if (ipod.ramsize > 0) { printf("(%dMB RAM) ",ipod.ramsize); }
392 printf("(\"%s\")\n",ipod.macpod ? "macpod" : "winpod");
366 393
367 if (ipod.ipod_directory[0].vers == 0x10000) { 394 if (ipod.ipod_directory[0].vers == 0x10000) {
368 fprintf(stderr,"[ERR] *** ipodpatcher does not support the 2nd Generation Nano! ***\n"); 395 fprintf(stderr,"[ERR] *** ipodpatcher does not support the 2nd Generation Nano! ***\n");
@@ -476,6 +503,24 @@ int main(int argc, char* argv[])
476 } else { 503 } else {
477 fprintf(stderr,"[ERR] --write-aupd failed.\n"); 504 fprintf(stderr,"[ERR] --write-aupd failed.\n");
478 } 505 }
506 } else if (action==DUMP_XML) {
507 if (ipod.xmlinfo == NULL) {
508 fprintf(stderr,"[ERR] No XML to write\n");
509 return 1;
510 }
511
512 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE);
513 if (outfile < 0) {
514 perror(filename);
515 return 4;
516 }
517
518 if (write(outfile, ipod.xmlinfo, ipod.xmlinfo_len) < 0) {
519 fprintf(stderr,"[ERR] --dump-xml failed.\n");
520 } else {
521 fprintf(stderr,"[INFO] XML info written to %s.\n",filename);
522 }
523 close(outfile);
479 } else if (action==READ_PARTITION) { 524 } else if (action==READ_PARTITION) {
480 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE); 525 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE);
481 if (outfile < 0) { 526 if (outfile < 0) {
@@ -571,6 +616,5 @@ int main(int argc, char* argv[])
571 } 616 }
572#endif 617#endif
573 618
574
575 return 0; 619 return 0;
576} 620}