struct iso_primary_descriptor * cdfs_get_iso_info(struct super_block *sb, int track_no){ cd * this_cd = cdfs_info(sb); struct buffer_head * bh; int block; struct iso_primary_descriptor * iso_info = kmalloc(sizeof(struct iso_primary_descriptor), GFP_KERNEL); if (!iso_info) { printk("kmalloc failed\n"); return NULL; } block = this_cd->track[track_no].start_lba+16; /* ISO info at sector 16 */ PRINT("Retrieving info for data track %d: block %d\n", track_no, block); if (!(bh = bread(sb->s_dev, block, CD_FRAMESIZE))) { PRINT("FAILED\n"); return NULL; } if (!strncmp(bh->b_data+1,"CD001",5)) { memcpy(iso_info, bh->b_data, sizeof(struct iso_primary_descriptor)); /* ISO session */ } else { kfree(iso_info); iso_info=NULL; /* DATA, but no ISO */ } brelse(bh); return iso_info; }
static int cdfs_statfs(struct super_block *sb, struct statfs *buf) { cd * this_cd = cdfs_info(sb); #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) static int cdfs_statfs(struct dentry *d, struct kstatfs *buf) { cd * this_cd = cdfs_info(d->d_sb); #else static int cdfs_statfs(struct super_block *sb, struct kstatfs *buf) { cd * this_cd = cdfs_info(sb); #endif #endif PRINT("rmfs_statfs\n"); buf->f_type = CDFS_MAGIC; buf->f_bsize = CD_FRAMESIZE; buf->f_blocks = this_cd->size/CD_FRAMESIZE; buf->f_namelen = CDFS_MAXFN; buf->f_files = this_cd->tracks; return 0; }
static int cdfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; int i; cd * this_cd = cdfs_info(inode->i_sb); PRINT("cdfs_readdir ino=%ld f_pos=%u\n", inode->i_ino, (int)filp->f_pos); for(i=filp->f_pos; i<T2I(this_cd->tracks); i++) { if (filldir(dirent, this_cd->track[i].name, strlen(this_cd->track[i].name), 0, i, DT_UNKNOWN) < 0) return 0; filp->f_pos++; } return 1; }
static void cdfs_umount(struct super_block *sb) { int t; cd * this_cd = cdfs_info(sb); PRINT("cdfs_umount\n"); for (t=0; t<=this_cd->tracks; t++) if ((this_cd->track[T2I(t)].type == DATA) && this_cd->track[T2I(t)].iso_info) kfree(this_cd->track[T2I(t)].iso_info); // Free & invalidate cache kfree(this_cd->cache); this_cd->cache_sector = -CACHE_SIZE; // Remove /proc entry cdfs_proc_cd = NULL; kfree(cdfs_info(sb)); #ifdef OLD_KERNEL MOD_DEC_USE_COUNT; #endif }
unsigned cdfs_data_bmap(struct super_block * sb, int inode, int block) { int result; cd * this_cd = cdfs_info(sb); track_info * this_track = &(this_cd->track[inode]); int session; printk("cddata.c:cdfs_data_bmap():AnyoneUseThis???\n"); if ((this_track->type == BOOT) || (this_track->type == HFS) || (block<20) || this_cd->single) /* 20 sectors seems to be OK for ISO */ result = this_track->start_lba+block; else { /* ISO past sector 18 */ result = block; /* post processing */ for (session=0; session < this_cd->nr_iso_sessions; session++) { PRINT("this is sector %d, checking session %d: %d-%d\n", result, session, this_cd->lba_iso_sessions[session].start, this_cd->lba_iso_sessions[session].stop); if ((this_cd->lba_iso_sessions[session].start<=result) && (result<=this_cd->lba_iso_sessions[session].stop)) goto exit; /* OK, reading from an ISO session */ if ((this_cd->lba_iso_sessions[session].stop<result) && (result<this_cd->lba_iso_sessions[session].start)) { result = 0; goto exit; /* not OK, reading between two ISO sessions => we force 0*/ } } /* We only get here if we read past the last session => we force 0 */ result = 0; } exit: //PRINT("BMAP('%s', block %d) => sector %d\n", this_track->name, block, result); return result; }
void cdfs_check_bootable(struct super_block *sb){ struct buffer_head * bh1, * bh2, *bh3; cd * this_cd = cdfs_info(sb); int boottrack; int no_bootimage=0; int sectionoffset=0; if (!(bh1 = bread(sb->s_dev, 17, CD_FRAMESIZE))) return; /* sector 17 is unreadable */ else if (!strncmp(bh1->b_data+7, "EL TORITO", 9)) { PRINT("BOOT, catalog at %d\n", *(unsigned int*)(bh1->b_data+71)); bh2 = bread(sb->s_dev, *(unsigned int*)(bh1->b_data+71), CD_FRAMESIZE); PRINT("Catalog:\n\tHeader ID=%d, Platform ID=%d, Developer ID=%s\n", *(unsigned char*)(bh2->b_data), *(unsigned char*)(bh2->b_data+1), bh2->b_data+4); do { this_cd->tracks++; boottrack = this_cd->tracks+2; PRINT("\tInitial/Default entry: %x Bootable, media: %d\n", *(unsigned char*)(bh2->b_data+32+0+sectionoffset), *(unsigned char*)(bh2->b_data+32+1+sectionoffset) & 15); PRINT("\tSector count: %d, Load LBA: %d\n", *(unsigned short*)(bh2->b_data+32+6+sectionoffset), *(unsigned int*)(bh2->b_data+32+8+sectionoffset)); this_cd->track[boottrack].type = BOOT; this_cd->track[boottrack].start_lba = *(unsigned int*) (bh2->b_data+32+8+sectionoffset); this_cd->track[boottrack].size = cdfs_bootmedia[ *(unsigned char*)(bh2->b_data+32+1+sectionoffset) & 15].size; if (!this_cd->track[boottrack].size) this_cd->track[boottrack].size = *(unsigned short*) (bh2->b_data+32+6+sectionoffset) * CD_FRAMESIZE ; this_cd->track[boottrack].stop_lba = this_cd->track[boottrack]. start_lba + this_cd->track[boottrack].size/CD_FRAMESIZE -1; this_cd->track[boottrack].time = 0; sprintf(this_cd->track[boottrack].name,"boot.image_%d",no_bootimage); strncpy(this_cd->track[boottrack].bootID, bh2->b_data+4+sectionoffset,24); /* 27?? */ this_cd->track[boottrack].bootID[24]=0; /* get first sector from boot image */ bh3=bread(sb->s_dev, this_cd->track[boottrack].start_lba, CD_FRAMESIZE); if ((*(unsigned char*)(bh3->b_data+511)=0xAA) && (*(unsigned char*)(bh3->b_data+512)=0x55)) { strcat(this_cd->track[boottrack].bootID, "\n\tType: x86 boot sector, "); if (!strncmp(bh3->b_data+2, "LILO", 4)) strcat(this_cd->track[boottrack].bootID, "LILO boot/chain loader with "); else if (!strncmp(bh3->b_data+495, "LDLINUX", 7)) { strncat(this_cd->track[boottrack].bootID, bh3->b_data+495, 12); strcat(this_cd->track[boottrack].bootID, " boot loader with "); } if (*(unsigned short*)(bh3->b_data+0x438)==0xEF53) strcat(this_cd->track[boottrack].bootID, "Linux/i386 ext2 filesystem\n"); else /* FAT */ strncat(this_cd->track[boottrack].bootID, bh3->b_data+54, 8); /* FAT type */ } brelse(bh3); if (sectionoffset==0) sectionoffset=0x60; sectionoffset=sectionoffset+0x20; } while (*(unsigned char*)(bh2->b_data+0x42)>no_bootimage++); brelse(bh2); } brelse(bh1); }
static void kcdfsd_process_request(void){ struct list_head * tmp; struct kcdfsd_req * req; struct page * page; struct inode * inode; unsigned request; while (!list_empty (&kcdfsd_req_list)){ /* Grab the next entry from the beginning of the list */ tmp = kcdfsd_req_list.next; req = list_entry (tmp, struct kcdfsd_req, req_list); list_del (tmp); page = req->page; inode = req->dentry->d_inode; request = req->request_type; if (!PageLocked(page)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)) PAGE_BUG(page); #else BUG(); #endif switch (request){ case CDDA_REQUEST: case CDDA_RAW_REQUEST: { cd *this_cd = cdfs_info (inode->i_sb); char *p; track_info *this_track = &(this_cd->track[inode->i_ino]); cdfs_cdda_file_read (inode, p = (char *) kmap (page), 1 << PAGE_CACHE_SHIFT, (page->index << PAGE_CACHE_SHIFT) + ((this_track->avi) ? this_track-> avi_offset : 0), (request == CDDA_RAW_REQUEST)); if ((this_track->avi) && (this_track->avi_swab)){ int k; for (k=0; k<(1 << PAGE_CACHE_SHIFT); k+=2){ char c; c = p[k]; p[k] = p[k + 1]; p[k + 1] = c; } } } break; case CDXA_REQUEST: cdfs_copy_from_cdXA(inode->i_sb, inode->i_ino, page->index << PAGE_CACHE_SHIFT, (page->index + 1) << PAGE_CACHE_SHIFT, (char *)kmap(page)); break; case CDDATA_REQUEST: cdfs_copy_from_cddata(inode->i_sb, inode->i_ino, page->index << PAGE_CACHE_SHIFT, (page->index + 1) << PAGE_CACHE_SHIFT, (char *)kmap(page)); break; case CDHFS_REQUEST: cdfs_copy_from_cdhfs(inode->i_sb, inode->i_ino, page->index << PAGE_CACHE_SHIFT, (page->index + 1) << PAGE_CACHE_SHIFT, (char *)kmap(page)); break; } SetPageUptodate (page); kunmap (page); unlock_page (page); kfree (req); } }
int cdfs_copy_from_cd(struct super_block * sb, int inode, unsigned int start, unsigned int stop, char * buf) { int start_sector, start_byte, stop_sector, stop_byte, sector; int status=0; int bad_sector_no_read=0; struct cdrom_read_audio cdda; unsigned int read_size=CD_FRAMESIZE_RAW_Q; //CD_FRAMESIZE_RAW_Q=2352+16=2368 cd * this_cd = cdfs_info(sb); //unsigned start_lba=this_cd->track[inode].start_lba; unsigned start_lba=this_cd->track[inode].start_lba; char * temp, * temp2; char * temp_start; int temp_length; start_lba=this_cd->track[inode].start_lba; /* cache */ /* char * temp, * temp2; char * temp_start; int temp_length; */ temp = this_cd->cache; start_sector = start/read_size; start_byte = start%read_size; stop_sector = stop/read_size; stop_byte = stop%read_size; start_sector += start_lba; stop_sector += start_lba; if (!stop_byte) { /* empty frame */ stop_sector -= 1; stop_byte = CD_FRAMESIZE_RAW_Q; //CD_FRAMESIZE_RAW_Q=2352+16=2368 } cdda.addr_format = CDROM_LBA; //Using CDROM_LBA format cdda.nframes = CACHE_SIZE; cdda.buf = temp; // testen of eindadres>CD for (sector=start_sector; sector<=stop_sector; sector++) { PRINT("cache holds [%d-%d], we want sector=%d\n", this_cd->cache_sector, this_cd->cache_sector+CACHE_SIZE-1, sector); if (!((this_cd->cache_sector<=sector) && (sector<this_cd->cache_sector+CACHE_SIZE))) { this_cd->cache_sector = cdda.addr.lba = sector; if((this_cd->bad_sector<5000000) &&((this_cd->bad_sector)<=((unsigned long long)cdda.addr.lba)) &&(((unsigned long long)cdda.addr.lba)<(this_cd->bad_sector+70))) bad_sector_no_read=1; if(bad_sector_no_read) { status=-5; PRINT("<vcd module> Bad sector %d in ACD fail!!! status=%d bad_sector=%lld\n", cdda.addr.lba, status,this_cd->bad_sector); return status; } else { PRINT("<vcd module> Reading sector %d in ACD ST \n",cdda.addr.lba); status = cdfs_read_cd(sb, (&cdda), cdda.buf); } if (status) { printk("<vcd module> Reading sector %d in ACD SP fail!!! status=%d\n", cdda.addr.lba, status); this_cd->bad_sector=cdda.addr.lba; return status; } /* else PRINT("<vcd module> Reading sector %d in ACD SP OK status=%d\n", cdda.addr.lba, status); */ } temp2=temp+(sector-this_cd->cache_sector)*CD_FRAMESIZE_RAW_Q; //CD_FRAMESIZE_RAW_Q=2352+16=2368 if (sector==start_sector) { temp_start = temp2+start_byte; if (sector!=stop_sector) { temp_length = read_size-start_byte; } else { temp_length = stop_byte-start_byte; } } else if (sector==stop_sector) { temp_start = temp2; temp_length = stop_byte; } else { temp_start = temp2; temp_length = read_size; } memcpy(buf, (char*)temp_start, temp_length); buf += temp_length; } return status; }
void cdfs_copy_from_cd(struct super_block * sb, int inode, unsigned int start, unsigned int stop, char * buf){ int start_sector, start_byte, stop_sector, stop_byte, sector; int status; struct cdrom_read_audio cdda; unsigned int read_size=CD_FRAMESIZE_RAW; cd * this_cd = cdfs_info(sb); unsigned start_lba=this_cd->track[inode].start_lba; /* cache */ char * temp, * temp2; char * temp_start; int temp_length; PRINT("copy_from_cd(%x, %d, %d, %d, %x)\n", sb, inode, start, stop, buf); temp = this_cd->cache; start_sector = start/read_size; start_byte = start%read_size; stop_sector = stop/read_size; stop_byte = stop%read_size; start_sector += start_lba; stop_sector += start_lba; if (!stop_byte) { /* empty frame */ stop_sector -= 1; stop_byte = CD_FRAMESIZE_RAW; } PRINT("%d[%d-%d] -> 0x%x...0x%x ... (%d,%d),(%d,%d)\n", inode, start, stop, (int)buf, (int)buf+stop-start, start_sector,start_byte,stop_sector,stop_byte); cdda.addr_format = CDROM_LBA; cdda.nframes = CACHE_SIZE; cdda.buf = temp; // testen of eindadres>CD for (sector=start_sector; sector<=stop_sector; sector++){ PRINT("cache holds [%d-%d], we want sector=%d\n", this_cd->cache_sector, this_cd->cache_sector+CACHE_SIZE-1, sector); if (!((this_cd->cache_sector<=sector) && (sector<this_cd->cache_sector+CACHE_SIZE))) { PRINT("reading sector %d from CD\n", sector); this_cd->cache_sector = cdda.addr.lba = sector; status = cdfs_ioctl(sb, CDROMREADAUDIO, (unsigned long)&cdda); if (status) { printk("copy_from_cd(%d) ioctl failed: %d\n", cdda.addr.lba, status); return; } } else { PRINT("getting sector %d from cache\n", sector); } temp2=temp+(sector-this_cd->cache_sector)*CD_FRAMESIZE_RAW; if (sector==start_sector) { temp_start = temp2+start_byte; if (sector!=stop_sector) temp_length = read_size-start_byte; else temp_length = stop_byte-start_byte; } else if (sector==stop_sector) { temp_start = temp2; temp_length = stop_byte; } else { temp_start = temp2; temp_length = read_size; } PRINT("memcpy(0x%x, %x, %d)\n",(int)buf, (int)temp_start, temp_length); memcpy(buf, (char*)temp_start, temp_length); buf += temp_length; } }
int cdfs_get_hfs_info(struct super_block *sb, unsigned track){ cd * this_cd = cdfs_info(sb); struct buffer_head * bh; struct new_pmap * pmapp; int thistrack; unsigned start_lba=this_cd->track[track].start_lba; /* We only check for the first partition. */ PRINT("Retrieving HFS info: reading frame %d from track %d\n", start_lba, track); if (!(bh = bread(sb->s_dev, start_lba+0, CD_FRAMESIZE ))) { /* read 2048 bytes */ PRINT("FAILED\n"); return -1; } pmapp=(struct new_pmap*)(bh->b_data+1024); /* 3e blok van 512 bytes */ if ( !strncmp((char*)&(pmapp->pmPartType),"Apple_HFS",9) ) { this_cd->tracks++; thistrack = this_cd->tracks+2; this_cd->track[thistrack].type = HFS; this_cd->track[thistrack].start_lba = ntohl(*(unsigned*)(pmapp->pmPyPartStart))/4; this_cd->track[thistrack].hfs_offset = ntohl(*(unsigned*)(pmapp->pmPyPartStart))-4*this_cd->track[thistrack].start_lba; this_cd->track[thistrack].size = ntohl(*(unsigned*)(pmapp->pmPartBlkCnt))*512; this_cd->track[thistrack].stop_lba = this_cd->track[thistrack].start_lba + this_cd->track[thistrack].size/2048; this_cd->track[thistrack].time = 0; strcpy(this_cd->track[thistrack].name,"apple.hfs"); strcpy(this_cd->track[thistrack].bootID,(char*)&pmapp->pmPartName); this_cd->track[thistrack].start_lba += start_lba; this_cd->track[thistrack].stop_lba += start_lba; PRINT("Found HFS: %s, starts at %d (offset=%d), stops at %d\n", &pmapp->pmPartName, this_cd->track[thistrack].start_lba, this_cd->track[thistrack].hfs_offset, this_cd->track[thistrack].stop_lba); } else { /* try next partition */ pmapp=(struct new_pmap*)(bh->b_data+1024+512); /* 4e blok van 512 bytes */ if ( !strncmp((char*)&(pmapp->pmPartType),"Apple_HFS",9) ) { this_cd->tracks++; thistrack = this_cd->tracks+2; this_cd->track[thistrack].type = HFS; this_cd->track[thistrack].start_lba = ntohl(*(unsigned*)(pmapp->pmPyPartStart))/4; this_cd->track[thistrack].hfs_offset = ntohl(*(unsigned*)(pmapp->pmPyPartStart))-4*this_cd->track[thistrack].start_lba; this_cd->track[thistrack].size = ntohl(*(unsigned*)(pmapp->pmPartBlkCnt))*512; this_cd->track[thistrack].stop_lba = this_cd->track[thistrack].start_lba + this_cd->track[thistrack].size/2048; this_cd->track[thistrack].time = 0; strcpy(this_cd->track[thistrack].name,"apple.hfs"); strcpy(this_cd->track[thistrack].bootID,(char*)&pmapp->pmPartName); this_cd->track[thistrack].start_lba += start_lba; this_cd->track[thistrack].stop_lba += start_lba; PRINT("Found HFS: %s, starts at %d (offset=%d), stops at %d\n", &pmapp->pmPartName, this_cd->track[thistrack].start_lba, this_cd->track[thistrack].hfs_offset, this_cd->track[thistrack].stop_lba); } } brelse(bh); return 0; }
void cdfs_copy_from_cdhfs(struct super_block * sb, int inode, unsigned int start, unsigned int stop, char * buf){ int start_sector, start_byte, stop_sector, stop_byte, sector; unsigned int read_size=2048; cd * this_cd = cdfs_info(sb); struct buffer_head * bh; unsigned start_lba=this_cd->track[inode].start_lba; char * temp; char * temp_start; int temp_length; char * buf_ptr; PRINT("start_lba=%d\n", start_lba); /* recalculate start and stop in bytes from the real start of the CD !! */ start += start_lba*2048+ this_cd->track[inode].hfs_offset*512; stop += start_lba*2048+ this_cd->track[inode].hfs_offset*512; start_sector = start/read_size; start_byte = start - start_sector*read_size; stop_sector = stop/read_size; stop_byte = stop - stop_sector*read_size; if (!stop_byte) { stop_sector--; stop_byte=2048; } PRINT("%d[%d-%d] -> 0x%x...0x%x ... (%d,%d),(%d,%d)\n", inode, start, stop, (int)buf, (int)buf+stop-start, start_sector,start_byte,stop_sector,stop_byte); buf_ptr=buf; for (sector=start_sector; sector<=stop_sector; sector++){ PRINT("reading sector %d, lba=%d\n", sector, start_lba); if (!(bh = bread(sb->s_dev, sector, CD_FRAMESIZE))) { /* read 2048 bytes */ PRINT("FAILED\n"); return; } temp = bh->b_data; if (sector==start_sector) { temp_start = temp+start_byte; if (sector!=stop_sector) temp_length = read_size-start_byte; else temp_length = stop_byte-start_byte; } else if (sector==stop_sector) { temp_start = temp; temp_length = stop_byte; } else { temp_start = temp; temp_length = read_size; } PRINT("memcpy(0x%x, %x, %d)\n", (int)buf_ptr, (int)temp_start, temp_length); memcpy(buf_ptr, (char*)temp_start, temp_length); brelse(bh); buf_ptr+=temp_length; } };
static struct dentry * cdfs_lookup(struct inode *dir, struct dentry *dentry){ #else static struct dentry * cdfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ #endif struct inode * inode; int i; cd * this_cd = cdfs_info(dir->i_sb); PRINT("cdfs_lookup %s ino=%ld \n", dentry->d_name.name, dir->i_ino); for(i=0; i<T2I(this_cd->tracks); i++) if (!(strcmp(this_cd->track[i].name, dentry->d_name.name))) { goto found; } return ERR_PTR(-ENOENT); /* Use goto and read inode with iget()/cdfs_iget() */ /* Thanks to David Howells for patch and Master class in his mail */ found: #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) inode = cdfs_iget(dir->i_sb, i); if (IS_ERR(inode)) return ERR_CAST(inode); #else inode = iget(dir->i_sb, i); if (!inode) return ERR_PTR(-ENOMEM); #endif d_add(dentry, inode); return NULL; } /***************************************************************************/ static struct file_operations cdfs_dir_operations = { .read = generic_read_dir, .readdir = cdfs_readdir, }; static struct inode_operations cdfs_inode_operations = { .lookup = cdfs_lookup }; /**************************************************************************/ static void cdfs_read_inode(struct inode *i) { cd * this_cd = cdfs_info(i->i_sb); PRINT("this_cd = 0x%x\n", (unsigned)this_cd); PRINT("read inode %ld\n", i->i_ino); i->i_uid = this_cd->uid; i->i_gid = this_cd->gid; i->i_nlink = 1; i->i_op = &cdfs_inode_operations; i->i_fop = NULL; i->i_data.a_ops = NULL; if (i->i_ino <= 2) { /* . and .. */ i->i_size = 0; /* Uuugh ?? */ i->i_mtime = i->i_atime = i->i_ctime = CURRENT_TIME; i->i_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; i->i_fop = &cdfs_dir_operations; } else { /* file */ i->i_size = this_cd->track[i->i_ino].size; #ifdef OLD_KERNEL i->i_mtime = i->i_atime = i->i_ctime = this_cd->track[i->i_ino].time; #else i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = this_cd->track[i->i_ino].time; i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0; #endif i->i_mode = this_cd->mode; if ((this_cd->track[i->i_ino].type==DATA) && this_cd->track[i->i_ino].iso_size) { i->i_fop = &cdfs_cddata_file_operations; i->i_data.a_ops = &cdfs_cddata_aops; } else if (this_cd->track[i->i_ino].type==AUDIO) { i->i_fop = &cdfs_cdda_file_operations; if (this_cd->raw_audio) i->i_data.a_ops = &cdfs_cdda_raw_aops; else i->i_data.a_ops = &cdfs_cdda_aops; } else if (this_cd->track[i->i_ino].type==BOOT) { i->i_fop = &cdfs_cddata_file_operations; i->i_data.a_ops = &cdfs_cddata_aops; } else if (this_cd->track[i->i_ino].type==HFS) { if (this_cd->track[i->i_ino].hfs_offset) { i->i_fop = &cdfs_cdhfs_file_operations; /* Bummer, this partition isn't properly aligned... */ i->i_data.a_ops = &cdfs_cdhfs_aops; } else { i->i_fop = &cdfs_cddata_file_operations; i->i_data.a_ops = &cdfs_cddata_aops; } } else { i->i_fop = &cdfs_cdXA_file_operations; i->i_data.a_ops = &cdfs_cdXA_aops; } } }
static struct super_block * cdfs_mount(struct super_block *sb, void *data, int silent){ kdev_t dev = sb->s_dev; int i, j, t; struct cdrom_tochdr hdr; #else static int cdfs_fill_super(struct super_block *sb, void *data, int silent){ int i, t; #endif struct cdrom_tocentry entry; int no_audio=0, no_data=0; cd * this_cd; struct inode *retinode; PRINT("cdfs_mount\n"); #ifdef OLD_KERNEL MOD_INC_USE_COUNT; set_blocksize(dev, CD_FRAMESIZE); // voor bread met ide-cd #else sb_set_blocksize(sb, CD_FRAMESIZE); // voor bread met ide-cd #endif sb->s_blocksize = CD_FRAMESIZE; sb->s_blocksize_bits = 11; if (!(this_cd = cdfs_info(sb) = kmalloc(sizeof(cd), GFP_KERNEL))){ #ifdef OLD_KERNEL MOD_DEC_USE_COUNT; return NULL; #else return -ENOMEM; #endif } this_cd->mode = MODE; this_cd->gid = GID; this_cd->uid = UID; this_cd->single = FALSE; this_cd->raw_audio = 0; this_cd->toc_scsi = FALSE; // Initialize cache for maximum sector size if (!(this_cd->cache = kmalloc(CD_FRAMESIZE_RAWER*CACHE_SIZE, GFP_KERNEL))) { #ifdef OLD_KERNEL MOD_DEC_USE_COUNT; return NULL; #else kfree(cdfs_info(sb)); return -ENOMEM; #endif } // Cache is still invalid this_cd->cache_sector = -CACHE_SIZE; cdfs_parse_options((char *) data, this_cd); /* Populate CD info with '.' and '..' */ strcpy(this_cd->track[1].name, "."); this_cd->track[1].start_lba=0; strcpy(this_cd->track[2].name, ".."); this_cd->track[2].start_lba=0; this_cd->nr_iso_sessions = 0; this_cd->size = 0; if (this_cd->toc_scsi){ if (cdfs_toc_read_full(sb)){ printk("TOC read failed\n"); #ifdef OLD_KERNEL MOD_DEC_USE_COUNT; return NULL; #else goto invalid; #endif } } else { //if (cdfs_ioctl(sb, CDROMREADTOCHDR, (unsigned long)&hdr)){ if (cdfs_toc_read(sb)){ printk("cdfs_toc_read failed\n"); #ifdef OLD_KERNEL MOD_DEC_USE_COUNT; return NULL; #else goto invalid; #endif } } PRINT("CD contains %d tracks\n", this_cd->tracks); /* Collect track info */ entry.cdte_format = CDROM_LBA; for (t=this_cd->tracks; t>=0; t--) { i = T2I(t); // j = this_cd->tracks-i; // entry.cdte_track = (t==this_cd->tracks) ? CDROM_LEADOUT : t+1; // PRINT("Read track %d/%d/%d\n", entry.cdte_track, t, i); // if (cdfs_ioctl(sb, CDROMREADTOCENTRY, (unsigned long)&entry)){ // printk("ioctl(CDROMREADTOCENTRY) failed\n"); // MOD_DEC_USE_COUNT; // return NULL; // } // this_cd->track[i].start_lba = entry.cdte_addr.lba; // this_cd->track[i].stop_lba = this_cd->track[i+1].start_lba - 1; this_cd->track[i].track_size = this_cd->track[i+1].start_lba - this_cd->track[i].start_lba; /* in sectors! */ PRINT("Start[%d]: %d\n", i, this_cd->track[i].start_lba); if (t!=this_cd->tracks) { /* all tracks but the LEADOUT */ if (this_cd->track[i].type==DATA) { //int track=i; no_data++; this_cd->track[i].iso_info = cdfs_get_iso_info(sb, i); if (this_cd->track[i].iso_info) { this_cd->track[i].time = cdfs_constructtime((char*)&(this_cd->track[i].iso_info->creation_date)); this_cd->track[i].iso_size = cdfs_constructsize((char*)&(this_cd->track[i].iso_info->volume_space_size)) * CD_FRAMESIZE; if (!this_cd->single) this_cd->track[i].iso_size += this_cd->track[i].start_lba * CD_FRAMESIZE; this_cd->track[i].track_size *= CD_FRAMESIZE; this_cd->track[i].size = this_cd->track[i+1].start_lba * CD_FRAMESIZE; sprintf(this_cd->track[i].name, this_cd->single ? DATA_NAME_SINGLE : DATA_NAME_ISO, t+1); this_cd->lba_iso_sessions[this_cd->nr_iso_sessions].start = this_cd->track[i].start_lba; this_cd->lba_iso_sessions[this_cd->nr_iso_sessions].stop = this_cd->track[i].iso_size/CD_FRAMESIZE; this_cd->nr_iso_sessions++; cdfs_get_hfs_info(sb, i); // possibly also a HFS } else { // DATA, but no ISO -> either HFS or VideoCD if (cdfs_get_hfs_info(sb, i)==-1){ printk("CHECKING VIDEOCD!!\n"); cdfs_get_XA_info(sb, i); this_cd->track[i].time = 0; this_cd->track[i].iso_size = 0; this_cd->track[i].track_size = (this_cd->track[i].track_size-1) * this_cd->track[i].xa_data_size; this_cd->track[i].size = this_cd->track[i].track_size; sprintf(this_cd->track[i].name, DATA_NAME_VCD, no_data); } else { // HFS, no ISO, no VideoCD -> remove track this_cd->track[i].iso_info = NULL; this_cd->track[i].type = 0; } } } else { no_audio++; this_cd->track[i].iso_info = NULL; this_cd->track[i].type = AUDIO; this_cd->track[i].time = get_seconds(); this_cd->track[i].iso_size = 0; this_cd->track[i].track_size = this_cd->track[i].track_size * CD_FRAMESIZE_RAW + ((this_cd->raw_audio==0)?WAV_HEADER_SIZE:0); this_cd->track[i].size = this_cd->track[i].track_size; this_cd->track[i].avi = 0; sprintf(this_cd->track[i].name, (this_cd->raw_audio)? RAW_AUDIO_NAME:AUDIO_NAME, t+1); if (this_cd->raw_audio) { /* read the first sector. */ struct cdrom_read_audio cdda; int status,k,j,prevk=0; char* buf; buf=kmalloc(CD_FRAMESIZE_RAW*2,GFP_KERNEL); if(buf==NULL) { printk(FSNAME ": kmalloc failed in root.c !\n"); return(-ENOMEM); } for (j=0;j<10;j++) { cdda.addr_format = CDROM_LBA; cdda.nframes = 1; cdda.buf = buf+CD_FRAMESIZE_RAW; cdda.addr.lba = this_cd->track[i].start_lba+j; status = cdfs_ioctl(sb,CDROMREADAUDIO,(unsigned long)&cdda); if (status) { printk("cdfs_ioctl(CDROMREADAUDIO,%d) ioctl failed: %d\n", cdda.addr.lba, status); goto out; } /* search the first non-zero byte */ for (k=0;k<CD_FRAMESIZE_RAW;k++) if (buf[k+CD_FRAMESIZE_RAW]) break; if (k<=CD_FRAMESIZE_RAW-4) break; prevk=k; if (k<CD_FRAMESIZE_RAW) for (k=0;k<CD_FRAMESIZE_RAW;k++) buf[k]=buf[k+CD_FRAMESIZE_RAW]; } if (j==10) goto out; if ((j!=0)&&(prevk!=CD_FRAMESIZE_RAW)) { k=prevk; j--; } else k+=CD_FRAMESIZE_RAW; this_cd->track[i].avi_offset = j*CD_FRAMESIZE_RAW+k-CD_FRAMESIZE_RAW; if ((buf[k]=='R')&&(buf[k+1]=='I')&& (buf[k+2]=='F')&&(buf[k+3]=='F')) { this_cd->track[i].avi = 1; this_cd->track[i].avi_swab = 0; } else if ((buf[k]=='I')&&(buf[k+1]=='R')&& (buf[k+2]=='F')&&(buf[k+3]=='F')) { this_cd->track[i].avi = 1; this_cd->track[i].avi_swab = 1; } if (this_cd->track[i].avi) { if ((this_cd->track[i].avi_offset&1)!=0) { printk("AVI offset is not even, error\n"); this_cd->track[i].avi=0; } else { this_cd->track[i].track_size -= this_cd->track[i].avi_offset; sprintf(this_cd->track[i].name, AVI_AUDIO_NAME, t+1); } } out: kfree(buf); } } // Calculate total CD size this_cd->size += this_cd->track[i].track_size; PRINT("Track %2d: (%dB)\n", t, this_cd->track[i].size); } // else CDROM_LEADOUT } PRINT("CD ends at %d\n", this_cd->track[this_cd->tracks].start_lba); /* take care to get disc id after the toc has been read. JP, 29-12-2001 */ this_cd->discid = discid(this_cd); //////////////////////////////// /* Check if CD is bootable */ if (this_cd->track[T2I(0)].type==DATA) cdfs_check_bootable(sb); /* Check for an HFS partition in the first data track */ /*if (no_data) { i=T2I(0); while (i<T2I(this_cd->tracks)) { if (this_cd->track[i].type==DATA) break; i++; } cdfs_get_hfs_info(sb, i); } */ PRINT("%d audio tracks and %d data tracks => %dbytes\n", no_audio, no_data, this_cd->size); sb->s_magic = CDFS_MAGIC; sb->s_flags |= MS_RDONLY; sb->s_op = &cdfs_ops; /* always get inode status */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) retinode=cdfs_iget(sb, 0); #else retinode=iget(sb, 0); #endif if ( IS_ERR(retinode) ) return PTR_ERR(retinode); PRINT("retinode = %ld\n", retinode->i_ino); sb->s_root = d_alloc_root(retinode); cdfs_proc_cd = this_cd; #ifdef OLD_KERNEL return sb; #else return 0; invalid: kfree(this_cd->cache); kfree(cdfs_info(sb)); return -EINVAL; #endif }
void cdfs_copy_from_cddata(struct super_block * sb, int inode, unsigned int start, unsigned int stop, char * buf){ int start_sector, start_byte, stop_sector, stop_byte, sector; int status; cd * this_cd = cdfs_info(sb); unsigned int data_size = CD_FRAMESIZE; printk("cddata.c:cdfs_copy_from_cddata():AnyoneUseThis???\n"); start_sector = start / data_size; start_byte = start % data_size; stop_sector = stop / data_size; stop_byte = stop % data_size; if (!stop_byte) { /* empty frame */ stop_sector -= 1; stop_byte = CD_FRAMESIZE; } PRINT("%d[%d-%d] -> 0x%x...0x%x ... (%d,%d),(%d,%d)\n", inode, start, stop, (int)buf, (int)buf+stop-start, start_sector,start_byte,stop_sector,stop_byte); for (sector=start_sector; sector<=stop_sector; sector++) { unsigned lba = cdfs_data_bmap(sb, inode, sector); if (!(this_cd->cache_sector == lba)) { this_cd->cache_sector = lba; if((status = cdfs_read_rawDATA_frame(sb, lba, this_cd->cache))) { printk("copy_from_cddata(%d): ioctl failed: %d\n", lba, status); return; } } { char * copy_start; int copy_length; if (sector==start_sector) { copy_start = this_cd->cache+start_byte; if (sector!=stop_sector) copy_length = data_size-start_byte; else copy_length = stop_byte-start_byte; } else if (sector==stop_sector) { copy_start = this_cd->cache; copy_length = stop_byte; } else { copy_start = this_cd->cache; copy_length = data_size; } PRINT("memcpy(0x%x, 0x%x, %d)\n", (int)buf, (int)copy_start, copy_length); memcpy(buf, (char*)copy_start, copy_length); buf+=copy_length; } } }