View Full Version : first attempt at cmd line iso decrypter based on libcdio/udf and dvdcss
setarip_old
26th October 2010, 19:04
I'm referring to actual Windows (I, for one, know nothing about Linux, cygwin, etc.)
spotter
26th October 2010, 20:09
cygwin is windows. its an application that runs in windows that provides a unix like environment and lets you compile/run many unix programs. someone else would have to build it for that environment, but it should be easy.
SledgeHammer_999
27th October 2010, 13:51
I think it might be possible to compile it using Mingw (http://www.mingw.org/) too!
spotter
27th October 2010, 14:23
probably and mingw is better in my experience (at least I've had better experience compiling handbrakecli w/ mingw than with cygwin). but one would still need a version of ddrescue.
spotter
27th October 2010, 15:56
I can't get an environment setup for mingw easily and don't have time to play with it, if anyone else wants to create a mingw binary, go ahead.
sl1pkn07
28th October 2010, 14:13
thanks man!
(for make you program for linux!)
is possible make the all steps directly with your progarm? (calling lsdvd and ddrescue and make the iso decrypter directly form te drive)
spotter
28th October 2010, 15:46
no, it works directly on the iso. ./a.out <iso image>
what I do
1) lsdvd /dev/dvd
2) ddrescue -v -b 2048 -d /dev/dvd <image.iso> <image.log>
(perhaps adding -r -1 depending if scratched and trying to rescue scratched but valid parts, but makes it hard to distinguish with protection based invalid sectors, so losing proposition if you have a scratched disc of that type)
3) ./a.out <image.iso>
I give no warranties that my program wont mess up the ISO image, could very well be buggy. But I think it works well enough to prove that my naive method is a sound approach for whole disc decryption.
spotter
28th October 2010, 20:19
I should be picking up iron man 2 from library tonight to test on. Also watched Alice in Wonderland through last night, didn't notice any problems.
setarip_old
29th October 2010, 00:38
Also watched Alice in Wonderland through last night, didn't notice any problems.Including all menus and extras, or just "movie only"?
spotter
29th October 2010, 00:41
well, both disney fast play into movie and watching the movie through regular menu
spotter
29th October 2010, 02:13
iron man 2 extras DVD worked fine.
spotter
29th October 2010, 02:31
not watching through the whole video at this moment but disc 1 (the movie) seems to be fine too (windows media player playing the mounted iso w/ daemon tools)
setarip_old
29th October 2010, 03:32
If you burn a disc from the .ISO, would that play properly, on a PC, on a standalone player?
spotter
29th October 2010, 03:33
as mentioned, if it requires dual layer, I'd think that might be an issue. I don't know how to calculate the equivalent of an mds file.
setarip_old
29th October 2010, 03:35
I just had an odd thought (don't ask why) - You're not running AnyDVD or DVDFab while doing any of this, are you?
Again, a very odd thought...
spotter
29th October 2010, 03:40
By definition no. This is all in Linux.
Also, I'm thinking that layer break might not be an issue. imgburn seems to be able to figure it out.
cwl7454
29th October 2010, 09:43
"By definition no"
Rather odd answer
spotter
29th October 2010, 17:01
"By definition no"
Rather odd answer
if I'm running in Linux, how can I anydvd/dvdfab running?
qyot27
30th October 2010, 14:12
In an effort to help on the MinGW side, trying to compile results in the following error:
$ g++ `pkg-config --cflags --libs libdvdcss libiso9660` decrypter.cpp
decrypter.cpp: In function 'int main(int, char**)':
decrypter.cpp:244:34: error: 'bcopy' was not declared in this scope
This was with the 2010.09.07 premade MSys/MinGW environment on the CCCP Wiki, straight as it comes with no additional stuff installed or tweaked. It can compile libdvdcss and libcdio out of the box, but it chokes on the decrypter, with the above error.
spotter
30th October 2010, 23:54
add #include <strings.h> (I just had string.h) or replace bcopy w/ memcpy (and switch src/dest params around)
spotter
31st October 2010, 02:50
updated version, mostly to fix problem compiling described above.
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
#define _LARGEFILE_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <dvdcss/dvdcss.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cdio/cdio.h>
#include <cdio/iso9660.h>
#include <vector>
#include <map>
#include <algorithm>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <errno.h>
using namespace std;
#define MAX 2000
#define CEILING(x, y) ((x+(y-1))/y) //ripped from libudf
vector<unsigned long long> start_blocks;
map<unsigned long long, unsigned long long> end_blocks;
map<unsigned long long, char *> start_map;
ssize_t my_write(int fd, const void * buf, size_t count)
{
int ret;
size_t my_count = count;
char * my_buf = (char *) buf;
while (my_count) {
if (my_count != count) {
printf("looped in my_write, last write = %d\n", ret);
}
if ((ret = write(fd, my_buf, my_count)) == -1) {
if (errno != EINTR) {
perror("write failed!");
goto out;
}
} else {
my_count -= ret;
my_buf += ret;
}
}
ret = count;
out:
return ret;
}
void find_start_blocks(iso9660_t *p_iso)
{
CdioList_t *p_entlist;
CdioListNode_t *p_entnode;
if (!p_iso)
return;
p_entlist = iso9660_ifs_readdir (p_iso, "/video_ts/");
if (p_entlist) {
_CDIO_LIST_FOREACH (p_entnode, p_entlist)
{
unsigned long long start;
unsigned long long blocks;
char filename[4096];
int len;
iso9660_stat_t *p_statbuf =
(iso9660_stat_t *) _cdio_list_node_data (p_entnode);
iso9660_name_translate(p_statbuf->filename, filename);
len = strlen(filename);
if (!(2 == p_statbuf->type) ) {
if (! strcmp(filename + (len-3), "vob")) {
start = p_statbuf->lsn;
blocks = CEILING(p_statbuf->size, DVDCSS_BLOCK_SIZE);
start_map[start] = strdup(filename);
if (blocks == 0) {
//file length of 0 would result in a blocks of 0, and don't want
//to subtract one from it.
end_blocks[start] = start;
} else {
//-1 as start block is included in count of blocks
end_blocks[start] = start - 1 + blocks;
}
printf("%s: %llu->%llu (%llu blocks)\n", filename, start, end_blocks[start], blocks);
if (blocks) {
if (find(start_blocks.begin(), start_blocks.end(), start) == start_blocks.end()) {
start_blocks.push_back(start);
}
}
}
}
}
_cdio_list_free (p_entlist, true);
}
}
int main(int argc, char *argv[])
{
dvdcss_t input;
int fd;
int flags = O_RDWR;
off64_t disc_len;
int total_blocks;
unsigned long long pos = 0;
iso9660_t * p_iso;
char * buffer;
unsigned long long preamble;
unsigned long long count = 0;
if (argc == 3 && !strcmp(argv[2], "-test")) {
flags = O_RDONLY;
}
if (!(buffer = (char *) malloc(MAX*DVDCSS_BLOCK_SIZE))) {
printf("failed to allocate space for buffer\n");
return 0;
}
if (argc < 2) {
printf("usage:\n\t %s <input iso>\n", argv[0]);
return 1;
}
if ((fd = open(argv[1], flags)) < 0) {
printf("failed to open input/output file\n");
return 1;
}
/* figure out how big the ISO image is */
if ((disc_len = lseek64(fd, 0, SEEK_END)) < 0) {
perror("lseek64 failed");
return 1;
}
total_blocks = disc_len / DVDCSS_BLOCK_SIZE;
if (disc_len != (long long) total_blocks * DVDCSS_BLOCK_SIZE) {
printf("partial block?????\n");
return 1;
}
printf("total_blocks = %d\n", total_blocks);
start_blocks.push_back(total_blocks);
/* find locations where have to rekey CSS */
if ((p_iso = iso9660_open(argv[1])) == NULL) {
printf("couldn't open %s as UDF\n", argv[1]);
return 1;
}
find_start_blocks(p_iso);
sort(start_blocks.begin(), start_blocks.end());
for(vector<unsigned long long>::iterator it = start_blocks.begin(); it != start_blocks.end(); it++) {
printf("end pos = %llu\n", *it);
}
for(map<unsigned long long, char *>::iterator p = start_map.begin(); p != start_map.end(); p++) {
printf("%s : %llu\n", p->second, p->first);
}
if (argc == 3 && !strcmp(argv[2], "-test")) {
return 0;
}
/* prep CSS */
if (!(input = dvdcss_open(argv[1]))) {
printf("dvdcss_open failed\n");
return 1;
}
/* if not scrambled skip! */
/* this doesn't do anything on iso input */
if (! dvdcss_is_scrambled(input)) {
printf("dvd isn't scrambled\n");
return 0;
}
preamble = start_blocks[0];
start_blocks.erase(start_blocks.begin());
lseek64(fd, preamble*DVDCSS_BLOCK_SIZE, SEEK_SET);
pos = preamble;
while (! start_blocks.empty()) {
int len = MAX;
int blocks_read;
int cur = pos;
int end = start_blocks[0];
fflush(NULL);
start_blocks.erase(start_blocks.begin());
//printf("syncing at position = %llu, next sync point at %u\n", pos, end);
if ( dvdcss_seek(input, pos, DVDCSS_SEEK_KEY) < 0) {
//Q. Can it ever fail to get key here, but have the key
//elsewhere? perhaps have some accounting if this fails,
//know no point in trying to dvdcss_read() till next
//DVDCSS_SEEK_KEY?
printf("failed to seek to %llu: %s\n", pos, dvdcss_error(input));
}
while (pos < end) {
int read_size;
char * tmp_buffer;
int reseek;
fflush(NULL);
if (pos + len > end) {
len = end - pos;
}
read_size = len * DVDCSS_BLOCK_SIZE;
if ((blocks_read = read(fd, buffer, read_size)) != read_size) {
printf("short read, not handled yet\n");
return 1;
}
tmp_buffer = buffer;
reseek = 0;
for(int index = 0; index < len; index++) {
char block[2048];
if( ((uint8_t*)tmp_buffer)[0x14] & 0x30 ) {
int skip=0;
if (pos + index > end_blocks[cur]) {
printf("should skipping decode of supposed encrypted block (%llu) as not within VOB\n", pos+index);
bcopy(tmp_buffer, block, 2048);
skip=1;
}
count++;
if (dvdcss_seek(input, pos+index, DVDCSS_NOFLAGS) < 0) {
printf("failed to seek to %llu (index %d): %s\n", pos+index, index, dvdcss_error(input));
return 1;
}
if (dvdcss_read(input, tmp_buffer, 1, DVDCSS_READ_DECRYPT) != 1) {
printf("dvdcss_read failed\n");
return 1;
}
if (skip) {
printf("testing block we are skipping anyways\n");
if( ((uint8_t*)tmp_buffer)[0x14] & 0x30 ) {
printf("dvdcss \"decoded\" block still has bit set\n");
if (!memcmp(tmp_buffer, block, 2048)) {
printf("dvdcss \"decoded\" block didn't change!\n");
} else {
printf("dvdcss \"decoded\" block changed!\n");
}
} else {
printf("dvdcss \"decoded\" block got bit removed!\n");
}
} else {
lseek64(fd, (pos+index) * DVDCSS_BLOCK_SIZE, SEEK_SET);
if (my_write(fd, tmp_buffer, DVDCSS_BLOCK_SIZE) < 0) {
return 1;
}
reseek = 1;
}
}
tmp_buffer = tmp_buffer + DVDCSS_BLOCK_SIZE;
}
pos += len;
if (reseek) {
lseek64(fd, pos * DVDCSS_BLOCK_SIZE, SEEK_SET);
}
}
}
printf("descrambled %llu blocks\n", count);
printf("\n");
return 0;
}
SledgeHammer_999
31st October 2010, 15:53
Since this is C++ code you should change the includes to:
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
#define _LARGEFILE_SOURCE 1
#include <cstdio>
#include <unistd.h>
#include <dvdcss/dvdcss.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cdio/cdio.h>
#include <cdio/iso9660.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstring>
#include <strings.h>
#include <cctype>
#include <cerrno>
using namespace std;
#define MAX 2000
#define CEILING(x, y) ((x+(y-1))/y) //ripped from libudf
vector<unsigned long long> start_blocks;
map<unsigned long long, unsigned long long> end_blocks;
map<unsigned long long, char *> start_map;
ssize_t my_write(int fd, const void * buf, size_t count)
{
int ret;
size_t my_count = count;
char * my_buf = (char *) buf;
while (my_count) {
if (my_count != count) {
printf("looped in my_write, last write = %d\n", ret);
}
if ((ret = write(fd, my_buf, my_count)) == -1) {
if (errno != EINTR) {
perror("write failed!");
goto out;
}
} else {
my_count -= ret;
my_buf += ret;
}
}
ret = count;
out:
return ret;
}
void find_start_blocks(iso9660_t *p_iso)
{
CdioList_t *p_entlist;
CdioListNode_t *p_entnode;
if (!p_iso)
return;
p_entlist = iso9660_ifs_readdir (p_iso, "/video_ts/");
if (p_entlist) {
_CDIO_LIST_FOREACH (p_entnode, p_entlist)
{
unsigned long long start;
unsigned long long blocks;
char filename[4096];
int len;
iso9660_stat_t *p_statbuf =
(iso9660_stat_t *) _cdio_list_node_data (p_entnode);
iso9660_name_translate(p_statbuf->filename, filename);
len = strlen(filename);
if (!(2 == p_statbuf->type) ) {
if (! strcmp(filename + (len-3), "vob")) {
start = p_statbuf->lsn;
blocks = CEILING(p_statbuf->size, DVDCSS_BLOCK_SIZE);
start_map[start] = strdup(filename);
if (blocks == 0) {
//file length of 0 would result in a blocks of 0, and don't want
//to subtract one from it.
end_blocks[start] = start;
} else {
//-1 as start block is included in count of blocks
end_blocks[start] = start - 1 + blocks;
}
printf("%s: %llu->%llu (%llu blocks)\n", filename, start, end_blocks[start], blocks);
if (blocks) {
if (find(start_blocks.begin(), start_blocks.end(), start) == start_blocks.end()) {
start_blocks.push_back(start);
}
}
}
}
}
_cdio_list_free (p_entlist, true);
}
}
int main(int argc, char *argv[])
{
dvdcss_t input;
int fd;
int flags = O_RDWR;
off64_t disc_len;
int total_blocks;
unsigned long long pos = 0;
iso9660_t * p_iso;
char * buffer;
unsigned long long preamble;
unsigned long long count = 0;
if (argc == 3 && !strcmp(argv[2], "-test")) {
flags = O_RDONLY;
}
if (!(buffer = (char *) malloc(MAX*DVDCSS_BLOCK_SIZE))) {
printf("failed to allocate space for buffer\n");
return 0;
}
if (argc < 2) {
printf("usage:\n\t %s <input iso>\n", argv[0]);
return 1;
}
if ((fd = open(argv[1], flags)) < 0) {
printf("failed to open input/output file\n");
return 1;
}
/* figure out how big the ISO image is */
if ((disc_len = lseek64(fd, 0, SEEK_END)) < 0) {
perror("lseek64 failed");
return 1;
}
total_blocks = disc_len / DVDCSS_BLOCK_SIZE;
if (disc_len != (long long) total_blocks * DVDCSS_BLOCK_SIZE) {
printf("partial block?????\n");
return 1;
}
printf("total_blocks = %d\n", total_blocks);
start_blocks.push_back(total_blocks);
/* find locations where have to rekey CSS */
if ((p_iso = iso9660_open(argv[1])) == NULL) {
printf("couldn't open %s as UDF\n", argv[1]);
return 1;
}
find_start_blocks(p_iso);
sort(start_blocks.begin(), start_blocks.end());
for(vector<unsigned long long>::iterator it = start_blocks.begin(); it != start_blocks.end(); it++) {
printf("end pos = %llu\n", *it);
}
for(map<unsigned long long, char *>::iterator p = start_map.begin(); p != start_map.end(); p++) {
printf("%s : %llu\n", p->second, p->first);
}
if (argc == 3 && !strcmp(argv[2], "-test")) {
return 0;
}
/* prep CSS */
if (!(input = dvdcss_open(argv[1]))) {
printf("dvdcss_open failed\n");
return 1;
}
/* if not scrambled skip! */
/* this doesn't do anything on iso input */
if (! dvdcss_is_scrambled(input)) {
printf("dvd isn't scrambled\n");
return 0;
}
preamble = start_blocks[0];
start_blocks.erase(start_blocks.begin());
lseek64(fd, preamble*DVDCSS_BLOCK_SIZE, SEEK_SET);
pos = preamble;
while (! start_blocks.empty()) {
int len = MAX;
int blocks_read;
int cur = pos;
int end = start_blocks[0];
fflush(NULL);
start_blocks.erase(start_blocks.begin());
//printf("syncing at position = %llu, next sync point at %u\n", pos, end);
if ( dvdcss_seek(input, pos, DVDCSS_SEEK_KEY) < 0) {
//Q. Can it ever fail to get key here, but have the key
//elsewhere? perhaps have some accounting if this fails,
//know no point in trying to dvdcss_read() till next
//DVDCSS_SEEK_KEY?
printf("failed to seek to %llu: %s\n", pos, dvdcss_error(input));
}
while (pos < end) {
int read_size;
char * tmp_buffer;
int reseek;
fflush(NULL);
if (pos + len > end) {
len = end - pos;
}
read_size = len * DVDCSS_BLOCK_SIZE;
if ((blocks_read = read(fd, buffer, read_size)) != read_size) {
printf("short read, not handled yet\n");
return 1;
}
tmp_buffer = buffer;
reseek = 0;
for(int index = 0; index < len; index++) {
char block[2048];
if( ((uint8_t*)tmp_buffer)[0x14] & 0x30 ) {
int skip=0;
if (pos + index > end_blocks[cur]) {
printf("should skipping decode of supposed encrypted block (%llu) as not within VOB\n", pos+index);
bcopy(tmp_buffer, block, 2048);
skip=1;
}
count++;
if (dvdcss_seek(input, pos+index, DVDCSS_NOFLAGS) < 0) {
printf("failed to seek to %llu (index %d): %s\n", pos+index, index, dvdcss_error(input));
return 1;
}
if (dvdcss_read(input, tmp_buffer, 1, DVDCSS_READ_DECRYPT) != 1) {
printf("dvdcss_read failed\n");
return 1;
}
if (skip) {
printf("testing block we are skipping anyways\n");
if( ((uint8_t*)tmp_buffer)[0x14] & 0x30 ) {
printf("dvdcss \"decoded\" block still has bit set\n");
if (!memcmp(tmp_buffer, block, 2048)) {
printf("dvdcss \"decoded\" block didn't change!\n");
} else {
printf("dvdcss \"decoded\" block changed!\n");
}
} else {
printf("dvdcss \"decoded\" block got bit removed!\n");
}
} else {
lseek64(fd, (pos+index) * DVDCSS_BLOCK_SIZE, SEEK_SET);
if (my_write(fd, tmp_buffer, DVDCSS_BLOCK_SIZE) < 0) {
return 1;
}
reseek = 1;
}
}
tmp_buffer = tmp_buffer + DVDCSS_BLOCK_SIZE;
}
pos += len;
if (reseek) {
lseek64(fd, pos * DVDCSS_BLOCK_SIZE, SEEK_SET);
}
}
}
printf("descrambled %llu blocks\n", count);
printf("\n");
return 0;
}
spotter
31st October 2010, 17:37
it's mostly a C program w/ C++ data structures algorithms. started off as a c program, but was lazy and didn't want to write my own map/vector data structures or depend on even more libs. so yea, could be benefit to change, but doesn't matter much (or teach me why I'm wrong).
SledgeHammer_999
31st October 2010, 19:10
Since you're using C++ features and you compile it using g++ it is considered a C++ program (although one can see that it started as a C program). Also C++, in order to remain compatible with C code, it introduced a new way to include the standard libs. As far as I know this is the standard way in C++ to include the "C standard libs". Maybe it is done to prevent compatibility issues, I am not sure.
spotter
31st October 2010, 19:41
ok, updated my version, seems to make no difference in binary produced by gcc, same exact size when stripped (unstripped, slightly larger w/ c++ headers).
qyot27
31st October 2010, 20:51
Now the error reads:
g++ `pkg-config --cflags --libs libdvdcss libiso9660` decrypter-v7.cpp
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xc0): undefined reference to `iso9660_ifs_readdir'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xd8): undefined reference to `_cdio_list_begin'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xeb): undefined reference to `_cdio_list_node_data'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x109): undefined reference to `iso9660_name_translate'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x2ce): undefined reference to `_cdio_list_node_next'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x2f3): undefined reference to `_cdio_list_free'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x52b): undefined reference to `iso9660_open'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x6f8): undefined reference to `dvdcss_open'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x733): undefined reference to `dvdcss_is_scrambled'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x86d): undefined reference to `dvdcss_seek'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0x887): undefined reference to `dvdcss_error'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xa66): undefined reference to `bcopy'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xaad): undefined reference to `dvdcss_seek'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xac3): undefined reference to `dvdcss_error'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccjjuOeD.o:decrypter-v7.cpp:(.text+0xb32): undefined reference to `dvdcss_read'
collect2: ld returned 1 exit status
The same occurs with the version SledgeHammer_999 posted as well. Even though I installed libdvdcss and libcdio to /mingw, and even tried /local and msys' root. All the same error. And the bcopy problem is still there. The issue at least partially stems from the fact MinGW doesn't define bcopy at all. Switching to memcpy and reversing the src/dest parameters (I'm guessing those are 'tmp_buffer' and 'block' in said call) resolves the bcopy error, but the libdvdcss and libcdio errors remain.
Is that stuff related to the code itself or to the parameters passed to g++? Up until now my compiling experience is with projects with full-fledged build systems, not calling the compiler directly.
spotter
31st October 2010, 21:17
assuming everything is installed in default lookup path, you would compile it like
g++ -ldvdcss -ludf -liso9660 -lcdio -lm <source code>
(though in reality the -ludf isn't needed for latest version as not using any udf calls)
for instance, on my ubuntu box, pkg-config says the params should be
-I/usr/include/libdvdcss -ldvdcss -ludf -liso9660 -lcdio -lm
i.e. all libs are stored in normal place and dvdcss headers are stored under /usr/include/libdvdcss as their rooted location.
now if the above command doesn't work, i.e. returns an error like
spotter@dent:~/dvdripper$ g++ -lfoobar 6.cpp
/usr/bin/ld: cannot find -lfoobar
collect2: ld returned 1 exit status
then that means it's not stored in the normal location, to specify search path for libraries you use
-L/path/to/lib
you can have multiple of these -L calls.
spotter
1st November 2010, 05:21
qyot27: any progress?
qyot27
1st November 2010, 17:23
Nope. I tried all of these different commands (as I went and explicitly duplicated the include/lib across all the main paths in the environment, just in case it wasn't picking them up in /local):
g++ -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
g++ -I/include -L/lib -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
g++ -I/mingw/include -L/mingw/lib -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
g++ -I/local/include -L/local/lib -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
All resulted in the same 'undefined reference' errors. By default, libcdio and libdvdcss installed themselves to /local, but using WinRAR I archived and then unpacked them to /mingw and / as well (as msys' / = /usr in a normal *nix setup). I even went and edited all of pkg-config's .pc files in /local/lib/pkgconfig to point to /local instead of /usr/local, but that didn't change anything (and I already knew msys understands /usr locations to be points in its root directory).
Based on the error messages, which talk about an .o file residing in the Temp folder in Local Settings, I went and watched said folder as I ran the command. No .o file gets generated there, although a .s file does. What's more, is that the filename given for the .o file and the generated .s file don't match either. Unfortunately, as soon as the command errors and exits, the .s file disappears. I'm not sure why MSys is calling a location completely outside of its filesystem tree, but I wonder if that's not a part of why this isn't working.
I did use the SVN and git versions of libdvdcss and libcdio respectively, might that be what's going wrong? On Ubuntu I simply used the stock/repo versions (libdvdcss-dev from Medibuntu), which are more likely than not from the release tarballs than the development branch. On Ubuntu it compiled fine, but I know from experience that things don't always go as smoothly with MSys as it does on a true Linux system.
SledgeHammer_999
1st November 2010, 18:00
qyote27, I understand that you know what you're doing, but I have to ask this. Did you compile libdvdcss and the other libs? Do the compiled objects exist in the paths that mingw searches? The warnings show that it fails on the linking process not on the compiling.
spotter
1st November 2010, 18:33
I spent a little time w/ mingw on a server 2003 box, failed to build both wget and libcdio. can't do much with it now.
qyot27
1st November 2010, 20:37
qyote27, I understand that you know what you're doing, but I have to ask this. Did you compile libdvdcss and the other libs? Do the compiled objects exist in the paths that mingw searches? The warnings show that it fails on the linking process not on the compiling.
Yes, I compiled both, straight from the SVN repo for libdvdcss and the git repo for libcdio, using the latest pre-prepared MSys/MinGW environment provided by the CCCP Wiki. I decided on that because it was a clean environment that others could use to try and replicate what I'm seeing, separated from my other setups.
The direct link to the environment is:
http://www.cccp-project.net/nichorai/msys.premade.2010.09.07.7z
I'll retrace everything I did here so it can be reviewed.
In a normal cmd.exe prompt:
svn checkout svn://svn.videolan.org/libdvdcss libdvdcss
git clone git://git.sv.gnu.org/libcdio.git
In MSys' rxvt prompt:
libcdio:
cd libcdio
./autogen.sh
make
make install
libdvdcss:
cd $HOME/libdvdcss/trunk
./bootstrap
./configure
make
make install
The readout of ls showing that the files are in /local:
Stephen@[computer-name-omitted] ~
$ cd /local
Stephen@[computer-name-omitted] /local
$ ls -R include
include:
cdio cdio++ dvdcss
include/cdio:
audio.h cdtext.h logging.h posix.h udf_file.h
bytesex.h device.h mmc.h read.h udf_time.h
bytesex_asm.h disc.h mmc_cmds.h rock.h utf8.h
cd_types.h ds.h mmc_hl_cmds.h sector.h util.h
cdda.h dvd.h mmc_ll_cmds.h track.h version.h
cdio.h ecma_167.h mmc_util.h types.h xa.h
cdio_config.h iso9660.h paranoia.h udf.h
include/cdio++:
cdio.hpp device.hpp disc.hpp iso9660.hpp read.hpp
cdtext.hpp devices.hpp enum.hpp mmc.hpp track.hpp
include/dvdcss:
dvdcss.h
Stephen@[computer-name-omitted] /local
$ ls -R lib
lib:
libcdio++.a libcdio_cdda.dll.a libdvdcss.la libudf.a
libcdio++.dll.a libcdio_cdda.la libiso9660++.a libudf.dll.a
libcdio++.la libcdio_paranoia.a libiso9660++.dll.a libudf.la
libcdio.a libcdio_paranoia.dll.a libiso9660++.la pkgconfig
libcdio.dll.a libcdio_paranoia.la libiso9660.a
libcdio.la libdvdcss.a libiso9660.dll.a
libcdio_cdda.a libdvdcss.dll.a libiso9660.la
lib/pkgconfig:
libcdio++.pc libcdio_cdda.pc libdvdcss.pc libiso9660.pc
libcdio.pc libcdio_paranoia.pc libiso9660++.pc libudf.pc
Stephen@[computer-name-omitted] /local
$
The $PATH variable area in /etc/profile:
if [ $MSYSTEM == MINGW32 ]; then
export PATH=".:/usr/local/bin:/mingw/bin:/bin:$PATH"
else
export PATH=".:/usr/local/bin:/bin:/mingw/bin:$PATH"
fi
Using 'echo $PATH' shows those three directories, plus all my Windows PATH settings after them (separated on new lines for ease of reading):
.:/usr/local/bin
:/mingw/bin
:/bin
:/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE
:/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN
:/c/Program Files/Microsoft Visual Studio 9.0/Common7/Tools
:/c/WINDOWS/Microsoft.NET/Framework/v3.5
:/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727
:/c/Program Files/Microsoft Visual Studio 9.0/VC/VCPackages
:/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin
:/c/Program Files/ImageMagick-6.5.5-Q16
:/c/WINDOWS/system32
:/c/WINDOWS
:/c/WINDOWS/system32/wbem
:/c/Program Files/cvsnt
:/c/Program Files/oggz-tools-0.9.9
:/c/Program Files/megui/tools/eac3to
:/c/Program Files/dvda-author
:/c/Program Files/FLAC
:/c/Program Files/MediaInfo
:/c/Program Files/megui/tools/xvid_encraw
:/c/Program Files/mplayer
:/c/Program Files/DGPulldown
:/c/Program Files/VirtualDubMod
:/c/Program Files/iTunesEncode
:/c/Program Files/megui/tools/x264
:/c/Program Files/HC025
:/c/Program Files/megui/tools/ffmpeg
:/c/Program Files/MKVtoolnix
:/c/Program Files/SVN-cygwin
:/c/Program Files/GTK2-Runtime/bin
:/c/Program Files/Microsoft SQL Server/90/Tools/binn
:/c/Program Files/QuickTime/QTSystem
:/c/Program Files/Microsoft SQL Server/90/Tools/binn/
:/c/Program Files/AviSynth 2.5/plugins/
:/c/Program Files/Windows NT/Accessories/
:/c/Program Files/dvdauthor
:/c/Program Files/Git/bin
:/c/Program Files/LAME
:/c/Program Files/qemu
:/c/Program Files/toolame-02l
:/c/WINDOWS/Python26
:/c/Program Files/SSRC
:/c/Program Files/rtmpdump
:/c/Program Files/mp4muxer
Leaving the install at the default location (/local) and attempting to compile the decrypter fails with an explicit warning about not finding dvdcss.h.
g++ -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
decrypter-v7.cpp:7:27: fatal error: dvdcss/dvdcss.h: No such file or directory
compilation terminated.
If I specify -I and -L parameters to identify that they are in /local:
g++ -I/local/include -L/local/lib -ldvdcss -ludf -liso9660 -lcdio -lm decrypter-v7.cpp
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xc0): undefined reference to `iso9660_ifs_readdir'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xd8): undefined reference to `_cdio_list_begin'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xeb): undefined reference to `_cdio_list_node_data'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x109): undefined reference to `iso9660_name_translate'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x2ce): undefined reference to `_cdio_list_node_next'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x2f3): undefined reference to `_cdio_list_free'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x52b): undefined reference to `iso9660_open'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x6f8): undefined reference to `dvdcss_open'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x733): undefined reference to `dvdcss_is_scrambled'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x86d): undefined reference to `dvdcss_seek'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0x887): undefined reference to `dvdcss_error'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xaad): undefined reference to `dvdcss_seek'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xac3): undefined reference to `dvdcss_error'
C:\DOCUME~1\Stephen\LOCALS~1\Temp\ccuqFOh5.o:decrypter-v7.cpp:(.text+0xb32): undefined reference to `dvdcss_read'
collect2: ld returned 1 exit status
The linking errors are why I was wondering if the fact I was using the development branches of libdvdcss and libcdio could be causing the problem - APIs changing and whatforth, calls being abandoned, etc.
spotter
1st November 2010, 21:05
I really doubt the api has changed much, especially w/ libdvdcss its difficult for it to change as applications generally dynamically load it if its availalable and ignore it if not.
on my linux box, I can do
spotter@dent:/usr/lib$ nm libdvdcss.a
to list all symbols
also
spotter@dent:/usr/lib$ nm -D libdvdcss.so
will do a similar thing on the dynamic version
with that said, playing around a bit, on my box
spotter@dent:~/dvdripper$ g++ -static `pkg-config --cflags --libs libdvdcss libudf libiso9660` 6.cpp
/tmp/ccTIc0df.o: In function `find_start_blocks(_iso9660_s*)':
6.cpp:(.text+0xd1): undefined reference to `iso9660_ifs_readdir'
6.cpp:(.text+0xf2): undefined reference to `_cdio_list_begin'
6.cpp:(.text+0x10b): undefined reference to `_cdio_list_node_data'
6.cpp:(.text+0x12f): undefined reference to `iso9660_name_translate'
6.cpp:(.text+0x394): undefined reference to `_cdio_list_node_next'
6.cpp:(.text+0x3c2): undefined reference to `_cdio_list_free'
/tmp/ccTIc0df.o: In function `main':
6.cpp:(.text+0x648): undefined reference to `iso9660_open'
6.cpp:(.text+0x867): undefined reference to `dvdcss_open'
6.cpp:(.text+0x89f): undefined reference to `dvdcss_is_scrambled'
6.cpp:(.text+0xa10): undefined reference to `dvdcss_seek'
6.cpp:(.text+0xa29): undefined reference to `dvdcss_error'
6.cpp:(.text+0xc41): undefined reference to `dvdcss_seek'
6.cpp:(.text+0xc56): undefined reference to `dvdcss_error'
6.cpp:(.text+0xcc3): undefined reference to `dvdcss_read'
collect2: ld returned 1 exit status
i.e. same error. doesn't want to compile statically.
unsure what the problem is.
spotter
1st November 2010, 21:24
from irc
"spotter: your libraries should be listed after your source file and in order of dependency"
try
g++ 6.cpp -I/usr/include/libdvdcss -ldvdcss -ludf -liso9660 -lcdio -lm
works w/ --static for me now.
qyot27
1st November 2010, 23:23
Thanks, got it figured out now.
With that pre-made environment (and the instructions I laid about about how I got libdvdcss and libcdio compiled):
g++ -static decrypter-v7.cpp -I/local/include -L/local/lib -ldvdcss -ludf -liso9660 -lcdio -lm -liconv
Compiles successfully. Now I have to see about getting lsdvd compiled. Or at least find an equivalent for Windows.
spotter
1st November 2010, 23:53
I bet if you run vlc to play the disk it will get authenticated as well. (I sometimes did that for disc's lsdvd would fail on)
if ddrescue throws lots of fits of unreadable sectors (basically never gets up to speed, because keeps hitting bad sectors) then it wasn't authenticated, but if it reads w/o a problem (most TV shows for instance don't have unreadable sectors I've found besides for abc shows), then you can drag/drop the iso onto vlc (vlc will work fine w/ the scrambled sectors iso). my program can then be run on it to descramble it and try it w/ a mounting program.
qyot27
2nd November 2010, 00:45
That actually requires playing a title in VLC, though, right?
I'm really not sure how ddrescue is supposed to interact, actually. After loading the disc with VLC (and even playing a title), running ddrescue with the command earlier, amended slightly for Windows (ddrescue -v -b 2048 -d E:/ image.iso image.log), it registers in the Petabytes and ipos and opos cycle without writing anything. I have to stop it prematurely.
ddrescue -v -b 2048 -d E:/ image.iso
cygwin warning:
MS-DOS style path detected: E:/
Preferred POSIX equivalent is: /cygdrive/e
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
About to copy 9223 PBytes from E:/ to image.iso
Starting positions: infile = 0 B, outfile = 0 B
Copy block size: 32 hard blocks
Hard block size: 2048 bytes
Max_retries: 0
Direct: yes Sparse: no Split: yes Truncate: no
Press Ctrl-C to interrupt
rescued: 0 B, errsize: 9223 PB, current rate: 0 B/s
ipos: 68715 MB, errors: 1, average rate: 0 B/s
opos: 68715 MB, time from last successful read: 23 s
Splitting failed blocks...
Interrupted by user
The disc in question (Toradora! Volume 1 Disc 1, replacement) isn't one with any weird obfuscation techniques or damaged sectors. MPC and SmartRipper both recognize it as having CSS, though.
spotter
2nd November 2010, 01:26
1) I'd guess you don't have to play a title as usually even the menus have css scrambled sectors.
2) e: is a file system to cygwin. need to be the raw block device.
from http://www.cygwin.com/cygwin-ug-net/using-specialnames.html
it appears as if it be /dev/sr0,1....
qyot27
2nd November 2010, 04:06
Ok, /dev/scd1 appears to work. It's copying now so I'll see how all this turns out after it's done.
Does VLC have to remain open during the ddrescue operation, or is that safe to close after it sees the disc?
spotter
2nd November 2010, 04:10
good luck, I'd make a copy of the ISO with scrambled sectors before you do anything with it, as if my program is buggy, the ddrescue part is very time consuming so a pain to have to redo.
qyot27
2nd November 2010, 04:54
Well, didn't actually seem to take much longer than an average disc read, just 17min 15sec if I go by the created and modified timestamps on the ISO. On this computer I'm accustomed to long wait times anyway.
In any case, the decrypter gave an error this time (the output from ddrescue really is named 'image.iso'):
C:\>isodecrypter.exe image.iso
failed to open input/output file
C:\>
The .exe and .iso are in the same folder, so it should be seeing it (and specifying the full path to the .iso gave the same error). I don't think there's anything the matter with the ISO, as VLC can read it sans-scrambling, while MPC and MPC-HC clearly show that it is still there in the stream.
spotter
2nd November 2010, 04:59
hmm. let me add some more debugging output.
replace the printf with a perror
perror("failed to open input/output file");
that should give a printout on why open() failed.
spotter
2nd November 2010, 05:42
the code should be fairly straight forward, you can try playing around w/ a simple C program to try and open the file to see what goes wrong. my only possible guess at this point, spaces in the filename? edit: though obviously incorrect as your example shows.
spotter
2nd November 2010, 16:22
building it myself with mingw. first issue, last release of libcdio doesn't work with it, using git repo.
spotter
2nd November 2010, 16:58
pretty sure now it has to do with the large size of the file.
spotter
2nd November 2010, 17:11
100% positive this problem has to do w/ large file size, seems to be an issue w/ mingw see lots of other references for issues with files 4GB or larger.
tried it on an < 4GB iso and it "worked" (i.e. got passed open() call), but failed do to me detecting a short read and not handling that situation yet. never had that occur on linux will play with it more tonight.
spotter
2nd November 2010, 19:07
assumption is the problem is in my code, as both libcdio's and dvdcss's open calls work fine.
JohnAStebbins
2nd November 2010, 19:29
mingw doesn't support large file sizes well. HandBrake has been using the following patch to make libdvdread work with large iso images.
diff -Naur libdvdread.orig/src/dvd_input.h libdvdread/src/dvd_input.h
--- libdvdread.orig/src/dvd_input.h 2008-10-03 13:11:30.000000000 -0700
+++ libdvdread/src/dvd_input.h 2009-04-23 13:47:04.000000000 -0700
@@ -29,6 +29,24 @@
#define DVDINPUT_READ_DECRYPT (1 << 0)
+#if defined( __MINGW32__ )
+# undef lseek
+# define lseek _lseeki64
+# undef fseeko
+# define fseeko fseeko64
+# undef ftello
+# define ftello ftello64
+# define flockfile(...)
+# define funlockfile(...)
+# define getc_unlocked getc
+# undef off_t
+# define off_t off64_t
+# undef stat
+# define stat _stati64
+# define fstat _fstati64
+# define wstat _wstati64
+#endif
+
typedef struct dvd_input_s *dvd_input_t;
/**
spotter
2nd November 2010, 19:40
don't see why any of that would impact open() actually failing. what I do on the fd after the fact, yea, but on the function itself?
I'm really confused. libcdio and dvdcss work fine and I do (from what I can tell) the exasct same thing. I wish I had strace available.
spotter
2nd November 2010, 19:59
so I stuck in a spotter_open into libdvdcss
int spotter_open(char const *file)
{
return open(file, O_RDWR | O_BINARY);
}
and this seemed to get passed that problem.
but not a real solution.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.