diff -urN wt1-350/fs/Config.in wt1-350-cdfs-2420a/fs/Config.in --- wt1-350/fs/Config.in Fri Aug 13 18:09:56 2004 +++ wt1-350-cdfs-2420a/fs/Config.in Fri Aug 13 18:20:17 2004 @@ -37,6 +37,8 @@ define_bool CONFIG_JBD $CONFIG_EXT3_FS dep_mbool ' JBD (ext3) debugging support' CONFIG_JBD_DEBUG $CONFIG_JBD +dep_tristate 'CDFS file system support (EXPERIMENTAL)' CONFIG_CDFS_FS $CONFIG_EXPERIMENTAL + # msdos file systems tristate 'DOS FAT fs support' CONFIG_FAT_FS dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS diff -urN wt1-350/fs/Makefile wt1-350-cdfs-2420a/fs/Makefile --- wt1-350/fs/Makefile Fri Aug 13 18:09:56 2004 +++ wt1-350-cdfs-2420a/fs/Makefile Fri Aug 13 18:24:28 2004 @@ -70,6 +70,7 @@ subdir-$(CONFIG_JFS_FS) += jfs subdir-$(CONFIG_EVFS_FS) += evfs subdir-$(CONFIG_XFS_FS) += xfs +subdir-$(CONFIG_CDFS_FS) += cdfs obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o diff -urN wt1-350/fs/cdfs/Makefile wt1-350-cdfs-2420a/fs/cdfs/Makefile --- wt1-350/fs/cdfs/Makefile Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/Makefile Fri Aug 13 18:21:14 2004 @@ -0,0 +1,15 @@ +# +# Makefile for CDFS filesystem. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main Makefile... + +O_TARGET := cdfs.o + +obj-y := audio.o cdXA.o cddata.o hfs.o iso.o proc.o root.o utils.o daemon.o discid.o toc.o +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -urN wt1-350/fs/cdfs/Makefile.in wt1-350-cdfs-2420a/fs/cdfs/Makefile.in --- wt1-350/fs/cdfs/Makefile.in Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/Makefile.in Mon Apr 21 16:42:36 2003 @@ -0,0 +1,62 @@ +CC=@CC@ +moddir=@moddir@ +CONFIG_CDFS_VERSION=@CONFIG_CDFS_VERSION@ +kaversion=@kaversion@ +kversion=@kversion@ +kpatchlevel=@kpatchlevel@ +ksublevel=@ksublevel@ +kextraversion=@kextraversion@ +CONFIG_CDFS_KERNELDIR=@CONFIG_CDFS_KERNELDIR@ +CONFIG_CDFS_MVERSION=@CONFIG_CDFS_MVERSION@ + +CFLAGS=-Wall @c_opts@ -DCONFIG_CDFS_VERSION=\"@CONFIG_CDFS_VERSION@\" + +COPTS=$(c_opts) -Wall -Wstrict-prototypes -fomit-frame-pointer -pipe + +OBJS=audio.o cdXA.o cddata.o hfs.o iso.o proc.o root.o utils.o daemon.o discid.o toc.o + +TARGET_OBJ=cdfs.o + +ALL=$(TARGET_OBJ) + +all: $(ALL) + +cdfs.o: $(OBJS) + $(LD) -r $(OBJS) -o $@ + +$(OBJS) $(TARGET_OBJ): cdfs.h + +.c.o: + $(CC) $(CFLAGS) $(c_opts) $(O) -I$(CONFIG_CDFS_KERNELDIR)/include -c $< -Wall + +.PHONY: install clean reload tags + +install: $(TARGET_OBJ) + @INSTALL@ -m755 -d $(moddir) + @INSTALL@ -m644 $(TARGET_OBJ) $(moddir) + if [ -r $(CONFIG_CDFS_KERNELDIR)/System.map ]; then \ + depmod -ae -F $(CONFIG_CDFS_KERNELDIR)/System.map $(kaversion); \ + else \ + if [ -r /boot/System.map-$(kaversion) ]; then \ + depmod -ae -F /boot/System.map-$(kaversion) $(kaversion); \ + else \ + echo 1>&2 "No System.map found to compare symbols against."; \ + echo 1>&2 "Using default (running kernel); may fail"; \ + depmod -ae $(kaversion); \ + fi; \ + fi + +clean: + -rm -f *.o *~ core tags tags + +distclean: clean + -rm -f Makefile config.* + +reload: cdfs.o + -umount /mnt/cdfs + -rmmod cdfs + insmod -m cdfs.o > /tmp/cdfs.map + mount /mnt/cdfs + +tags: + ctags *.[ch] diff -urN wt1-350/fs/cdfs/audio.c wt1-350-cdfs-2420a/fs/cdfs/audio.c --- wt1-350/fs/cdfs/audio.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/audio.c Sat Mar 9 19:36:10 2002 @@ -0,0 +1,190 @@ +/* + + File audio.c - routines for 2352 byte frames cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" +#include + +/***************************************************************************/ + +void cdfs_make_header(char * temp, unsigned int size){ + PRINT("MAKING HEADER, size=%d @ 0x%x\n", size, temp); + + /* RIFF header */ + strcpy( temp, "RIFF"); + *(u32 *) (temp+ 4) = cpu_to_le32(size-8); /* size of RIFF */ + + /* WAVE file */ + strcpy( temp+ 8, "WAVE"); + + /* WAVE format*/ + strcpy( temp+12, "fmt "); + *(u32 *) (temp+16) = cpu_to_le32(16); /* size of format descriptor */ + /* common fields */ + *(u16 *) (temp+20) = cpu_to_le16(1); /* format category: WAVE_FORMAT_PCM */ + *(u16 *) (temp+22) = cpu_to_le16(2); /* number of channels */ + *(u32 *) (temp+24) = cpu_to_le32(44100); /* sample rate */ + *(u32 *) (temp+28) = cpu_to_le32(44100*4); /* bytes/sec */ + *(u16 *) (temp+32) = cpu_to_le16(4); /* data block size */ + /* format specific fields (PCM) */ + *(u16 *) (temp+34) = cpu_to_le16(16); /* bits per sample */ + + /* WAVE data */ + strcpy( temp+36, "data"); + *(u32 *) (temp+40) = cpu_to_le32(size-44); /* size of data chunk */ + +} +/***************************************************************************/ + +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) && (sectorcache_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; + + } +} + +/***************************************************************************/ + +void cdfs_cdda_file_read(struct inode * inode, char * buf, size_t count, unsigned start, int raw){ + unsigned stop=start+count; + + PRINT("cdda_file_read(%x, %x, %d, %d)\n", inode, buf, count, start); + + if (raw) { + cdfs_copy_from_cd(inode->i_sb, inode->i_ino, start, stop, buf); + } else { + if (start < WAV_HEADER_SIZE) { + if (stop > WAV_HEADER_SIZE) { + cdfs_cdda_file_read( inode, buf, WAV_HEADER_SIZE-start, start , 0 ); + cdfs_cdda_file_read( inode, buf+WAV_HEADER_SIZE-start, stop-WAV_HEADER_SIZE, WAV_HEADER_SIZE, 0 ); + } else { + char temp[44]; + cdfs_make_header(temp, inode->i_size); + memcpy(buf, temp+start, stop-start); + } + } else { + start -= WAV_HEADER_SIZE; + stop -= WAV_HEADER_SIZE; + cdfs_copy_from_cd(inode->i_sb, inode->i_ino, start, stop, buf); + } + } +} + +/***************************************************************************/ + +struct file_operations cdfs_cdda_file_operations = { +read: generic_file_read, +mmap: generic_file_mmap +}; + +int kcdfsd_add_cdda_request(struct file * file, struct page *page){ + PRINT("kcdfsd_add_cdda_request(%x, %x)\n", file, page); + return kcdfsd_add_request(file->f_dentry, page, CDDA_REQUEST); +} + +int kcdfsd_add_cdda_raw_request(struct file * file, struct page *page){ + PRINT("kcdfsd_add_cdda_request(%x, %x)\n", file, page); + return kcdfsd_add_request(file->f_dentry, page, CDDA_RAW_REQUEST); +} + +struct address_space_operations cdfs_cdda_aops = { +readpage: kcdfsd_add_cdda_request +}; + +struct address_space_operations cdfs_cdda_raw_aops = { +readpage: kcdfsd_add_cdda_raw_request +}; diff -urN wt1-350/fs/cdfs/cdXA.c wt1-350-cdfs-2420a/fs/cdfs/cdXA.c --- wt1-350/fs/cdfs/cdXA.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/cdXA.c Sat Aug 17 16:27:59 2002 @@ -0,0 +1,165 @@ +/* + + File cdXA.c - routines for frames <>2048 and <> 2352 byte frames for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" + +struct file_operations cdfs_cdXA_file_operations = { + read: generic_file_read, + mmap: generic_file_mmap +}; + +struct address_space_operations cdfs_cdXA_aops = { + readpage: kcdfsd_add_cdXA_request +}; + +/************************************************************/ + +int kcdfsd_add_cdXA_request(struct file * file, struct page *page){ + return kcdfsd_add_request(file->f_dentry, page, CDXA_REQUEST); +} + +/***********************************************************/ + +int cdfs_read_raw_frame(struct super_block * sb, int lba, unsigned char *buf) { + struct cdrom_msf *msf; + msf = (struct cdrom_msf*) buf; + msf->cdmsf_min0 = (lba + CD_MSF_OFFSET) / CD_FRAMES / CD_SECS; + msf->cdmsf_sec0 = (lba + CD_MSF_OFFSET) / CD_FRAMES % CD_SECS; + msf->cdmsf_frame0 = (lba + CD_MSF_OFFSET) % CD_FRAMES; + return cdfs_ioctl(sb, CDROMREADMODE2, (unsigned long)msf); +} + +/***********************************************************/ + +void cdfs_get_XA_info(struct super_block * sb, int inode) { + char frame[CD_FRAMESIZE_RAW0]; + cd * this_cd = cdfs_info(sb); + track_info * this_track = &(this_cd->track[inode]); + unsigned start_lba = this_track->start_lba; + int status; + + if((status = cdfs_read_raw_frame(sb, start_lba, frame))) { + printk("get_XA_info: ioctl failed: %d\n", status); + return; + } + + if (frame[0] == frame[4] && + frame[1] == frame[5] && + frame[2] == frame[6] && + frame[3] == frame[7] && + frame[2] != 0 && + frame[0] < 8 && + frame[1] < 8) { + this_track->xa_data_size = (frame[2] & 0x20) ? 2324 : 2048; + this_track->xa_data_offset = 8; + } else { + this_track->xa_data_size = 2048; + this_track->xa_data_offset = 0; + } + + // Get type & title + if((status = cdfs_read_raw_frame(sb, 150, frame))) { + printk("get_XA_info: ioctl failed: %d\n", status); + return; + } + + strncpy(this_cd->videocd_type, frame+this_track->xa_data_offset, 8); + this_cd->videocd_type[8]=0; + strncpy(this_cd->videocd_title, frame+this_track->xa_data_offset+10, 16); + this_cd->videocd_title[16]=0; + +} + +/***********************************************************/ + +void cdfs_copy_from_cdXA(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); + track_info * this_track = &(this_cd->track[inode]); + unsigned start_lba = this_track->start_lba; + unsigned int data_size = this_track->xa_data_size; + unsigned int data_offset = this_track->xa_data_offset; + + PRINT("start_lba=%d\n", start_lba); + + 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 = data_size; // Diego Rodriguez + } + + 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++) { + + int lba=sector+start_lba; + + PRINT("reading sector %d, lba=%d\n", sector, lba); + + if (this_cd->cache_sector == lba) { + PRINT("using cache\n"); + } else { + this_cd->cache_sector = lba; + if((status = cdfs_read_raw_frame(sb, lba, this_cd->cache))) { + printk("copy_from_cdXA(%d): ioctl failed: %d\n", lba, status); + return; + } + } + + { + char * copy_start; + int copy_length; + + if (sector==start_sector) { + copy_start = this_cd->cache+data_offset+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+data_offset; + copy_length = stop_byte; + } else { + copy_start = this_cd->cache+data_offset; + copy_length = data_size; + } + PRINT("memcpy(0x%x, %x, %d)\n", (int)buf, (int)copy_start, copy_length); + memcpy(buf, (char*)copy_start, copy_length); + buf+=copy_length; + } + + } +} + + +/***************************************************************************/ diff -urN wt1-350/fs/cdfs/cddata.c wt1-350-cdfs-2420a/fs/cdfs/cddata.c --- wt1-350/fs/cdfs/cddata.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/cddata.c Tue Feb 5 22:07:40 2002 @@ -0,0 +1,174 @@ +/* + + File cddata.c - routines for 2048 byte frames for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" + + +/***************************************************************************/ + + +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; + + 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].stoplba_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; +} + +/***************************************************************************/ + + +struct file_operations cdfs_cddata_file_operations = { + read: generic_file_read, + mmap: generic_file_mmap +}; + +struct address_space_operations cdfs_cddata_aops = { + readpage: kcdfsd_add_cddata_request +}; + +/************************************************************/ + +int kcdfsd_add_cddata_request(struct file * file, struct page *page){ + return kcdfsd_add_request(file->f_dentry, page, CDDATA_REQUEST); +} + +/***********************************************************/ + +int cdfs_read_rawDATA_frame(struct super_block * sb, unsigned lba, unsigned char *buf) { + struct buffer_head * bh; + + bh=bread(sb->s_dev, lba, CD_FRAMESIZE); + if (!bh) { + // dit gebeurt indien track1!=ISO is, bv. De Morgen CD + printk("cdfs_read_rawDATA(%x, %u, %x) FAILED!\n", (unsigned)sb, lba, (unsigned)buf); + } else { + memcpy(buf, bh->b_data, CD_FRAMESIZE); + brelse(bh); + } + return 0; +} + +/***********************************************************/ + +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; + + 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); + + PRINT("reading sector %d, lba=%d\n", sector, lba); + + if (this_cd->cache_sector == lba) { + PRINT("using cache\n"); + } else { + 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, %x, %d)\n", (int)buf, (int)copy_start, copy_length); + memcpy(buf, (char*)copy_start, copy_length); + buf+=copy_length; + } + + } +} + + +/***************************************************************************/ diff -urN wt1-350/fs/cdfs/cdfs.h wt1-350-cdfs-2420a/fs/cdfs/cdfs.h --- wt1-350/fs/cdfs/cdfs.h Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/cdfs.h Fri Aug 13 18:24:07 2004 @@ -0,0 +1,185 @@ +/* +#define PRDEBUG +*/ + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#error Sorry, this version of cdfs needs at least kernel 2.4.0 +#endif + + +// #define MODULE +// #define __KERNEL__ + +#define FSNAME "cdfs" +#define VERSION "0.5c" + + +#ifdef PRDEBUG +# define PRINT(format, arg...) printk(FSNAME "-> " format, ## arg) +#else +# define PRINT(format, arg...) +#endif + +#include +#ifdef CONFIG_MODVERSIONS +#include +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CDFS_MAGIC 0xCDDA +#define CDFS_MAXFN 128 + +#define TRUE 1 +#define FALSE 0 + +#define MAX_TRACKS 99 +#define WAV_HEADER_SIZE 44 + +#define READ_AHEAD 0 + +#define NONE 0 +#define AUDIO 1 +#define DATA 2 +#define BOOT 3 +#define HFS 4 + +#define AUDIO_NAME "track-%02d.wav" +#define RAW_AUDIO_NAME "track-%02d.raw" +#define AVI_AUDIO_NAME "track-%02d.avi" +#define DATA_NAME_ISO "sessions_1-%d.iso" +#define DATA_NAME_SINGLE "session-%d.iso" +#define DATA_NAME_VCD "videocd-%d.mpeg" + +#define UID 0 +#define GID 0 +#define MODE (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH) + +#define cdfs_info(X) ((X)->u.generic_sbp) + +#define CACHE_SIZE 1 + +// Convert track to inode number +#define T2I(X) ((X)+3) + +/* + sb -> inode 0 + . -> inode 1 + .. -> inode 2 + track-01 -> inode 3 (track 0!) + track-02 -> inode 4 (track 1!) + etc. +*/ + +typedef struct _iso_track_ { + unsigned start; + unsigned stop; +} iso_track; + +typedef struct _track_info { + unsigned size; /* in bytes */ + unsigned start_lba; + unsigned stop_lba; + unsigned hfs_offset; /* in 512 bytes */ + unsigned track_size; /* in bytes */ + unsigned iso_size; /* in bytes */ + unsigned type; /* audio, data of boot */ + char name[99]; + unsigned inode; + time_t time; /* only for data tracks */ + struct iso_primary_descriptor * iso_info; /* only for data tracks */ + int xa_data_size; /* only for xa data tracks */ + int xa_data_offset; /* only for xa data tracks */ + char bootID[99]; + int avi; /* only for raw audio tracks */ + int avi_offset; + int avi_swab; /* swap audio bytes? */ +} track_info; + +typedef struct _cd_ { + mode_t mode; + gid_t gid; + uid_t uid; + int single; + unsigned size; /* bytes */ + unsigned tracks; /* number of tracks */ + track_info track[MAX_TRACKS]; /* info per track */ + int nr_iso_sessions; + int discid; /* disc id hash */ + iso_track lba_iso_sessions[MAX_TRACKS]; + char videocd_type[9]; + char videocd_title[17]; + char * cache; + int cache_sector; + int raw_audio; + int toc_scsi; +} cd; + +typedef unsigned char byte; + +int cdfs_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *data ); + +extern struct file_operations cdfs_cdda_file_operations; +extern struct file_operations cdfs_cdXA_file_operations; +extern struct file_operations cdfs_cddata_file_operations; +extern struct file_operations cdfs_cdhfs_file_operations; + +extern struct address_space_operations cdfs_cdda_aops; +extern struct address_space_operations cdfs_cdda_raw_aops; +extern struct address_space_operations cdfs_cdXA_aops; +extern struct address_space_operations cdfs_cddata_aops; +extern struct address_space_operations cdfs_cdhfs_aops; + +int cdfs_toc_read(struct super_block *sb); +int cdfs_toc_read_full(struct super_block *sb); +time_t cdfs_constructtime(char * time); +unsigned cdfs_constructsize(char * size); +void cdfs_constructMSFsize(char * result, unsigned length); +int cdfs_ioctl(struct super_block *s, int cmd, unsigned long arg); +struct iso_primary_descriptor * cdfs_get_iso_info(struct super_block *sb, int track_no); +int cdfs_get_hfs_info(struct super_block *sb, unsigned track); +void cdfs_check_bootable(struct super_block *sb); +void cdfs_get_XA_info(struct super_block * sb, int inode); +void cdfs_copy_from_cdXA(struct super_block * sb, int inode, unsigned int start, + unsigned int stop, char * buf); +void cdfs_copy_from_cddata(struct super_block * sb, int inode, unsigned int start, + unsigned int stop, char * buf); +void cdfs_copy_from_cdhfs(struct super_block * sb, int inode, unsigned int start, + unsigned int stop, char * buf); +void cdfs_cdda_file_read(struct inode * inode, char * buf, size_t count, unsigned start /*loff_t *ppos*/,int raw); + +int kcdfsd_add_cdXA_request(struct file * file, struct page *page); +int kcdfsd_add_cddata_request(struct file * file, struct page *page); +int kcdfsd_add_cdda_request(struct file * file, struct page *page); +int kcdfsd_add_cdda_raw_request(struct file * file, struct page *page); +int kcdfsd_add_cdhfs_request(struct file * file, struct page *page); + +int kcdfsd_add_request(struct dentry *dentry, struct page *page, unsigned type); +int kcdfsd_thread(void *unused); +void kcdfsd_cleanup_thread(void); +extern int kcdfsd_pid; + +/* for discid stuff */ +unsigned long discid(cd *); + +// REQUEST TYPES +#define CDDA_REQUEST 1 +#define CDXA_REQUEST 2 +#define CDHFS_REQUEST 3 +#define CDDATA_REQUEST 4 +#define CDDA_RAW_REQUEST 5 diff -urN wt1-350/fs/cdfs/daemon.c wt1-350-cdfs-2420a/fs/cdfs/daemon.c --- wt1-350/fs/cdfs/daemon.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/daemon.c Sun Dec 1 23:29:02 2002 @@ -0,0 +1,175 @@ +/* + + File daemon.c - kernel thread routines for asynchronuous I/O + + Initial code written by Chih-Chung Chang + + Copyright (c) 2000, 2001 by Michiel Ronsse + + Support for kmap by Peter Korf + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + + +#include "cdfs.h" + +static int kcdfsd_pid = 0; +static int kcdfsd_running = 0; +static DECLARE_WAIT_QUEUE_HEAD(kcdfsd_wait); +static LIST_HEAD(kcdfsd_req_list); /* List of requests needing servicing */ + +struct kcdfsd_req { + struct list_head req_list; + struct dentry *dentry; + struct page *page; + unsigned request_type; +}; + +/*********************************************************************************/ + +int kcdfsd_add_request(struct dentry* dentry, struct page *page, unsigned request){ + struct kcdfsd_req *req = kmalloc(sizeof(struct kcdfsd_req), GFP_KERNEL); + INIT_LIST_HEAD(&req->req_list); + req->dentry = dentry; + req->page = page; + req->request_type = request; + list_add_tail(&req->req_list, &kcdfsd_req_list); + wake_up(&kcdfsd_wait); + return 0; +} + +/*********************************************************************************/ + +static void kcdfsd_process_request(){ + struct list_head * tmp; + struct kcdfsd_req * req; + struct page * page; + struct inode * inode; + unsigned request; + + while(1) { + + if (list_empty(&kcdfsd_req_list)) + break; + + /* 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)) + PAGE_BUG(page); + + 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<index<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<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); + UnlockPage(page); + kfree(req); + } + +} + +/****************************************************************************/ + +int kcdfsd_thread(void *unused){ + kcdfsd_running = 1; + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources + */ + exit_files(current); /* daemonize doesn't do exit_files */ + daemonize(); + + /* Setup a nice name */ + strcpy(current->comm, "k"FSNAME"d"); + + /* Send me a signal to get me die */ + do { + kcdfsd_process_request(); + interruptible_sleep_on(&kcdfsd_wait); + } while (!signal_pending(current)); + + kcdfsd_running = 0; + return 0; +} + +/****************************************************************************/ + +void kcdfsd_cleanup_thread(){ + int ret; + ret = kill_proc(kcdfsd_pid, SIGTERM, 1); + if (!ret) { + /* Wait 10 seconds */ + int count = 10 * HZ; + + while (kcdfsd_running && --count) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + if (!count) + printk(FSNAME": Giving up on killing k"FSNAME"d!\n"); + } +} diff -urN wt1-350/fs/cdfs/discid.c wt1-350-cdfs-2420a/fs/cdfs/discid.c --- wt1-350/fs/cdfs/discid.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/discid.c Tue Feb 5 22:07:40 2002 @@ -0,0 +1,29 @@ + +#include "cdfs.h" + +static unsigned int cddb_sum(int n); + + +unsigned long discid(cd * this_cd) { + unsigned int i=0, t, n = 0; + + for (i=0; i< this_cd->tracks; i++) + n += cddb_sum((this_cd->track[T2I(i)].start_lba+CD_MSF_OFFSET)/CD_FRAMES); + + t = this_cd->track[T2I(this_cd->tracks-1)].stop_lba/CD_FRAMES; + + return (((n % 0xFF) << 24) | (t << 8) | this_cd->tracks); +} + + +static unsigned int cddb_sum(int n) { + unsigned int ret = 0; + + while (n > 0) { + ret += (n % 10); + n /= 10; + } + + return ret; +} + diff -urN wt1-350/fs/cdfs/hfs.c wt1-350-cdfs-2420a/fs/cdfs/hfs.c --- wt1-350/fs/cdfs/hfs.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/hfs.c Mon Apr 21 17:03:03 2003 @@ -0,0 +1,208 @@ +/* + + File hfs.c - routines for HFS partitions for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" + +/* from /usr/src/linux/fs/hfs/part_tbl.c */ + +struct new_pmap { + char pmSig[2]; + char padding[2]; + char pmMapBlkCnt[4]; + char pmPyPartStart[4]; + char pmPartBlkCnt[4]; + char pmPartName[32]; + char pmPartType[32]; +}; + +/*************************/ + +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; + int part; + int aantal; + 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; + } + + if (!strncmp(bh->b_data,"ER",2)){ + pmapp=(struct new_pmap*)(bh->b_data+512); /* 2e blok van 512 bytes */ + if (!strncmp(pmapp->pmSig,"PM",2)){ + 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; + sprintf(this_cd->track[thistrack].name, "%d.1.%s", track, (char*)&pmapp->pmPartType); + 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); + aantal=this_cd->track[thistrack].size/512; + PRINT(">>%d<<\n", aantal); + for (part=2; parts_dev, start_lba+part/4, CD_FRAMESIZE); + PRINT("mapping @ %d\n",(part%4)*512); + pmapp=(struct new_pmap*)(bh->b_data+(part%4)*512); + if (!strncmp(pmapp->pmSig,"PM",2)&&*(unsigned*)(pmapp->pmPartBlkCnt)){ + if (ntohl(*(unsigned*)(pmapp->pmPyPartStart))==1){ + //printk("done!!\n"); + part=aantal*2; + } else { + 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; + sprintf(this_cd->track[thistrack].name, "%d.%d.%s", track, part, (char*)&pmapp->pmPartType); + 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/%s, starts at %d (offset=%d), stops at %d\n", &pmapp->pmPartName, + &pmapp->pmPartType, + this_cd->track[thistrack].start_lba, + this_cd->track[thistrack].hfs_offset, + this_cd->track[thistrack].stop_lba); + } + } //else printk("failed:%s\n", pmapp->pmSig); + + } + } + brelse(bh); + return 0; + } else { + brelse(bh); + return -1; + } +} + +/***********************************************************/ + + +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; + + } +}; + +/***************************************************************************/ + +struct file_operations cdfs_cdhfs_file_operations = { + read: generic_file_read, + mmap: generic_file_mmap +}; + + +int kcdfsd_add_cdhfs_request(struct file * file, struct page *page){ + return kcdfsd_add_request(file->f_dentry, page, CDHFS_REQUEST); +} + +struct address_space_operations cdfs_cdhfs_aops = { + readpage: kcdfsd_add_cdhfs_request +}; diff -urN wt1-350/fs/cdfs/iso.c wt1-350-cdfs-2420a/fs/cdfs/iso.c --- wt1-350/fs/cdfs/iso.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/iso.c Tue Feb 5 22:07:40 2002 @@ -0,0 +1,162 @@ +/* + + File iso.c - routines for ISO segments and boot images for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" + + +struct _bootmedia_ { + char text[20]; + unsigned int size; /* in bytes */ +} cdfs_bootmedia[5] = { + {"No Emulation", 0}, + {"1.2 MB diskette", 1200*1024}, + {"1.44 MB diskette", 1440*1024}, + {"2.88 MB diskette", 2800*1024}, + {"Hard Disk", 0} +}; + +/************************/ + +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); +} + +/*************************/ + +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; + +} + +/***********************/ + + diff -urN wt1-350/fs/cdfs/proc.c wt1-350-cdfs-2420a/fs/cdfs/proc.c --- wt1-350/fs/cdfs/proc.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/proc.c Mon Apr 21 16:57:11 2003 @@ -0,0 +1,387 @@ +/* + + File proc.c - /proc routines for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* + * Robert W. Boone (November, 2002) * + * Rewrote using kernel sequential synthetic file support. This was * + * done to fix a kernel segmentation fault caused by trying to shove too * + * much data into a kernel buffer when looking at a CD with more than a * + * few sessions on it. I tried modifying existing code to gracefully * + * carve up output into 4K pieces but it quickly became a nightmare to * + * manage the file position to keep proc_file_read() from changing it * + * unexpectedly. To me, it seemed most logical to break up the output * + * into manageable chunks, with each chunk being a CD track. Thus, file * + * offset 0 would be track 0, file offset 1 would be track 1, etc. * + * Since the kernel already provides this capability in the form of * + * sequential synthetic file support, that's what I settled on using. * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +#include "cdfs.h" +#include + +struct proc_dir_entry * cdfs_proc_entry; + +cd * cdfs_proc_cd; + +/****************************************************************************** + * Pointer to dummy track; used to tell cdfs_show() there is no CD mounted * + ******************************************************************************/ + +struct _track_info *dummy_track_p = NULL; + + +/*============================================================================* + * cdfs_start() * + * Purpose: * + * Given a track number, find its track[] entry. * + * Inputs: * + * file_p ===> Pointer to seq_file descriptor; unused * + * offset_p => Pointer to offset (track number) within /proc/cdfs * + * Returns: * + * If no CD is mounted, dummy_track_p is returned as long as we * + * don't try to go past the first track, otherwise NULL is returned. * + * If there are no more tracks left, NULL is returned. Otherwise, * + * the address of the track's track[] entry is returned. * + *============================================================================*/ + +static void * +cdfs_start(struct seq_file *file_p, loff_t *offset_p) { + + /* + * If there is no CD + * If we're not trying to go past the first track + * Allocate a dummy track pointer if needed + * Tell cdfs_show() to print "No CD mounted" message + * Else + * Indicate end of file + */ + + if (cdfs_proc_cd == NULL) { + if (*offset_p < 1) { + if (dummy_track_p == NULL) { + dummy_track_p = kmalloc(sizeof(struct _track_info), GFP_KERNEL); + if (dummy_track_p == NULL) { + return NULL; + } + } + return dummy_track_p; + } else { + return NULL; + } + } + + /* + * If there are no more tracks left + * Indicate end of file + */ + + if (*offset_p >= cdfs_proc_cd->tracks) { + return NULL; + } + + /* + * Return track[] entry address for track, converting track to inode + */ + + return &cdfs_proc_cd->track[T2I(*offset_p)]; +} + + +/*============================================================================* + * cdfs_next() * + * Purpose: * + * Move to next track number. * + * Inputs: * + * file_p ===> Pointer to seq_file descriptor; unused * + * data_p ===> Pointer to some bit of data; unused * + * offset_p => Pointer to offset (track number) within /proc/cdfs * + * Returns: * + * cdfs_start() result. * + *============================================================================*/ + +static void * +cdfs_next(struct seq_file *file_p, void *data_p, loff_t *offset_p) { + + /* + * Go to next track and get its track[] entry address + */ + + (*offset_p)++; + return cdfs_start(file_p, offset_p); +} + + +/*============================================================================* + * cdfs_stop() * + * Purpose: * + * Placeholder function; does nothing. * + * Inputs: * + * file_p ===> Pointer to seq_file descriptor; unused * + * data_p ===> Pointer to some bit of data; unused * + * Returns: * + * Nothing. * + *============================================================================*/ + +static void +cdfs_stop(struct seq_file *file_p, void *data_p) { +} + + +/*============================================================================* + * remove_trailing_blanks() * + * Purpose: * + * Remove trailing blanks from a string, placing a null character * + * (\0) immediately after first non-blank character found during * + * right to left scan. * + * Inputs: * + * string_p => Pointer to string to remove blanks from * + * bytes ====> Maximum number of bytes in string * + * Returns: * + * Address of + *============================================================================*/ + +static char temp_buffer[4096]; + +static char * +remove_trailing_blanks( + char *string_p, + int bytes +) { + char *temp_p; + + /* + * Make copy of string in temporary buffer + * Get address of last character in string + */ + + (void) memcpy(temp_buffer, string_p, bytes); + temp_p = temp_buffer + bytes - 1; + + /* + * While string not exhausted and current character is a blank + * Move one character to the left in the string + */ + + while ((temp_p >= temp_buffer) && (*temp_p == ' ')) { + temp_p -= 1; + } + + /* + * We went too far left, move one character back to right + * Insert null character to terminate string + */ + + temp_p += 1; + *temp_p = '\0'; + return &temp_buffer[0]; +} + + +/*============================================================================* + * cdfs_show() * + * Purpose: * + * Print information for a CD track. * + * Inputs: * + * file_p ===> Pointer to seq_file descriptor * + * data_p ===> Pointer to address of track's track[] entry * + * Returns: * + * 0 on success. Negative number on failure. * + *============================================================================*/ + +#define TRACK_POINTER_TO_TRACK_NUMBER(pointer) \ + ((pointer - &cdfs_proc_cd->track[0]) - 3) + 1 + +static int +cdfs_show(struct seq_file *file_p, void *data_p) { + struct _track_info *track_p; + + track_p = data_p; + + /* + * If no CD mounted + * Print that message but nothing else + */ + + if (track_p == dummy_track_p) { + seq_printf( + file_p, + "[%s\t%s]\n\tNo CD mounted\n", + FSNAME, + VERSION + ); + return 0; + } + + /* + * If current track is track 1 (inode 3) + * Print disc ID and number of tracks before anything else + */ + + if (track_p == &(cdfs_proc_cd->track[3])) { + seq_printf( + file_p, + "[%s\t%s%s]\n\nCD (discid=%08X) contains %d track%s:\n\n", + FSNAME, + VERSION, + cdfs_proc_cd->toc_scsi?", with new (SCSI) TOC support":"", + cdfs_proc_cd->discid, + cdfs_proc_cd->tracks, + cdfs_proc_cd->tracks - 1 ? "s" : "" + ); + } + + seq_printf(file_p, "\n"); + + /* + * Now print information for current track + */ + + if (track_p->type == DATA) { + if (track_p->iso_size) { + seq_printf( + file_p, + "Track %2d: data track (%s), [%d-%d/%d], length=%d MB\n", + TRACK_POINTER_TO_TRACK_NUMBER(track_p), + track_p->name, + track_p->start_lba, + track_p->iso_size / 2048, + track_p->stop_lba, + track_p->track_size / 1024 / 1024 + ); + seq_printf( + file_p, + "\ttype: %c info: %.5s version: %c\n" + "\tdate: %.2s/%.2s/%.4s time: %.2s:%.2s:%.2s\n" + "\tsystem: %.32s\n\tvolume: %.32s\n", + track_p->iso_info->type[0] + 48, + track_p->iso_info->id, + track_p->iso_info->version[0] + 48, + track_p->iso_info->creation_date + 6, + track_p->iso_info->creation_date + 4, + track_p->iso_info->creation_date, + track_p->iso_info->creation_date + 8, + track_p->iso_info->creation_date + 10, + track_p->iso_info->creation_date + 12, + track_p->iso_info->system_id, + track_p->iso_info->volume_id + ); + seq_printf( + file_p, + "\tpublisher: %.128s\n", + remove_trailing_blanks(track_p->iso_info->publisher_id, 128) + ); + seq_printf( + file_p, + "\tpreparer: %.128s\n", + remove_trailing_blanks(track_p->iso_info->preparer_id, 128) + ); + seq_printf( + file_p, + "\tapplication: %.128s\n", + remove_trailing_blanks(track_p->iso_info->application_id, 128) + ); + seq_printf( + file_p, + "\tlength: %d MB / %d MB / %d MB / %d MB\n", + (track_p->iso_size - track_p->start_lba * CD_FRAMESIZE) / 1024 / 1024, + track_p->track_size / 1024 / 1024, + track_p->iso_size / 1024 / 1024, + track_p->size / 1024 / 1024 + ); + } else { + seq_printf( + file_p, + "Track %2d: data track (%s), [%d-%d], length=%d kB\n", + TRACK_POINTER_TO_TRACK_NUMBER(track_p), + track_p->name, + track_p->start_lba, + track_p->stop_lba, + track_p->track_size / 1024 + ); + seq_printf( + file_p, + "\ttype: %s\n", + cdfs_proc_cd->videocd_type + ); + seq_printf( + file_p, + "\ttitle: %s\n", + cdfs_proc_cd->videocd_title + ); + seq_printf( + file_p, + "\tframesize: %d B\n", + track_p->xa_data_size + ); + } + } else if (track_p->type == BOOT) { + seq_printf( + file_p, + "Bootimage (%s), [%d-%d], length=%d kB\n\tID string:%s\n", + track_p->name, + track_p->start_lba, + track_p->stop_lba, + track_p->size / 1024, + track_p->bootID + ); + } else if (track_p->type == HFS) { + seq_printf( + file_p, + "Apple HFS (%s), [%d-%d], length=%d MB\n\tID string:%s\n", + track_p->name, + track_p->start_lba, + track_p->stop_lba, + track_p->size / 1024 / 1024, + track_p->bootID + ); + } else if (track_p->type == AUDIO) { + char MSFsize[10]; + + cdfs_constructMSFsize(MSFsize, track_p->size); + seq_printf( + file_p, + "Track %2d: audio track (%s), [%8d -%8d], length=%s\n", + TRACK_POINTER_TO_TRACK_NUMBER(track_p), + track_p->name, + track_p->start_lba, + track_p->stop_lba, + MSFsize + ); + } + + return 0; +} + + +/****************************************************************************** + * Table of sequential file operations implemented for CDFS * + ******************************************************************************/ + +struct seq_operations cdfs_operations = { + start: cdfs_start, + next: cdfs_next, + stop: cdfs_stop, + show: cdfs_show +}; diff -urN wt1-350/fs/cdfs/root.c wt1-350-cdfs-2420a/fs/cdfs/root.c --- wt1-350/fs/cdfs/root.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/root.c Tue Apr 22 22:36:22 2003 @@ -0,0 +1,575 @@ +/* + + File root.c - superblock and module routines for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "cdfs.h" + +#include + + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* + * Robert W. Boone (November, 2002) * + * Added code to transform /proc/cdfs into a sequential synthetic file. * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +#include + +extern struct seq_operations cdfs_operations; +extern struct _track_info *dummy_track_p; + + +/*============================================================================* + * cdfs_open() * + * Description: * + * Open a CDFS /proc file as a sequential synthetic file. * + * Input: * + * inode_p => Pointer to /proc file inode; unused * + * file_p ==> Pointer to sequential file descriptor * + * Return Value: * + * seq_open() result. * + *============================================================================*/ + +static int +cdfs_open(struct inode *inode_p, struct file *file_p) { + return seq_open(file_p, &cdfs_operations); +} + + +/*============================================================================* + * cdfs_release() * + * Description: * + * Free any memory allocated when /proc/cdfs was opened or accessed * + * as a sequential synthetic file. * + * Input: * + * inode_p => Pointer to /proc file inode * + * file_p ==> Pointer to sequential file descriptor * + * Return Value: * + * seq_release() result. * + *============================================================================*/ + +int +cdfs_release(struct inode *inode_p, struct file *file_p) { + + /* + * Release any memory allocated to tell cdfs_show() there is no CD + */ + + if (dummy_track_p != NULL) { + kfree(dummy_track_p); + dummy_track_p = NULL; + } + + return seq_release(inode_p, file_p); +} + + +/****************************************************************************** + * CDFS high-level file operations table * + ******************************************************************************/ + +struct file_operations proc_cdfs_operations = { + owner: THIS_MODULE, + llseek: seq_lseek, + read: seq_read, + open: cdfs_open, + release: cdfs_release, +}; + + +/********************************************************************/ + +static struct super_operations cdfs_ops; + +void cdfs_parse_options(char *, cd *); + +extern struct proc_dir_entry * cdfs_proc_entry; + +extern cd * cdfs_proc_cd; + +/********************************************************************/ + +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; + struct cdrom_tocentry entry; + int no_audio=0, no_data=0; + cd * this_cd; + + PRINT("cdfs_mount\n"); + + MOD_INC_USE_COUNT; + + set_blocksize(dev, CD_FRAMESIZE); // voor bread met ide-cd + + sb->s_blocksize = CD_FRAMESIZE; + sb->s_blocksize_bits = 11; + + if (!(this_cd = cdfs_info(sb) = kmalloc(sizeof(cd), GFP_KERNEL))){ + MOD_DEC_USE_COUNT; + return NULL; + } + + 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))) { + MOD_DEC_USE_COUNT; + return NULL; + } + + // 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"); + MOD_DEC_USE_COUNT; + return NULL; + } + } else { + //if (cdfs_ioctl(sb, CDROMREADTOCHDR, (unsigned long)&hdr)){ + if (cdfs_toc_read(sb)){ + printk("cdfs_toc_read failed\n"); + MOD_DEC_USE_COUNT; + return NULL; + } + } + + 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 = CURRENT_TIME; + 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); + 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;ktrack[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 (itracks)) { + 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; + sb->s_root = d_alloc_root(iget(sb, 0)); + + cdfs_proc_cd = this_cd; + + return sb; +} + +/************************************************************************/ + +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)); + + MOD_DEC_USE_COUNT; + +} + +/************************************************************************/ + +static int cdfs_statfs(struct super_block *sb, struct statfs *buf) { + cd * this_cd = cdfs_info(sb); + 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; itracks); 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 struct dentry * cdfs_lookup(struct inode *dir, struct dentry *dentry){ + struct inode * inode; + int i; + cd * this_cd = cdfs_info(dir->i_sb); + + PRINT("cdfs_lookup %s ino=%ld -> ", dentry->d_name.name, dir->i_ino); + + for(i=0; itracks); i++) + if (!(strcmp(this_cd->track[i].name, dentry->d_name.name))) { + if ((inode=iget(dir->i_sb, i))==NULL) { + return ERR_PTR(-EACCES); + } else { + d_add(dentry, inode); + return ERR_PTR(0); + } + } + return ERR_PTR(-ENOENT); +} + + +/***************************************************************************/ + +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); + + //printk("this_cd = 0x%x\n\n\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 = NULL; + 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_op = &cdfs_inode_operations; + i->i_fop = &cdfs_dir_operations; + } else { /* file */ + i->i_size = this_cd->track[i->i_ino].size; + i->i_mtime = i->i_atime = i->i_ctime = this_cd->track[i->i_ino].time; + 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_operations cdfs_ops = { + read_inode: cdfs_read_inode, + put_super: cdfs_umount, + statfs: cdfs_statfs +}; + +static DECLARE_FSTYPE_DEV(cdfs_fs_type, FSNAME, cdfs_mount); + +/******************************************************/ + +MODULE_AUTHOR("Michiel Ronsse (ronsse@elis.rug.ac.be)"); +MODULE_DESCRIPTION("CDfs: a CD filesystem"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; + +/******************************************************************/ + +static int __init cdfs_init(void) { + int err; + PRINT("init_module (insmod)\n"); + + printk(FSNAME" "VERSION" loaded.\n"); + + // register file system + err = register_filesystem(&cdfs_fs_type); + if (err < 0) return err; + + // register /proc entry + if ((cdfs_proc_entry = create_proc_entry(FSNAME, 0, NULL ))) + cdfs_proc_entry->proc_fops = &proc_cdfs_operations; + cdfs_proc_cd=NULL; + + // start kernel thread + if ((kcdfsd_pid = kernel_thread(kcdfsd_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) >0 ) { + return 0; + } else { + printk(FSNAME" kernel_thread failed.\n"); + if (cdfs_proc_entry) remove_proc_entry(FSNAME, NULL); + unregister_filesystem(&cdfs_fs_type); + return -1; + } +} + +/******************************************************************/ + +static void __exit cdfs_exit(void) { + PRINT("cleanup_module (rmmod)\n"); + kcdfsd_cleanup_thread(); + if (cdfs_proc_entry) remove_proc_entry(FSNAME, NULL); + unregister_filesystem(&cdfs_fs_type); +} + +/******************************************************************/ + +module_init(cdfs_init); +module_exit(cdfs_exit); + +/******************************************************************/ + +void cdfs_parse_options(char *options, cd * this_cd) { + char *this_char,*value; + + /* from isofs */ + + if (!options) return; + + for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { + + if (!strcmp(this_char,"single")) + this_cd->single=TRUE; + else if (!strcmp(this_char,"raw")) + this_cd->raw_audio=TRUE; + else if (!strcmp(this_char,"toc_scsi")) { + printk("Using new TOC function!\n"); + this_cd->toc_scsi=TRUE; + } else { + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + if (value && + (!strcmp(this_char,"mode") || + !strcmp(this_char,"uid") || + !strcmp(this_char,"gid"))) { + char * vpnt = value; + unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0); + if (*vpnt) return; + switch(*this_char) { + case 'u': this_cd->uid = ivalue; break; + case 'g': this_cd->gid = ivalue; break; + case 'm': this_cd->mode = ivalue | S_IFREG ; break; + } + } else + return; + } + } +} diff -urN wt1-350/fs/cdfs/toc.c wt1-350-cdfs-2420a/fs/cdfs/toc.c --- wt1-350/fs/cdfs/toc.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/toc.c Tue Apr 22 22:39:46 2003 @@ -0,0 +1,225 @@ +/* + + File toc.c - superblock and module routines for cdfs + + + Copyright (c) 2003 by Laurent Pinchart + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "cdfs.h" +#include + +/* + * Send a SCSI command + */ +static int cdfs_scsi_send_command( struct super_block *sb, + char *cmd, int dir, void *buffer, int buflen ) +{ + struct cdrom_generic_command cd_cmd; + struct request_sense sense; + + /* No need to zero the request sense as we don't use it anyway */ + memset( &cd_cmd, 0, sizeof( cd_cmd ) ); + memcpy( cd_cmd.cmd, cmd, CDROM_PACKET_SIZE ); + + cd_cmd.data_direction = dir; + cd_cmd.buffer = buffer; + cd_cmd.buflen = buflen; + cd_cmd.timeout = 20000; + cd_cmd.sense = &sense; + cd_cmd.quiet = 0; + cd_cmd.stat = GOOD; + + if ( cdfs_ioctl( sb, CDROM_SEND_PACKET, (unsigned long)&cd_cmd ) < 0 || cd_cmd.stat != GOOD ) + { + PRINT( "cdfs_scsi_send_command: CDROM_SEND_PACKET ioctl failed (status %d)\n", cd_cmd.stat ); + return -1; + } + + return 0; +} + +#define TIME2LBA(min, sec, frame) ((((min)*60)+(sec))*75+(frame)) + +int cdfs_toc_read_full( struct super_block *sb ) +{ + unsigned char cmd[CDROM_PACKET_SIZE]; + unsigned char toc[12]; + int first_session, last_session; + int sess, cur_track; + int lead_out; + cd * this_cd = cdfs_info( sb ); + + /* Get the number of sessions */ + memset( cmd, 0, sizeof( cmd ) ); + memset( toc, 0, sizeof( toc ) ); + cmd[0] = READ_TOC; + cmd[2] = 1; /* Format : Session Info */ + cmd[8] = sizeof( toc ); + if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, toc, sizeof( toc ) ) < 0 ) + return -1; + + first_session = toc[2]; + last_session = toc[3]; + PRINT( "cdfs_toc_read_full: CD contains %d sessions\n", last_session - first_session + 1 ); + + cur_track = T2I(0); + this_cd->track[0].start_lba = 0; + this_cd->track[1].start_lba = 0; + this_cd->track[2].start_lba = 0; + + /* Iterate through the sessions */ + cmd[1] = 2; /* Addresses in TIME format */ + cmd[2] = 2; /* Format : Full TOC */ + lead_out = 0; + for ( sess = first_session; sess <= last_session; ++sess ) + { + unsigned char *stoc; + int toc_size, tracks, j; + + /* Read the first 4 bytes of the full TOC to get the TOC length */ + cmd[6] = sess; /* Session number */ + cmd[7] = 0; /* Allocation length MSB */ + cmd[8] = 4; /* Allocation length LSB */ + + if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, toc, sizeof( toc ) ) < 0 ) + { + printk( "cdfs_read_toc: unable to read session %d toc header, skipping\n", sess ); + continue; + } + + /* Allocate memory for the session TOC */ + toc_size = ( toc[0] << 8 ) + toc[1] + 2; + tracks = ( toc_size - 4 ) / 11; + PRINT( "cdfs_toc_read_full: session %d contains %d track descriptors\n", sess, tracks ); + if ( tracks == 0 ) + continue; + + if ( ! ( stoc = kmalloc( toc_size, GFP_KERNEL ) ) ) + { + printk( "cdfs_read_toc: unable to allocate memory for session %d toc, skipping\n", sess ); + continue; + } + + /* Read the full session TOC */ + cmd[7] = toc_size >> 8; + cmd[8] = toc_size & 0xff; + if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, stoc, toc_size ) < 0 ) + { + printk( "cdfs_read_toc: unable to read session %d toc, skipping\n", sess ); + kfree( stoc ); + continue; + } + + /* Iterate through the tracks descriptors */ + lead_out = 0; + for ( j = 0; j < tracks; ++j ) + { + struct track_descriptor + { + unsigned char session; + unsigned char adr_control; + unsigned char tno; + unsigned char point; + unsigned char min; + unsigned char sec; + unsigned char frame; + unsigned char zero; + unsigned char pmin; + unsigned char psec; + unsigned char pframe; + } *track = (struct track_descriptor*)&stoc[11*j+4]; + + if ( ( track->adr_control >> 4 ) != 1 ) + continue; + + if ( track->point == 0xa2 ) + /* Lead out start. Needed to compute the size of the last track */ + lead_out = TIME2LBA( track->pmin, track->psec, track->pframe ) - 150; + else if ( track->point <= 0x63 ) + { + /* This is a true track descriptor */ + this_cd->track[cur_track].type = ( track->adr_control & 0x04 ) ? DATA : AUDIO; + this_cd->track[cur_track].time = CURRENT_TIME; + this_cd->track[cur_track].start_lba = TIME2LBA( track->pmin, track->psec, track->pframe ) - 150; + this_cd->track[cur_track-1].stop_lba = this_cd->track[cur_track].start_lba - 1; + PRINT("Start[%d]: %d\n", cur_track, this_cd->track[cur_track].start_lba); + ++cur_track; + } + } + this_cd->track[cur_track-1].stop_lba = lead_out - 1; + + kfree( stoc ); + break; //////////// + } + + this_cd->track[cur_track].start_lba = lead_out; + this_cd->tracks = cur_track-T2I(0); + return 0; +} + +int cdfs_toc_read( struct super_block *sb ) +{ + int i, t; + struct cdrom_tochdr hdr; + struct cdrom_tocentry entry; + cd * this_cd = cdfs_info( sb ); + + if ( cdfs_ioctl( sb, CDROMREADTOCHDR, (unsigned long)&hdr ) ) + { + printk( "ioctl(CDROMREADTOCHDR) failed\n" ); + return -1; + } + + this_cd->tracks = hdr.cdth_trk1 - hdr.cdth_trk0 + 1; + PRINT( "CD contains %d tracks: %d-%d\n", this_cd->tracks, hdr.cdth_trk0, hdr.cdth_trk1 ); + + /* Collect track info */ + entry.cdte_format = CDROM_LBA; + + this_cd->track[0].start_lba = 0; + this_cd->track[1].start_lba = 0; + this_cd->track[2].start_lba = 0; + for ( t = this_cd->tracks; t >= 0; --t ) + { + i = T2I(t); + + 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" ); + return -1; + } + + this_cd->track[i].start_lba = entry.cdte_addr.lba; + this_cd->track[i].stop_lba = this_cd->track[i+1].start_lba - 1; + + PRINT("Start[%d]: %d\n", i, this_cd->track[i].start_lba); + + if ( t != this_cd->tracks ) /* all tracks but the LEADOUT */ + { + this_cd->track[i].type = ( entry.cdte_ctrl & CDROM_DATA_TRACK ) ? DATA : AUDIO; + this_cd->track[i].time = CURRENT_TIME; + } + } + + return 0; +} diff -urN wt1-350/fs/cdfs/utils.c wt1-350-cdfs-2420a/fs/cdfs/utils.c --- wt1-350/fs/cdfs/utils.c Thu Jan 1 01:00:00 1970 +++ wt1-350-cdfs-2420a/fs/cdfs/utils.c Tue Feb 5 22:07:40 2002 @@ -0,0 +1,81 @@ +/* + + File utils.c - miscellaneous routines for cdfs + + + Copyright (c) 1999, 2000, 2001 by Michiel Ronsse + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include "cdfs.h" + + +/* convert YYYYMMDDHHMMSS to time_t (seconds since 1/1/1970) */ + +time_t cdfs_constructtime(char * time){ + + unsigned year,month,day,hour,min,sec; + + if (!time) return 0; + if ((*time!='1') && (*time!='2')) return 0; + + year = 1000*(time[0]-'0')+100*(time[1]-'0')+10*(time[2]-'0')+(time[3]-'0'); + + if (year<1970) + return 0; + else { + year -= 1970; + month = 10*(time[ 4]-'0') + (time[ 5]-'0'); + day = 10*(time[ 6]-'0') + (time[ 7]-'0'); + hour = 10*(time[ 8]-'0') + (time[ 9]-'0'); + min = 10*(time[10]-'0') + (time[11]-'0'); + sec = 10*(time[12]-'0') + (time[13]-'0'); + + return mktime(year, month, day, hour, min, sec); + } +} + +/****************************************/ + +unsigned cdfs_constructsize(char * size){ + return (unsigned char)size[0]+ + ((unsigned char)size[1]<<8)+ + ((unsigned char)size[2]<<16)+ + ((unsigned char)size[3]<<24); +} + +/**************************/ + + +void cdfs_constructMSFsize(char * result, unsigned length){ + int min,sec; + length = (length-WAV_HEADER_SIZE)/CD_FRAMESIZE_RAW; + length /= 75; + sec = length%60; + min = length/60; + sprintf(result,"%2d:%02d", min, sec); +} + +/***********************************************************************/ + +int cdfs_ioctl(struct super_block *s, int cmd, unsigned long arg) { + return ioctl_by_bdev(s->s_bdev, cmd, arg); +} + +/************************/