#include #include #include #include #include #include #include /* * convert a UTF16BE string to UTF8 and print it. Because iconv messes * with the i/o pointers, we need to keep two copies of each. */ gchar *convert_to_utf8( char *inbuffer, size_t maxlen ) { iconv_t cd = (iconv_t) -1; size_t outbytesleft, inbytesleft; size_t status; char *outbuffer = NULL, *outbuf; char *inbuf = inbuffer; /* Find out how many bytes to convert. Inbound data will be an array of 16bit values, either null-terminated or running right up against maxlen. */ for ( inbytesleft = 0; inbytesleft < maxlen; inbytesleft++ ) { if ( inbuf[inbytesleft * 2 + 1] == 0 && inbuf[inbytesleft * 2] == 0 ) { break; } } /* insane, but possible: UTF8 can use up to six bytes to represent a character. The +1 is for a trailing NULL */ outbytesleft = inbytesleft * 6 + 1; outbuffer = g_malloc( outbytesleft ); memset( outbuffer, 0, outbytesleft ); outbuf = outbuffer; /* convert 16bit size to 8bit size */ inbytesleft *= 2; cd = iconv_open( "UTF8", "UTF16BE" ); if ( cd != (iconv_t)(-1)) { status = iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); if ( status == -1 ) { perror( "conv" ); exit( 1 ); } goto out; } /* if we get here, some part of the conversion failed */ perror( "conv" ); exit( 1 ); out: if ( cd != (iconv_t) -1 ) { iconv_close( cd ); } return outbuffer; } /* * */ int main( int argc, char *argv[] ) { nw_device_t *dev; char *devstring; char *sourcefile = NULL, *destfile = NULL; int sourcetrack = -1; guint32 msn = 0; gboolean gotmsn = FALSE; if ( argc < 3 ) { fprintf( stderr, "usage: %s from to\n", argv[0] ); exit( 1 ); } else if ( argc == 4 ) { msn = atol( argv[3] ); gotmsn = TRUE; } /* this is full of stupid */ if ( g_str_has_suffix( argv[1], ".dat" ) || g_str_has_suffix( argv[1], ".DAT" ) || g_str_has_suffix( argv[1], ".oma" ) || g_str_has_suffix( argv[1], ".OMA" )) { /* device -> filesystem */ char *tmp1, *tmp2 = g_path_get_dirname( argv[1] ); /* /mnt/point/esys/nw-mp3 */ tmp1 = g_path_get_dirname( tmp2 ); /* ...esys */ g_free( tmp2 ); devstring = g_path_get_dirname( tmp1 ); /* /mnt/point */ g_free( tmp1 ); /* mpXXXX.dat */ sourcefile = g_path_get_basename( argv[1] ); if ( g_ascii_strncasecmp( "mp", sourcefile, 2 ) == 0 && strlen( sourcefile ) == 10 ) { int c; sourcetrack = 0; for ( c = 2; c < 6; c++ ) { char v = sourcefile[c]; if ( v > 'F' ) { v -= ( 'a' - 10 ); } else if ( v > '9' ) { v -= ( 'A' - 10 ); } else { v -= '0'; } sourcetrack |= ( v << (( 5 - c ) * 4 )); } } else { /* v2 */ int c; dprintf( stderr, "parsing sourcefile %s\n", sourcefile ); sourcetrack = 0; for ( c = 1; c < 8; c++ ) { char v = sourcefile[c]; if ( v > 'F' ) { v -= ( 'a' - 10 ); } else if ( v > '9' ) { v -= ( 'A' - 10 ); } else { v -= '0'; } sourcetrack |= ( v << (( 7 - c ) * 4 )); } } g_free( sourcefile ); sourcefile = NULL; destfile = g_strdup( argv[2] ); } else { /* filesystem -> device */ devstring = g_strdup( argv[1] ); sourcefile = g_strdup( argv[2] ); } #ifdef DEBUG fprintf( stderr, "copying " ); if ( sourcefile != NULL ) { fprintf( stderr, "%s to ", sourcefile ); } else { fprintf( stderr, "%s, track %d to ", devstring, sourcetrack ); } if ( destfile != NULL ) { fprintf( stderr, "%s\n", destfile ); } else { fprintf( stderr, "%s\n", devstring ); } #endif dev = nw_dev_init( devstring, NW_GUESS ); g_free( devstring ); if ( dev == NULL ) { fprintf( stderr, "failed to init %s: %s\n", devstring, strerror( errno )); exit( 1 ); } if ( nw_parse_directory( dev ) == NULL ) { fprintf( stderr, "failed to get folder list: %s\n", strerror( errno )); exit( 1 ); } /* if ( gotmsn != FALSE ) { dev->msn = msn; } */ if ( sourcetrack != -1 ) { /* device -> filesystem */ nw_track_t *tptr = nw_get_track_ptr( dev, sourcetrack ); NWFILE *mfp; FILE *fp; char buffer[BUFSIZ]; int nbytes, total = 0; struct stat statbuf; if ( tptr == NULL ) { fprintf( stderr, "failed to get track: %s\n", strerror( errno )); exit( 1 ); } if ( g_file_test( destfile, G_FILE_TEST_IS_DIR )) { /* need to get the filename from the device */ id3_utf8_t *fname = nw_get_tag( tptr, NW_FILENAME ); if ( fname == NULL || !strlen( fname )) { fname = g_strdup_printf( "Track %d.mp3", sourcetrack ); } destfile = g_strdup_printf( "%s/%s", destfile, fname ); } if (( mfp = nw_fopen( dev, 0, sourcetrack, NULL, "rb" )) == NULL ) { fprintf( stderr, "nw_open: %s\n", strerror( errno )); exit( 1 ); } if (( fp = fopen( destfile, "wb" )) == NULL ) { fprintf( stderr, "fopen %s: %s\n", destfile, strerror( errno )); exit( 1 ); } nw_stat( dev, sourcetrack, &statbuf ); total = statbuf.st_size; while( total ) { nbytes = nw_fread( buffer, 1, BUFSIZ, mfp ); /* manpage: if an error occurs, the return value is a short item count (or zero) */ if ( nbytes == 0 ) { break; } fwrite( buffer, 1, nbytes, fp ); total -= nbytes; } } nw_dev_free( dev ); return 0; }