diff -urN linux-2.4.19-pre7/fs/Config.in linux-2419p7-cdfs05c/fs/Config.in --- linux-2.4.19-pre7/fs/Config.in Sun Apr 21 17:43:53 2002 +++ linux-2419p7-cdfs05c/fs/Config.in Sun Apr 28 15:24:48 2002 @@ -28,6 +28,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 linux-2.4.19-pre7/fs/Makefile linux-2419p7-cdfs05c/fs/Makefile --- linux-2.4.19-pre7/fs/Makefile Sun Mar 3 17:17:08 2002 +++ linux-2419p7-cdfs05c/fs/Makefile Sun Apr 28 15:24:48 2002 @@ -33,6 +33,7 @@ subdir-$(CONFIG_CRAMFS) += cramfs subdir-$(CONFIG_RAMFS) += ramfs subdir-$(CONFIG_CODA_FS) += coda +subdir-$(CONFIG_CDFS_FS) += cdfs subdir-$(CONFIG_INTERMEZZO_FS) += intermezzo subdir-$(CONFIG_MINIX_FS) += minix subdir-$(CONFIG_FAT_FS) += fat diff -urN linux-2.4.19-pre7/fs/cdfs/Makefile linux-2419p7-cdfs05c/fs/cdfs/Makefile --- linux-2.4.19-pre7/fs/cdfs/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/Makefile Sun Apr 28 15:25:00 2002 @@ -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 +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -urN linux-2.4.19-pre7/fs/cdfs/audio.c linux-2419p7-cdfs05c/fs/cdfs/audio.c --- linux-2.4.19-pre7/fs/cdfs/audio.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/audio.c Sun Apr 28 15:24:48 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 linux-2.4.19-pre7/fs/cdfs/cdXA.c linux-2419p7-cdfs05c/fs/cdfs/cdXA.c --- linux-2.4.19-pre7/fs/cdfs/cdXA.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/cdXA.c Sun Apr 28 15:24:48 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 = CD_FRAMESIZE_RAW0; + } + + 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 linux-2.4.19-pre7/fs/cdfs/cddata.c linux-2419p7-cdfs05c/fs/cdfs/cddata.c --- linux-2.4.19-pre7/fs/cdfs/cddata.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/cddata.c Sun Apr 28 15:24:48 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 linux-2.4.19-pre7/fs/cdfs/cdfs.h linux-2419p7-cdfs05c/fs/cdfs/cdfs.h --- linux-2.4.19-pre7/fs/cdfs/cdfs.h Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/cdfs.h Sun Apr 28 15:25:00 2002 @@ -0,0 +1,184 @@ +/* +#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 + + +#ifndef __KERNEL__ +#define MODULE +#define __KERNEL__ +#endif + +#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; +} 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; + +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 linux-2.4.19-pre7/fs/cdfs/daemon.c linux-2419p7-cdfs05c/fs/cdfs/daemon.c --- linux-2.4.19-pre7/fs/cdfs/daemon.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/daemon.c Sun Apr 28 15:24:48 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 + + + 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*)page_address(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*)page_address(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*)page_address(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*)page_address(page)); + break; + } + + SetPageUptodate(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 linux-2.4.19-pre7/fs/cdfs/discid.c linux-2419p7-cdfs05c/fs/cdfs/discid.c --- linux-2.4.19-pre7/fs/cdfs/discid.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/discid.c Sun Apr 28 15:25:00 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 linux-2.4.19-pre7/fs/cdfs/hfs.c linux-2419p7-cdfs05c/fs/cdfs/hfs.c --- linux-2.4.19-pre7/fs/cdfs/hfs.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/hfs.c Sun Apr 28 15:24:48 2002 @@ -0,0 +1,200 @@ +/* + + 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; + 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; + + } +}; + +/***************************************************************************/ + +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 linux-2.4.19-pre7/fs/cdfs/iso.c linux-2419p7-cdfs05c/fs/cdfs/iso.c --- linux-2.4.19-pre7/fs/cdfs/iso.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/iso.c Sun Apr 28 15:24:48 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 linux-2.4.19-pre7/fs/cdfs/proc.c linux-2419p7-cdfs05c/fs/cdfs/proc.c --- linux-2.4.19-pre7/fs/cdfs/proc.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/proc.c Sun Apr 28 15:24:48 2002 @@ -0,0 +1,115 @@ +/* + + 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. + +*/ + + +#include "cdfs.h" + +cd * cdfs_proc_cd; + +struct proc_dir_entry * cdfs_proc_entry; + +int cdfs_read_proc(char *buf, char **start, off_t offset, + int len, int *eof, void *data ){ + + int t,i; + struct _track_info * track; + char proc_info[4096]; + char * proc_counter = proc_info; + char MSFsize[10]; + + + if (!cdfs_proc_cd) { + + proc_counter+=sprintf(proc_counter, "[%s\t%s]\n\tNo CD mounted\n", + FSNAME, VERSION); + + } else { + + proc_counter+=sprintf(proc_counter, + "[%s\t%s]\n\nCD (discid=%08X) contains %d track%s:\n\n", + FSNAME, VERSION, cdfs_proc_cd->discid, cdfs_proc_cd->tracks, + cdfs_proc_cd->tracks-1 ? "s" : ""); + + /* add stuff here */ + + for (t=0; ttracks; t++) { + i=T2I(t); + proc_counter+=sprintf(proc_counter,"\n"); + track = &cdfs_proc_cd->track[i]; + if (track->type == DATA) { + if (track->iso_size) { /* DATA & ISO */ + proc_counter+=sprintf(proc_counter,"Track %2d: data track (%s), [%d-%d/%d], length=%d MB\n", + t+1, track->name, track->start_lba, track->iso_size/2048, + track->stop_lba, track->track_size/1024/1024); + proc_counter+=sprintf(proc_counter, + "\ttype: %c info: %.5s version: %c\n" + "\tdate: %.2s/%.2s/%.4s time: %.2s:%.2s:%.2s\n" + "\tsystem: %.32s\n\tvolume: %.32s\n", + track->iso_info->type[0]+48, + track->iso_info->id, + track->iso_info->version[0]+48, + track->iso_info->creation_date+6, + track->iso_info->creation_date+4, + track->iso_info->creation_date, + track->iso_info->creation_date+8, + track->iso_info->creation_date+10, + track->iso_info->creation_date+12, + track->iso_info->system_id, + track->iso_info->volume_id + ); + proc_counter+=sprintf(proc_counter, "\tpublisher: %.128s\n", track->iso_info->publisher_id); + proc_counter-=2; while (*--proc_counter==' ') ; proc_counter+=2; *proc_counter++='\n'; + proc_counter+=sprintf(proc_counter, "\tpreparer: %.128s\n", track->iso_info->preparer_id); + proc_counter-=2; while (*--proc_counter==' ') ; proc_counter+=2; *proc_counter++='\n'; + proc_counter+=sprintf(proc_counter, "\tapplication: %.128s\n", track->iso_info->application_id); + proc_counter-=2; while (*--proc_counter==' ') ; proc_counter+=2; *proc_counter++='\n'; + proc_counter+=sprintf(proc_counter, "\tlength: %d MB / %d MB / %d MB / %d MB\n", + (track->iso_size-track->start_lba*CD_FRAMESIZE)/1024/1024, + track->track_size/1024/1024, + track->iso_size/1024/1024, + track->size/1024/1024); + } else { /* DATA, geen ISO */ + proc_counter+=sprintf(proc_counter,"Track %2d: data track (%s), [%d-%d], length=%d kB\n", + t+1, track->name, track->start_lba, track->stop_lba, track->track_size/1024); + proc_counter+=sprintf(proc_counter, "\ttype: %s\n", cdfs_proc_cd->videocd_type); + proc_counter+=sprintf(proc_counter, "\ttitle: %s\n", cdfs_proc_cd->videocd_title); + proc_counter+=sprintf(proc_counter, "\tframesize: %d B\n", track->xa_data_size); + } + } else if (track->type==BOOT) { + proc_counter+=sprintf(proc_counter,"Bootimage (%s), [%d-%d], length=%d kB\n\tID string:%s\n", + track->name, track->start_lba, track->stop_lba, track->size/1024, track->bootID); + } else if (track->type==HFS) { + proc_counter+=sprintf(proc_counter,"Apple HFS (%s), [%d-%d], length=%d MB\n\tID string:%s\n", + track->name, track->start_lba, track->stop_lba, track->size/1024/1024, track->bootID); + } else if (track->type==AUDIO) { + cdfs_constructMSFsize(MSFsize, track->size); + proc_counter+=sprintf(proc_counter,"Track %2d: audio track (%s), [%8d -%8d], length=%s\n", + t+1, track->name, track->start_lba, track->stop_lba, MSFsize); + } + } + } + + strncpy(buf, proc_info, proc_counter-proc_info); + return proc_counter-proc_info; +} diff -urN linux-2.4.19-pre7/fs/cdfs/root.c linux-2419p7-cdfs05c/fs/cdfs/root.c --- linux-2.4.19-pre7/fs/cdfs/root.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/root.c Sun Apr 28 15:24:48 2002 @@ -0,0 +1,494 @@ +/* + + 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 + +/********************************************************************/ + +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; + + // 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); + + if (cdfs_ioctl(sb, CDROMREADTOCHDR, (unsigned long)&hdr)){ + printk("ioctl(CDROMREADTOCHDR) failed\n"); + MOD_DEC_USE_COUNT; + return NULL; + } + + this_cd->nr_iso_sessions = 0; + this_cd->size = 0; + 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); + + /* 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[1].start_lba=0; + + /* 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 (entry.cdte_ctrl & CDROM_DATA_TRACK) { + no_data++; + this_cd->track[i].iso_info = cdfs_get_iso_info(sb, i); + this_cd->track[i].type = DATA; + 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++; + } else { /* DATA, but no ISO -> we suppose it's a VideoCD */ + 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 { + 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); + + 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->read_proc = cdfs_read_proc; + 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 ((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 linux-2.4.19-pre7/fs/cdfs/utils.c linux-2419p7-cdfs05c/fs/cdfs/utils.c --- linux-2.4.19-pre7/fs/cdfs/utils.c Thu Jan 1 01:00:00 1970 +++ linux-2419p7-cdfs05c/fs/cdfs/utils.c Sun Apr 28 15:24:48 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); +} + +/************************/