You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(2) |
Feb
(39) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(4) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Ben O. <ben...@us...> - 2003-08-03 23:14:12
|
Update of /cvsroot/njbfs/njbfs In directory sc8-pr-cvs1:/tmp/cvs-serv4454 Added Files: Tag: ben njbfs_id3.c njbfs_id3.h Log Message: Ben: get it compilable again --- NEW FILE: njbfs_id3.c --- /* * Nomad Jukebox filesystem for Linux. * * Copyright (C) 2001 Jörg Prante <joe...@gm...> * Copyright (C) 2002 Ben Osheroff <be...@gi...> * * based on ftpfs by Florin Malita <fm...@ya...> * * 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 of the * License, 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 <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/types.h> #include <linux/usb.h> #include "njbfs.h" #include "njbfs_id3.h" #include "proc.h" #include "mpg123/id3.h" int write_id3v2_frame(char *buf, char *id, char *val, off_t left) { u_int32_t size; int i, count = 0; if ( left < 11 ) return -ENOMEM; for (i = 0; i < 4; i++, count++) { buf[count] = id[i]; } size = __cpu_to_be32((u_int32_t) strlen(val) + 1); memcpy((void *) buf + count, &size, 4); count += 4; /* defaults for frame header tag, zero */ buf[count++] = 0x0; buf[count++] = 0x0; /* this signifies iso-whatever (standard) encoding */ buf[count++] = 0x0; for (i = 0; val[i]; i++) { if ( left - count <= 0 ) return -ENOMEM; buf[count++] = val[i]; } return count; } int write_id3v2_frame_numeric(char *buf, char *id, u_int32_t val, off_t left) { static char vbuf[80]; sprintf(vbuf, "%u", val); return write_id3v2_frame(buf, id, vbuf, left); } #define WRITE_ID3_FRAME(buf, title, val, bufleft) \ if ( val ) { \ int status = write_id3v2_frame(buf, title, val, bufleft); \ if ( status > 0 ) { \ buf += status; bufleft -=status; \ } else \ return status; \ } #define WRITE_ID3_FRAME_NUMERIC(buf, title, val, bufleft) \ if ( val ) { \ int status = write_id3v2_frame_numeric(buf, title, val, bufleft); \ if ( status > 0 ) { \ buf += status; bufleft -= status; \ } else \ return status; \ } /* * create a "fake" id3v2 tag based on the file given. * TODO: bounds checking on the buffer */ int create_id3v2_tag(struct njbfs_fattr *fattr, char *buffer, off_t bufsize) { off_t bufleft; u_int32_t size; int i; char *p; if ( bufsize < 10 ) return -ENOMEM; memset(buffer, 0, bufsize); strcat(buffer, "ID3"); /* set to version 2.3.0 */ buffer[3] = 0x03; buffer[4] = 0x00; /* all id3 flags empty */ buffer[5] = 0x00; /* * for now, leave bytes 6-9 empty: these are the size * bytes, and we'll know about the size later */ p = buffer + 10; bufleft = bufsize - 10; WRITE_ID3_FRAME(p, "TPE1", fattr->artist, bufleft); WRITE_ID3_FRAME(p, "TIT2", fattr->title, bufleft); WRITE_ID3_FRAME(p, "TALB", fattr->album, bufleft); WRITE_ID3_FRAME(p, "TCON", fattr->genre, bufleft); WRITE_ID3_FRAME_NUMERIC(p, "TRCK", fattr->tracknum, bufleft); WRITE_ID3_FRAME_NUMERIC(p, "TYER", fattr->year, bufleft); WRITE_ID3_FRAME_NUMERIC(p, "TLEN", fattr->length * 1000, bufleft); /* add 100 bytes of padding for future tags */ size = ((p - buffer) - 10) + 100; /* id3 uses a 28 bit number for tag size. how odd. */ for (i = 0; i <= 4; i++) { buffer[9 - i] = (char) size & 0x7F; size >>= 7; } return 0; } int create_id3v1_tag(struct njbfs_fattr *fattr, char *buffer, off_t bufsize) { struct id3v1tag_t tag; /* * pointer to location in buffer where we want to create the tag */ char *p = (buffer + bufsize) - 128; memset(buffer, 0, bufsize); memset(&tag, 0, sizeof(struct id3v1tag_t)); strcpy(tag.tag, "TAG"); if ( fattr->artist ) strncpy(tag.artist, fattr->artist, 30); if ( fattr->title ) strncpy(tag.title, fattr->title, 30); if ( fattr->album ) strncpy(tag.album, fattr->album, 30); if ( fattr->year ) memcpy(tag.year, &fattr->year, 4); if ( fattr->tracknum ) memcpy(&tag.track_number, &fattr->tracknum, 1); memcpy(p, &tag, sizeof(struct id3v1tag_t)); return 0; } int njbfs_id3frame_to_fattr(id3_frame_t *frame, struct njbfs_fattr *fattr) { char *str = NULL; if ( id3_frame_is_text(frame) ) SAFE_STRDUP(str, frame->fr_data + 1); switch(frame->fr_desc->fd_id) { case ID3_TPE1: fattr->artist = str; break; case ID3_TRCK: fattr->tracknum = simple_strtol(str, NULL, 0); kfree(str); break; case ID3_TALB: fattr->album = str; break; case ID3_TIT2: fattr->title = str; break; case ID3_TCON: fattr->genre = str; break; case ID3_TLEN: /* length in milliseconds, convert to length in seconds */ fattr->length = simple_strtol(str, NULL, 0) / 1000; kfree(str); break; } return 0; } int read_from_block_cache(struct njbfs_fattr *f, off_t start, off_t needed, void *buf) { struct njbfs_block *block; off_t blocksize, copy, pos = start; while(pos - start < needed ) { block = find_in_block_cache(f->bl_wcache, pos); if ( !block ) /* not enough data, or non-contiguous data. */ return 0; blocksize = block->size; if ( (pos - start) + blocksize > needed ) { copy = needed - ( pos - start); } else copy = blocksize; memcpy(buf + pos, block->buffer, copy); pos += copy; } return 1; } /* * Reads in an ID3v2 tag from the fattr's block cache */ void * read_id3v2_tag(struct njbfs_fattr *f, off_t *size) { int i; void *tagdata; static char hdrbuf[10]; uint32_t tagsize = 0; /* grab the ID3 header (10 bytes) */ if (!read_from_block_cache(f, 0, 10, hdrbuf)) return NULL; if ( strncmp(hdrbuf, "ID3", 3) != 0 ) return NULL; /* get the size out of the tag. */ for(i=6; i < 10; i++) tagsize = ((tagsize << 7) | (hdrbuf[i] & ((1 << 7) - 1))); dbg("id3: tagsize reports as %u", tagsize); tagsize += 10; tagdata = kmalloc(tagsize, GFP_KERNEL); if (!tagdata) { err("kmalloc error"); return NULL; } if ( !read_from_block_cache(f, 0, tagsize, tagdata) ) { err("incomplete id3 tag written"); return NULL; } *size = tagsize; return tagdata; } off_t njbfs_process_id3v2_tag(struct njbfs_fattr *f, void *id3data) { struct list_head *list; id3_t *id3tag; id3_frame_t *id3frame; dbg("passing it into open_mem"); /* pass the coagulated buffer into the id3 parser */ id3tag = id3_open_mem(id3data, 0); kfree(id3data); if ( !id3tag ) return 0; /* loop through the frames in the tag, and add them to our fattr structure */ list_for_each(list, &id3tag->id3_frame) { id3frame = list_entry(list, id3_frame_t, fr_list); njbfs_id3frame_to_fattr(id3frame, f); } id3_close(id3tag); return 1; } /* gets an id3 tag from the block_cache of the specified fattr, and sets fattr->artist, fattr->album, etc. accordingly. This is the glue code into the code in /mpg123. TODO: add id3v1 parsing BUGS: Software *might* re-write just part of the id3 header (4096-8192) and we'd be screwed. Although this seems unlikely. returns 0 if no valid id3 tag was found, or the size of the id3 tag if found. */ off_t njbfs_parse_id3(struct njbfs_fattr *f) { off_t size; void *id3data; int status; id3data = read_id3v2_tag(f, &size); if ( !id3data ) return 0; else { status = njbfs_process_id3v2_tag(f, id3data); if ( status ) return size; else return 0; } } --- NEW FILE: njbfs_id3.h --- #ifndef _NJBFS_ID3_H #define _NJBFS_ID3_H struct id3v1tag_t { char tag[3]; /* always "TAG": defines ID3v1 tag 128 bytes before EOF */ char title[30]; char artist[30]; char album[30]; char year[4]; char comment[28]; char __zero; unsigned char track_number; unsigned char genre; }; off_t njbfs_parse_id3(struct njbfs_fattr *); int create_id3v1_tag(struct njbfs_fattr *, char *, off_t ); int create_id3v2_tag(struct njbfs_fattr *, char *, off_t ); #endif; |
From: Ben O. <ben...@us...> - 2003-08-03 23:13:40
|
Update of /cvsroot/njbfs/njbfs In directory sc8-pr-cvs1:/tmp/cvs-serv4348 Modified Files: Tag: ben Makefile inode.c njb_usb.c nomad_usb.h track.c Log Message: Ben: get it compilable again Index: Makefile =================================================================== RCS file: /cvsroot/njbfs/njbfs/Makefile,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** Makefile 4 Sep 2002 19:08:07 -0000 1.4.2.2 --- Makefile 3 Aug 2003 23:13:36 -0000 1.4.2.3 *************** *** 33,37 **** # njbfs.o ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ./njbfs_cache.o ./njbfs_dir.o ./njbfs_id3.o mpg123/*.o ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} --- 33,41 ---- # njbfs.o ! mpg123: mpg123/*.c ! (cd mpg123 ; make) ! ! ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ./njbfs_cache.o ./njbfs_dir.o ./njbfs_id3.o mpg123 ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} Index: inode.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/inode.c,v retrieving revision 1.5.2.3 retrieving revision 1.5.2.4 diff -C2 -d -r1.5.2.3 -r1.5.2.4 *** inode.c 4 Sep 2002 19:08:08 -0000 1.5.2.3 --- inode.c 3 Aug 2003 23:13:36 -0000 1.5.2.4 *************** *** 190,194 **** init_timer(&info->njb->release.timer); init_timer(&info->njb->release.urb_timer); ! info->njb->release.dr = kmalloc(sizeof(devrequest), GFP_KERNEL); info->njb->release.njbstate = kmalloc(sizeof(char) * 1, GFP_KERNEL); info->njb->release.urb = usb_alloc_urb(0); --- 190,194 ---- init_timer(&info->njb->release.timer); init_timer(&info->njb->release.urb_timer); ! info->njb->release.dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); info->njb->release.njbstate = kmalloc(sizeof(char) * 1, GFP_KERNEL); info->njb->release.urb = usb_alloc_urb(0); Index: njb_usb.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.c,v retrieving revision 1.4.2.5 retrieving revision 1.4.2.6 diff -C2 -d -r1.4.2.5 -r1.4.2.6 *** njb_usb.c 4 Sep 2002 19:08:08 -0000 1.4.2.5 --- njb_usb.c 3 Aug 2003 23:13:36 -0000 1.4.2.6 *************** *** 673,677 **** { struct nomad_usb_data *njb = (struct nomad_usb_data *) data; ! devrequest *dr; struct urb *urb; --- 673,677 ---- { struct nomad_usb_data *njb = (struct nomad_usb_data *) data; ! struct usb_ctrlrequest *dr; struct urb *urb; *************** *** 703,711 **** } ! dr->requesttype = UT_READ | USB_TYPE_VENDOR | USB_RECIP_OTHER; ! dr->request = NJB_CMD_RELEASE_NJB; ! dr->value = cpu_to_le16p(&value); ! dr->index = cpu_to_le16p(&index); ! dr->length = cpu_to_le16p(&length); usb_fill_control_urb(urb, njb->nomad_dev, --- 703,711 ---- } ! dr->bRequestType = UT_READ | USB_TYPE_VENDOR | USB_RECIP_OTHER; ! dr->bRequest = NJB_CMD_RELEASE_NJB; ! dr->wValue = cpu_to_le16p(&value); ! dr->wIndex = cpu_to_le16p(&index); ! dr->wLength = cpu_to_le16p(&length); usb_fill_control_urb(urb, njb->nomad_dev, Index: nomad_usb.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/nomad_usb.h,v retrieving revision 1.4.2.3 retrieving revision 1.4.2.4 diff -C2 -d -r1.4.2.3 -r1.4.2.4 *** nomad_usb.h 4 Sep 2002 19:08:09 -0000 1.4.2.3 --- nomad_usb.h 3 Aug 2003 23:13:37 -0000 1.4.2.4 *************** *** 74,78 **** struct timer_list urb_timer; struct urb *urb; ! devrequest *dr; char *njbstate; }; --- 74,78 ---- struct timer_list urb_timer; struct urb *urb; ! struct usb_ctrlrequest *dr; char *njbstate; }; Index: track.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/track.c,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** track.c 4 Sep 2002 19:08:09 -0000 1.4.2.2 --- track.c 3 Aug 2003 23:13:37 -0000 1.4.2.3 *************** *** 71,74 **** --- 71,75 ---- memcpy(&nframes, dp, 2); nframes = le16_to_cpu(nframes); + dbg("nframes=%d", nframes); index = 2; *************** *** 83,92 **** memcpy(&lsize, &dp[index], 2); ! lsize = le16_to_cpu(type); index += 2; dbg("lsize=%d", lsize); memcpy(&vsize, &dp[index], 4); ! vsize = le32_to_cpu(type); index += 4; dbg("vsize=%d", vsize); --- 84,93 ---- memcpy(&lsize, &dp[index], 2); ! lsize = le16_to_cpu(lsize); index += 2; dbg("lsize=%d", lsize); memcpy(&vsize, &dp[index], 4); ! vsize = le32_to_cpu(vsize); index += 4; dbg("vsize=%d", vsize); |
From: Ben O. <ben...@us...> - 2003-08-03 23:10:45
|
Update of /cvsroot/njbfs/njbfs/mpg123 In directory sc8-pr-cvs1:/tmp/cvs-serv3804 Added Files: Tag: ben Makefile README id3.c id3.h id3_frame.c id3_frame_content.c id3_frame_text.c id3_frame_url.c id3_header.h id3_tag.c mpg123.c mpg123.h Log Message: Ben: add id3 support files --- NEW FILE: Makefile --- MYCODEDIR := . MODULESDIR = /lib/modules/$(shell uname -r) # Directories to search for header files SEARCHDIRS := -I- -I${MYCODEDIR} -I/usr/src/linux/include # makemake variables DEPENDFLAGS := -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -mpreferred-stack-boundary=2 -Wall ${SEARCHDIRS} -DMODULE -D__KERNEL__ -DLINUX -DEXPORT_SYMTAB # C preprocessor CPPFLAGS = # C compiler CC := gcc CFLAGS = ${DEPENDFLAGS} -DDEBUG %.o : %.c ${CC} ${CPPFLAGS} ${CFLAGS} -c $< -o $@ # C linker LINKER := ld LDFLAGS = -m elf_i386 -r LOADLIBES := # target for making everything .PHONY : all all: id3.o id3_frame.o id3_frame_content.o id3_frame_text.o id3_frame_url.o id3_tag.o mpg123.o # list of all source files MM_ALL_SOURCES := ./automount.c ./nomad.c ./cache.c ./dir.c ./file.c ./inode.c ./proc.c ./symlink.c ./njb_usb.c ./track.c ./playlist.c ./driver.c # target for checking a source file CHECKSYNTAXFILE := ${basename ${filter %${CHECKSTRING}, ${MM_ALL_SOURCES}}} .PHONY : checksyntax checksyntax: ifneq (${CHECKSYNTAXFILE},) @${MAKE} ${addsuffix .o, ${CHECKSYNTAXFILE}} else @echo No target to make ${CHECKSTRING} endif # target for touching appropriate source files .PHONY : touch touch:: @list=$$(grep -l ${TOUCHSTRING} ${MM_ALL_SOURCES}); \ for file in $$list; do { echo $$file; touch $$file; } done --- NEW FILE: README --- This is the source liberally stolen and modified to work as a kernel module. We originally grabbed it from the Inputs/Plugins/mp3 directory in the xmms source distro. Since the id3v2 source isn't patented (and is GPL'ed), there shouldn't be any licensing problems. Note about the mpg123 license! We have permission to release mpg123 source inside xmms as GPL! Using mpg123 source (at least in a commercial environment) may infringe 3rd party patents. Also Michael Hipp (hi...@in...) would like to know if you modify this sourcecode. Send him an email if you do, he would like to have an eye on external developments. Happy playing! --- NEW FILE: id3.c --- /********************************************************************* * * Copyright (C) 1999, 2001, Espen Skoglund * Department of Computer Science, University of Tromsø * * Modified 2002 Ben Osheroff for integration to njbfs * * Filename: id3.c * Description: Code for accessing ID3 tags. * Author: Espen Skoglund <es...@st...> * Created at: Fri Feb 5 23:55:13 1999 * * $Id: id3.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include "id3.h" #include "id3_header.h" /* ** ** Functions for accessing the ID3 tag using a memory pointer. ** */ /* * Function id3_seek_mem (id3, offset) * * Seek `offset' bytes forward in the indicated ID3-tag. Return 0 * upon success, or -1 if an error occured. * */ static int id3_seek_mem(id3_t * id3, int offset) { if (id3->id3_pos + offset > id3->id3_tagsize || id3->id3_pos + offset < 0) { id3_error(id3, "seeking beyond tag boundary"); return -1; } id3->s.me.id3_ptr = (char *) id3->s.me.id3_ptr + offset; id3->id3_pos += offset; return 0; } /* * Function id3_read_mem (id3, buf, size) * * Read `size' bytes from indicated ID3-tag. If `buf' is non-NULL, * read into that buffer. Return a pointer to the data which was * read, or NULL upon error. * */ static void *id3_read_mem(id3_t * id3, void *buf, int size) { void *ret = id3->s.me.id3_ptr; /* * Check boundary. */ if (id3->id3_pos + size > id3->id3_tagsize) { size = id3->id3_tagsize - id3->id3_pos; } /* * If buffer is non-NULL, we have to copy the data. */ if (buf != NULL) memcpy(buf, id3->s.me.id3_ptr, size); /* * Update memory pointer. */ id3->s.me.id3_ptr = (char *) id3->s.me.id3_ptr + size; id3->id3_pos += size; return ret; } /* * Function id3_open_mem (ptr, flags) * * Open an ID3 tag using a memory pointer. Return a pointer to a * structure describing the ID3 tag, or NULL if an error occured. * */ id3_t *id3_open_mem(void *ptr, int flags) { id3_t *id3; /* * Allocate ID3 structure. */ id3 = kmalloc(sizeof(id3_t), GFP_KERNEL); memset(id3, 0, sizeof(id3_t)); /* * Initialize access pointers. */ id3->id3_seek = id3_seek_mem; id3->id3_read = id3_read_mem; id3->id3_oflags = flags; id3->id3_type = ID3_TYPE_MEM; id3->id3_pos = 0; id3->s.me.id3_ptr = ptr; /* * Try reading ID3 tag. */ if (id3_read_tag(id3) == -1) { if (~flags & ID3_OPENF_CREATE) goto Return_NULL; id3_init_tag(id3); } return id3; Return_NULL: kfree(id3); return NULL; } /* * Function id3_close (id3) * * Free all resources assoicated with the ID3 tag. * */ int id3_close(id3_t * id3) { id3_destroy_frames(id3); kfree(id3); return 0; } /* * Function id3_tell (id3) * * Return the current position in ID3 tag. This will always be * directly after the tag. * */ int id3_tell(id3_t * id3) { if (id3->id3_newtag) { return 0; } else { return id3->id3_tagsize + 3 + sizeof(id3_taghdr_t); } } /* * Function id3_alter_file (id3) * * When altering a file, some ID3 tags should be discarded. As the ID3 * library has no means of knowing when a file has been altered * outside of the library, this function must be called manually * whenever the file is altered. * */ int id3_alter_file(id3_t * id3) { /* * List of frame classes that should be discarded whenever the * file is altered. */ static uint32_t discard_list[] = { ID3_ETCO, ID3_EQUA, ID3_MLLT, ID3_POSS, ID3_SYLT, ID3_SYTC, ID3_RVAD, ID3_TENC, ID3_TLEN, ID3_TSIZ, 0 }; id3_frame_t *fr; uint32_t id, i = 0; /* * Go through list of frame types that should be discarded. */ while ((id = discard_list[i++]) != 0) { /* * Discard all frames of that type. */ while ((fr = id3_get_frame(id3, id, 1))) { id3_delete_frame(fr); } } return 0; } EXPORT_SYMBOL(id3_open_mem); --- NEW FILE: id3.h --- /********************************************************************* * * Copyright (C) 1998, 1999, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3.h * Description: Include file for accessing the ID3 library. * Author: Espen Skoglund <es...@st...> * Created at: Thu Nov 5 15:55:10 1998 * * $Id: id3.h,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #ifndef ID3_H #define ID3_H #include <linux/list.h> #include <linux/types.h> /* * Option flags to id3_open_*(). */ #define ID3_OPENF_NONE 0x0000 #define ID3_OPENF_NOCHK 0x0001 #define ID3_OPENF_CREATE 0x0002 /* * The size of the read buffer used by file operations. */ #define ID3_FD_BUFSIZE 8192 typedef struct id3_t id3_t; typedef struct id3_frame_t id3_frame_t; typedef struct id3_framedesc_t id3_framedesc_t; /* * Structure describing the ID3 tag. */ struct id3_t { int id3_type; /* Memory or file desriptor */ int id3_oflags; /* Flags from open call */ int id3_flags; /* Flags from tag header */ int id3_altered; /* Set when tag has been altered */ int id3_newtag; /* Set if this is a new tag */ int id3_version; /* Major ID3 version number */ int id3_revision; /* ID3 revision number */ int id3_tagsize; /* Total size of ID3 tag */ int id3_pos; /* Current position within tag */ char *id3_error_msg; /* Last error message */ char id3_buffer[256]; /* Used for various strings */ union { /* * Memory specific fields. */ struct { void *id3_ptr; } me; } s; /* * Functions for doing operations within ID3 tag. */ int (*id3_seek) (id3_t *, int); void *(*id3_read) (id3_t *, void *, int); /* * Linked list of ID3 frames. */ struct list_head id3_frame; }; #define ID3_TYPE_NONE 0 #define ID3_TYPE_MEM 1 #define ID3_TYPE_FD 2 #define ID3_TYPE_FP 3 /* * Structure describing an ID3 frame. */ struct id3_frame_t { struct list_head fr_list; id3_t *fr_owner; id3_framedesc_t *fr_desc; int fr_flags; unsigned char fr_encryption; unsigned char fr_grouping; unsigned char fr_altered; void *fr_data; /* Pointer to frame data, excluding headers */ int fr_size; /* Size of uncompressed frame */ void *fr_raw_data; /* Frame data */ int fr_raw_size; /* Frame size */ void *fr_data_z; /* The decompressed compressed frame */ int fr_size_z; /* Size of decompressed compressed frame */ }; /* * Structure describing an ID3 frame type. */ struct id3_framedesc_t { uint32_t fd_id; char fd_idstr[4]; char *fd_description; }; /* * Text encodings. */ #define ID3_ENCODING_ISO_8859_1 0x00 #define ID3_ENCODING_UTF16 0x01 #define ID3_ENCODING_UTF16BE 0x02 #define ID3_ENCODING_UTF8 0x03 /* * ID3 frame id numbers. */ #define ID3_FRAME_ID(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d) #define ID3_AENC ID3_FRAME_ID('A','E','N','C') #define ID3_APIC ID3_FRAME_ID('A','P','I','C') #define ID3_COMM ID3_FRAME_ID('C','O','M','M') #define ID3_COMR ID3_FRAME_ID('C','O','M','R') #define ID3_ENCR ID3_FRAME_ID('E','N','C','R') #define ID3_EQUA ID3_FRAME_ID('E','Q','U','A') #define ID3_ETCO ID3_FRAME_ID('E','T','C','O') #define ID3_GEOB ID3_FRAME_ID('G','E','O','B') #define ID3_GRID ID3_FRAME_ID('G','R','I','D') #define ID3_IPLS ID3_FRAME_ID('I','P','L','S') #define ID3_LINK ID3_FRAME_ID('L','I','N','K') #define ID3_MCDI ID3_FRAME_ID('M','C','D','I') #define ID3_MLLT ID3_FRAME_ID('M','L','L','T') #define ID3_OWNE ID3_FRAME_ID('O','W','N','E') #define ID3_PRIV ID3_FRAME_ID('P','R','I','V') #define ID3_PCNT ID3_FRAME_ID('P','C','N','T') #define ID3_POPM ID3_FRAME_ID('P','O','P','M') #define ID3_POSS ID3_FRAME_ID('P','O','S','S') #define ID3_RBUF ID3_FRAME_ID('R','B','U','F') #define ID3_RVAD ID3_FRAME_ID('R','V','A','D') #define ID3_RVRB ID3_FRAME_ID('R','V','R','B') #define ID3_SYLT ID3_FRAME_ID('S','Y','L','T') #define ID3_SYTC ID3_FRAME_ID('S','Y','T','C') #define ID3_TALB ID3_FRAME_ID('T','A','L','B') #define ID3_TBPM ID3_FRAME_ID('T','B','P','M') #define ID3_TCOM ID3_FRAME_ID('T','C','O','M') #define ID3_TCON ID3_FRAME_ID('T','C','O','N') #define ID3_TCOP ID3_FRAME_ID('T','C','O','P') #define ID3_TDAT ID3_FRAME_ID('T','D','A','T') #define ID3_TDLY ID3_FRAME_ID('T','D','L','Y') #define ID3_TENC ID3_FRAME_ID('T','E','N','C') #define ID3_TEXT ID3_FRAME_ID('T','E','X','T') #define ID3_TFLT ID3_FRAME_ID('T','F','L','T') #define ID3_TIME ID3_FRAME_ID('T','I','M','E') #define ID3_TIT1 ID3_FRAME_ID('T','I','T','1') #define ID3_TIT2 ID3_FRAME_ID('T','I','T','2') #define ID3_TIT3 ID3_FRAME_ID('T','I','T','3') #define ID3_TKEY ID3_FRAME_ID('T','K','E','Y') #define ID3_TLAN ID3_FRAME_ID('T','L','A','N') #define ID3_TLEN ID3_FRAME_ID('T','L','E','N') #define ID3_TMED ID3_FRAME_ID('T','M','E','D') #define ID3_TOAL ID3_FRAME_ID('T','O','A','L') #define ID3_TOFN ID3_FRAME_ID('T','O','F','N') #define ID3_TOLY ID3_FRAME_ID('T','O','L','Y') #define ID3_TOPE ID3_FRAME_ID('T','O','P','E') #define ID3_TORY ID3_FRAME_ID('T','O','R','Y') #define ID3_TOWN ID3_FRAME_ID('T','O','W','N') #define ID3_TPE1 ID3_FRAME_ID('T','P','E','1') #define ID3_TPE2 ID3_FRAME_ID('T','P','E','2') #define ID3_TPE3 ID3_FRAME_ID('T','P','E','3') #define ID3_TPE4 ID3_FRAME_ID('T','P','E','4') #define ID3_TPOS ID3_FRAME_ID('T','P','O','S') #define ID3_TPUB ID3_FRAME_ID('T','P','U','B') #define ID3_TRCK ID3_FRAME_ID('T','R','C','K') #define ID3_TRDA ID3_FRAME_ID('T','R','D','A') #define ID3_TRSN ID3_FRAME_ID('T','R','S','N') #define ID3_TRSO ID3_FRAME_ID('T','R','S','O') #define ID3_TSIZ ID3_FRAME_ID('T','S','I','Z') #define ID3_TSRC ID3_FRAME_ID('T','S','R','C') #define ID3_TSSE ID3_FRAME_ID('T','S','S','E') #define ID3_TYER ID3_FRAME_ID('T','Y','E','R') #define ID3_TXXX ID3_FRAME_ID('T','X','X','X') #define ID3_UFID ID3_FRAME_ID('U','F','I','D') #define ID3_USER ID3_FRAME_ID('U','S','E','R') #define ID3_USLT ID3_FRAME_ID('U','S','L','T') #define ID3_WCOM ID3_FRAME_ID('W','C','O','M') #define ID3_WCOP ID3_FRAME_ID('W','C','O','P') #define ID3_WOAF ID3_FRAME_ID('W','O','A','F') #define ID3_WOAR ID3_FRAME_ID('W','O','A','R') #define ID3_WOAS ID3_FRAME_ID('W','O','A','S') #define ID3_WORS ID3_FRAME_ID('W','O','R','S') #define ID3_WPAY ID3_FRAME_ID('W','P','A','Y') #define ID3_WPUB ID3_FRAME_ID('W','P','U','B') #define ID3_WXXX ID3_FRAME_ID('W','X','X','X') /* * Prototypes. */ /* From id3.c */ id3_t *id3_open_mem(void *, int); int id3_set_output(id3_t *, char *); int id3_close(id3_t *); int id3_tell(id3_t *); int id3_alter_file(id3_t *); int id3_write_tag(id3_t *, int); /* From id3_frame.c */ int id3_read_frame(id3_t * id3); id3_frame_t *id3_get_frame(id3_t *, uint32_t, int); int id3_delete_frame(id3_frame_t * frame); id3_frame_t *id3_add_frame(id3_t *, uint32_t); int id3_decompress_frame(id3_frame_t *); void id3_destroy_frames(id3_t * id); void id3_frame_clear_data(id3_frame_t * frame); /* From id3_frame_text.c */ int8_t id3_get_encoding(id3_frame_t *); int id3_set_encoding(id3_frame_t *, int8_t); char *id3_get_text(id3_frame_t *); char *id3_get_text_desc(id3_frame_t *); int id3_get_text_number(id3_frame_t *); int id3_set_text(id3_frame_t *, char *); int id3_set_text_number(id3_frame_t *, int); int id3_frame_is_text(id3_frame_t *); /* From id3_frame_content.c */ char *id3_get_content(id3_frame_t *); /* From id3_frame_url.c */ char *id3_get_url(id3_frame_t *); char *id3_get_url_desc(id3_frame_t *); /* From id3_tag.c */ void id3_init_tag(id3_t * id3); int id3_read_tag(id3_t * id3); #endif /* ID3_H */ --- NEW FILE: id3_frame.c --- /********************************************************************* * * Copyright (C) 1999-2000, 2001, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3_frame.c * Description: Code for handling ID3 frames. * Author: Espen Skoglund <es...@st...> * Created at: Fri Feb 5 23:47:08 1999 * * $Id: id3_frame.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/list.h> #include "id3.h" #include "id3_header.h" static void *id3_frame_get_dataptr(id3_frame_t * frame); static int id3_frame_get_size(id3_frame_t * frame); /* * Description of all valid ID3v2 frames. */ static id3_framedesc_t Framedesc[] = { {ID3_AENC, "AENC", "Audio encryption"}, {ID3_APIC, "APIC", "Attached picture"}, {ID3_COMM, "COMM", "Comments"}, {ID3_COMR, "COMR", "Commercial frame"}, {ID3_ENCR, "ENCR", "Encryption method registration"}, {ID3_EQUA, "EQUA", "Equalization"}, {ID3_ETCO, "ETCO", "Event timing codes"}, {ID3_GEOB, "GEOB", "General encapsulated object"}, {ID3_GRID, "GRID", "Group identification registration"}, {ID3_IPLS, "IPLS", "Involved people list"}, {ID3_LINK, "LINK", "Linked information"}, {ID3_MCDI, "MCDI", "Music CD identifier"}, {ID3_MLLT, "MLLT", "MPEG location lookup table"}, {ID3_OWNE, "OWNE", "Ownership frame"}, {ID3_PRIV, "PRIV", "Private frame"}, {ID3_PCNT, "PCNT", "Play counter"}, {ID3_POPM, "POPM", "Popularimeter"}, {ID3_POSS, "POSS", "Position synchronisation frame"}, {ID3_RBUF, "RBUF", "Recommended buffer size"}, {ID3_RVAD, "RVAD", "Relative volume adjustment"}, {ID3_RVRB, "RVRB", "Reverb"}, {ID3_SYLT, "SYLT", "Synchronized lyric/text"}, {ID3_SYTC, "SYTC", "Synchronized tempo codes"}, {ID3_TALB, "TALB", "Album/Movie/Show title"}, {ID3_TBPM, "TBPM", "BPM (beats per minute)"}, {ID3_TCOM, "TCOM", "Composer"}, {ID3_TCON, "TCON", "Content type"}, {ID3_TCOP, "TCOP", "Copyright message"}, {ID3_TDAT, "TDAT", "Date"}, {ID3_TDLY, "TDLY", "Playlist delay"}, {ID3_TENC, "TENC", "Encoded by"}, {ID3_TEXT, "TEXT", "Lyricist/Text writer"}, {ID3_TFLT, "TFLT", "File type"}, {ID3_TIME, "TIME", "Time"}, {ID3_TIT1, "TIT1", "Content group description"}, {ID3_TIT2, "TIT2", "Title/songname/content description"}, {ID3_TIT3, "TIT3", "Subtitle/Description refinement"}, {ID3_TKEY, "TKEY", "Initial key"}, {ID3_TLAN, "TLAN", "Language(s)"}, {ID3_TLEN, "TLEN", "Length"}, {ID3_TMED, "TMED", "Media type"}, {ID3_TOAL, "TOAL", "Original album/movie/show title"}, {ID3_TOFN, "TOFN", "Original filename"}, {ID3_TOLY, "TOLY", "Original lyricist(s)/text writer(s)"}, {ID3_TOPE, "TOPE", "Original artist(s)/performer(s)"}, {ID3_TORY, "TORY", "Original release year"}, {ID3_TOWN, "TOWN", "File owner/licensee"}, {ID3_TPE1, "TPE1", "Lead performer(s)/Soloist(s)"}, {ID3_TPE2, "TPE2", "Band/orchestra/accompaniment"}, {ID3_TPE3, "TPE3", "Conductor/performer refinement"}, {ID3_TPE4, "TPE4", "Interpreted, remixed, or otherwise modified by"}, {ID3_TPOS, "TPOS", "Part of a set"}, {ID3_TPUB, "TPUB", "Publisher"}, {ID3_TRCK, "TRCK", "Track number/Position in set"}, {ID3_TRDA, "TRDA", "Recording dates"}, {ID3_TRSN, "TRSN", "Internet radio station name"}, {ID3_TRSO, "TRSO", "Internet radio station owner"}, {ID3_TSIZ, "TSIZ", "Size"}, {ID3_TSRC, "TSRC", "ISRC (international standard recording code)"}, {ID3_TSSE, "TSSE", "Software/Hardware and settings used for encoding"}, {ID3_TYER, "TYER", "Year"}, {ID3_TXXX, "TXXX", "User defined text information frame"}, {ID3_UFID, "UFID", "Unique file identifier"}, {ID3_USER, "USER", "Terms of use"}, {ID3_USLT, "USLT", "Unsychronized lyric/text transcription"}, {ID3_WCOM, "WCOM", "Commercial information"}, {ID3_WCOP, "WCOP", "Copyright/Legal information"}, {ID3_WOAF, "WOAF", "Official audio file webpage"}, {ID3_WOAR, "WOAR", "Official artist/performer webpage"}, {ID3_WOAS, "WOAS", "Official audio source webpage"}, {ID3_WORS, "WORS", "Official internet radio station homepage"}, {ID3_WPAY, "WPAY", "Payment"}, {ID3_WPUB, "WPUB", "Publishers official webpage"}, {ID3_WXXX, "WXXX", "User defined URL link frame"}, }; /* * Function id3_read_frame (id3) * * Read next frame from the indicated ID3 tag. Return 0 upon * success, or -1 if an error occured. * */ int id3_read_frame(id3_t * id3) { id3_framehdr_t *framehdr; id3_frame_t *frame; uint32_t id; void *p; int i; /* * Read frame header. */ framehdr = id3->id3_read(id3, NULL, sizeof(*framehdr)); if (framehdr == NULL) { printk("error reading the frame header.\n"); return -1; } /* * If we encounter an invalid frame id, we assume that there is * some padding in the header. We just skip the rest of the ID3 * tag. */ i = *((uint8_t *) &framehdr->fh_id); if (!((i >= '0' && i <= '9') || (i >= 'A' && i <= 'Z'))) { id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); return 0; } id = be32_to_cpu(framehdr->fh_id); /* * Allocate frame. */ frame = kmalloc(sizeof(*frame), GFP_KERNEL); memset(frame, 0, sizeof(*frame)); frame->fr_owner = id3; frame->fr_raw_size = be32_to_cpu(framehdr->fh_size); frame->fr_flags = be16_to_cpu(framehdr->fh_flags); /* * Determine the type of the frame. */ for (i = 0; i < sizeof(Framedesc) / sizeof(id3_framedesc_t); i++) { if (Framedesc[i].fd_id == id) { /* * Initialize frame. */ frame->fr_desc = Framedesc + i; /* * When allocating memory to hold a text frame, we * allocate 2 extra byte. This simplifies retrieval of * text strings. */ frame->fr_raw_data = kmalloc(frame->fr_raw_size + (id3_frame_is_text (frame) ? 2 : 0), GFP_KERNEL); p = id3->id3_read(id3, frame->fr_raw_data, frame->fr_raw_size); if (p == NULL) { kfree(frame->fr_raw_data); kfree(frame); return -1; } /* * Null-terminate text frames. */ if (id3_frame_is_text(frame)) { ((char *) frame->fr_raw_data)[frame->fr_raw_size] = 0; ((char *) frame->fr_raw_data)[frame->fr_raw_size + 1] = 0; } break; } } /* * Check if frame had a valid id. */ if (frame->fr_desc == NULL) { /* * No. Ignore the frame. */ if (id3->id3_seek(id3, frame->fr_raw_size) < 0) { printk("Invalid frame id: %d\n", id); kfree(frame); return -1; } return 0; } /* * Check if frame is compressed using zlib. */ if (frame->fr_flags & ID3_FHFLAG_COMPRESS) return 0; frame->fr_data = id3_frame_get_dataptr(frame); frame->fr_size = id3_frame_get_size(frame); /* * Insert frame into linked list. */ list_add(&frame->fr_list, &id3->id3_frame); return 0; } /* * Function id3_get_frame (id3, type, num) * * Search in the list of frames for the ID3-tag, and return a frame * of the indicated type. If tag contains several frames of the * indicated type, the third argument tells which of the frames to * return. * */ id3_frame_t *id3_get_frame(id3_t * id3, uint32_t type, int num) { struct list_head *node; list_for_each(node, &id3->id3_frame) { id3_frame_t *fr = list_entry(node, id3_frame_t, fr_list); if (fr->fr_desc && fr->fr_desc->fd_id == type) { if (--num <= 0) return fr; } } return NULL; } /* * Function decompress_frame(frame) * * Uncompress the indicated frame. Return 0 upon success, or -1 if * an error occured. * */ static int decompress_frame(id3_frame_t * frame) { return -1; } /* * Function id3_decompress_frame(frame) * * Check if frame is compressed, and uncompress if necessary. * Return 0 upon success, or -1 if an error occured. * */ int id3_decompress_frame(id3_frame_t * frame) { if (!(frame->fr_flags & ID3_FHFLAG_COMPRESS)) /* Frame not compressed */ return 0; if (frame->fr_data_z) /* Frame already decompressed */ return 0; /* Do decompression */ return decompress_frame(frame); } /* * Function id3_delete_frame (frame) * * Remove frame from ID3 tag and release memory ocupied by it. * */ int id3_delete_frame(id3_frame_t * frame) { struct list_head *node, *head = &frame->fr_owner->id3_frame, *match = &frame->fr_list, *found = NULL; int ret; /* * Search for frame in list. */ list_for_each(node, head) { if (node == match) { found = node; break; } } /* * Remove frame from frame list. */ if (!found) return -1; list_del(found); frame->fr_owner->id3_altered = 1; ret = 0; /* * Release memory occupied by frame. */ if (frame->fr_raw_data) kfree(frame->fr_raw_data); if (frame->fr_data_z) kfree(frame->fr_data_z); kfree(frame); return ret; } /* * Function id3_add_frame (id3, type) * * Add a new frame to the ID3 tag. Return a pointer to the new * frame, or NULL if an error occured. * */ id3_frame_t *id3_add_frame(id3_t * id3, uint32_t type) { id3_frame_t *frame; int i; /* * Allocate frame. */ frame = kmalloc(sizeof(*frame), GFP_KERNEL); memset(frame, 0, sizeof(*frame)); /* * Initialize frame */ frame->fr_owner = id3; /* * Try finding the correct frame descriptor. */ for (i = 0; i < sizeof(Framedesc) / sizeof(id3_framedesc_t); i++) { if (Framedesc[i].fd_id == type) { frame->fr_desc = &Framedesc[i]; break; } } /* * Insert frame into linked list. */ list_add(&frame->fr_list, &id3->id3_frame); id3->id3_altered = 1; return frame; } /* * Destroy all frames in an id3 tag, and free all data */ void id3_destroy_frames(id3_t * id) { struct list_head *node, *tmp; list_for_each_safe(node, tmp, &id->id3_frame) { id3_frame_t *frame = list_entry(node, id3_frame_t, fr_list); /* * Release memory occupied by frame. */ if (frame->fr_raw_data) kfree(frame->fr_raw_data); if (frame->fr_data_z) kfree(frame->fr_data_z); kfree(frame); } } int id3_frame_is_text(id3_frame_t * frame) { if (frame && frame->fr_desc && (frame->fr_desc->fd_idstr[0] == 'T' || frame->fr_desc->fd_idstr[0] == 'W')) return 1; return 0; } static int id3_frame_extra_headers(id3_frame_t * frame) { int retv = 0; /* * If frame is encrypted, we have four extra bytes in the * header. */ if (frame->fr_flags & ID3_FHFLAG_COMPRESS) retv += 4; /* * If frame is encrypted, we have one extra byte in the * header. */ if (frame->fr_flags & ID3_FHFLAG_ENCRYPT) retv += 1; /* * If frame has grouping identity, we have one extra byte in * the header. */ if (frame->fr_flags & ID3_FHFLAG_GROUP) retv += 1; return retv; } static void *id3_frame_get_dataptr(id3_frame_t * frame) { char *ptr = frame->fr_raw_data; ptr += id3_frame_extra_headers(frame); return ptr; } static int id3_frame_get_size(id3_frame_t * frame) { return frame->fr_raw_size - id3_frame_extra_headers(frame); } void id3_frame_clear_data(id3_frame_t * frame) { if (frame->fr_raw_data) kfree(frame->fr_raw_data); if (frame->fr_data_z) kfree(frame->fr_data_z); frame->fr_raw_data = NULL; frame->fr_raw_size = 0; frame->fr_data = NULL; frame->fr_size = 0; frame->fr_data_z = NULL; frame->fr_size_z = 0; } EXPORT_SYMBOL(id3_read_frame); EXPORT_SYMBOL(id3_get_frame); EXPORT_SYMBOL(id3_delete_frame); --- NEW FILE: id3_frame_content.c --- /********************************************************************* * * Copyright (C) 1999, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3_frame_content.c * Description: Code for handling ID3 content frames. * Author: Espen Skoglund <es...@st...> * Created at: Mon Feb 8 17:13:46 1999 * * $Id: id3_frame_content.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include <linux/string.h> #include "mpg123.h" #include "id3.h" /* * Function id3_get_content (frame) * * Expand content type string of frame and return it. Return NULL * upon error. * */ char *id3_get_content(id3_frame_t * frame) { char *text, *ptr; char *buffer = frame->fr_owner->id3_buffer; int spc = sizeof(frame->fr_owner->id3_buffer) - 1; /* Type check */ if (frame->fr_desc->fd_id != ID3_TCON) return NULL; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; text = (char *) frame->fr_data + 1; /* * If content is just plain text, return it. */ if (text[0] != '(') return text; /* * Expand ID3v1 genre numbers. */ ptr = buffer; while (text[0] == '(' && text[1] != '(' && spc > 0) { char *genre; int num = 0; if (text[1] == 'R' && text[2] == 'X') { text += 4; genre = " (Remix)"; if (ptr == buffer) genre++; } else if (text[1] == 'C' && text[2] == 'R') { text += 4; genre = " (Cover)"; if (ptr == buffer) genre++; } else { /* Get ID3v1 genre number */ text++; while (*text != ')') { num *= 10; num += *text++ - '0'; } text++; /* Boundary check */ if (num >= sizeof(mpg123_id3_genres) / sizeof(char *))continue; genre = (char *) mpg123_id3_genres[num]; if (ptr != buffer && spc-- > 0) *ptr++ = '/'; } /* Expand string into buffer */ while (*genre != '\0' && spc > 0) { *ptr++ = *genre++; spc--; } } /* * Add plaintext refinement. */ if (*text == '(') text++; if (*text != '\0' && ptr != buffer && spc-- > 0) *ptr++ = ' '; while (*text != '\0' && spc > 0) { *ptr++ = *text++; spc--; } *ptr = '\0'; /* * Return the expanded content string. */ return buffer; } --- NEW FILE: id3_frame_text.c --- /********************************************************************* * * Copyright (C) 1999, 2001, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3_frame_text.c * Description: Code for handling ID3 text frames. * Author: Espen Skoglund <es...@st...> * Created at: Fri Feb 5 23:50:33 1999 * * $Id: id3_frame_text.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include <linux/string.h> #include <linux/slab.h> #include <linux/module.h> #include "id3.h" #include "id3_header.h" /* * Function id3_get_encoding (frame) * * Return text encoding for frame, or -1 if frame does not have any * text encoding. * */ int8_t id3_get_encoding(id3_frame_t * frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T' && frame->fr_desc->fd_id != ID3_WXXX && frame->fr_desc->fd_id != ID3_IPLS && frame->fr_desc->fd_id != ID3_USLT && frame->fr_desc->fd_id != ID3_SYLT && frame->fr_desc->fd_id != ID3_COMM && frame->fr_desc->fd_id != ID3_APIC && frame->fr_desc->fd_id != ID3_GEOB && frame->fr_desc->fd_id != ID3_USER && frame->fr_desc->fd_id != ID3_OWNE && frame->fr_desc->fd_id != ID3_COMR) return -1; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; return *(uint8_t *) frame->fr_data; } /* * Function id3_set_encoding (frame, encoding) * * Set text encoding for frame. Return 0 upon success, or -1 if an * error occured. * */ int id3_set_encoding(id3_frame_t * frame, int8_t encoding) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T' && frame->fr_desc->fd_id != ID3_WXXX && frame->fr_desc->fd_id != ID3_IPLS && frame->fr_desc->fd_id != ID3_USLT && frame->fr_desc->fd_id != ID3_SYLT && frame->fr_desc->fd_id != ID3_COMM && frame->fr_desc->fd_id != ID3_APIC && frame->fr_desc->fd_id != ID3_GEOB && frame->fr_desc->fd_id != ID3_USER && frame->fr_desc->fd_id != ID3_OWNE && frame->fr_desc->fd_id != ID3_COMR) return -1; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; /* Changing the encoding of frames is not supported yet */ if (*(uint8_t *) frame->fr_data != encoding) return -1; /* Set encoding */ *(uint8_t *) frame->fr_data = encoding; return 0; } /* * Function id3_get_text (frame) * * Return string contents of frame. * */ char *id3_get_text(id3_frame_t * frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return NULL; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; if (frame->fr_desc->fd_id == ID3_TXXX) { /* * This is a user defined text frame. Skip the description. */ switch (*(uint8_t *) frame->fr_data) { case ID3_ENCODING_ISO_8859_1: { char *text = (char *) frame->fr_data + 1; while (*text != 0) text++; return ++text; } case ID3_ENCODING_UTF16: { int16_t *text16 = (int16_t *) ((int) frame->fr_data + 1); while (*text16 != 0) text16++; return (char *) ++text16; } default: return NULL; } } return (char *) frame->fr_data + 1; } /* * Function id3_get_text_desc (frame) * * Get description part of a text frame. * */ char *id3_get_text_desc(id3_frame_t * frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return NULL; /* If predefined text frame, return description. */ if (frame->fr_desc->fd_id != ID3_TXXX) return frame->fr_desc->fd_description; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; return (char *) frame->fr_data + 1; } /* * Function id3_get_text_number (frame) * * Return string contents of frame translated to a positive * integer, or -1 if an error occured. * */ int id3_get_text_number(id3_frame_t * frame) { int number = 0; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return -1; /* * Generate integer according to encoding. */ switch (*(uint8_t *) frame->fr_data) { case ID3_ENCODING_ISO_8859_1: { char *text = ((char *) frame->fr_data) + 1; while (*text >= '0' && *text <= '9') { number *= 10; number += *text - '0'; text++; } return number; } case ID3_ENCODING_UTF16: { int16_t *text = ((int16_t *) frame->fr_data) + 1; while (*text >= '0' && *text <= '9') { number *= 10; number += *text - '0'; text++; } return number; } default: return -1; } } /* * Function id3_set_text (frame, text) * * Set text for the indicated frame (only ISO-8859-1 is currently * supported). Return 0 upon success, or -1 if an error occured. * */ int id3_set_text(id3_frame_t * frame, char *text) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return -1; /* * Release memory occupied by previous data. */ id3_frame_clear_data(frame); /* * Allocate memory for new data. */ frame->fr_raw_size = strlen(text) + 1; frame->fr_raw_data = kmalloc(frame->fr_raw_size + 1, GFP_KERNEL); /* * Copy contents. */ *(uint8_t *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; memcpy((char *) frame->fr_raw_data + 1, text, frame->fr_raw_size); frame->fr_altered = 1; frame->fr_owner->id3_altered = 1; frame->fr_data = frame->fr_raw_data; frame->fr_size = frame->fr_raw_size; return 0; } /* * Function id3_set_text_number (frame, number) * * Set number for the indicated frame (only ISO-8859-1 is currently * supported). Return 0 upon success, or -1 if an error occured. * */ int id3_set_text_number(id3_frame_t * frame, int number) { char buf[64]; int pos; char *text; /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'T') return -1; /* * Release memory occupied by previous data. */ id3_frame_clear_data(frame); /* * Create a string with a reversed number. */ pos = 0; while (number > 0 && pos < 64) { buf[pos++] = (number % 10) + '0'; number /= 10; } if (pos == 64) return -1; if (pos == 0) buf[pos++] = '0'; /* * Allocate memory for new data. */ frame->fr_raw_size = pos + 1; frame->fr_raw_data = kmalloc(frame->fr_raw_size + 1, GFP_KERNEL); /* * Insert contents. */ *(uint8_t *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; text = (char *) frame->fr_raw_data + 1; while (--pos >= 0) *text++ = buf[pos]; *text = '\0'; frame->fr_altered = 1; frame->fr_owner->id3_altered = 1; frame->fr_data = frame->fr_raw_data; frame->fr_size = frame->fr_raw_size; return 0; } --- NEW FILE: id3_frame_url.c --- /********************************************************************* * * Copyright (C) 1999, 2001, * Department of Computer Science, University of Tromsø * * Filename: id3_frame_url.c * Description: Code for handling ID3 URL frames. * Author: Espen Skoglund <es...@st...> * Created at: Tue Feb 9 21:10:45 1999 * * $Id: id3_frame_url.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include "id3.h" #include "id3_header.h" /* * Function id3_get_url (frame) * * Return URL of frame. * */ char *id3_get_url(id3_frame_t * frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'W') return NULL; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; if (frame->fr_desc->fd_id == ID3_WXXX) { /* * This is a user defined link frame. Skip the description. */ switch (*(uint8_t *) frame->fr_data) { case ID3_ENCODING_ISO_8859_1: { char *text = (char *) frame->fr_data + 1; while (*text != 0) text++; return ++text; } case ID3_ENCODING_UTF16: { int16_t *text16 = (int16_t *) ((int) frame->fr_data + 1); while (*text16 != 0) text16++; return (char *) ++text16; } default: return NULL; } } return (char *) frame->fr_data; } /* * Function id3_get_url_desc (frame) * * Get description of a URL. * */ char *id3_get_url_desc(id3_frame_t * frame) { /* Type check */ if (frame->fr_desc->fd_idstr[0] != 'W') return NULL; /* If predefined link frame, return description. */ if (frame->fr_desc->fd_id != ID3_WXXX) return frame->fr_desc->fd_description; /* Check if frame is compressed */ if (id3_decompress_frame(frame) == -1) return NULL; return (char *) frame->fr_data + 1; } --- NEW FILE: id3_header.h --- /********************************************************************* * * Copyright (C) 1998, 1999, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3_header.h * Description: Definitions for various ID3 headers. * Author: Espen Skoglund <es...@st...> * Created at: Thu Nov 5 15:55:10 1998 * * $Id: id3_header.h,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #ifndef ID3_HEADER_H #define ID3_HEADER_H #ifndef __GNUC__ #define __attribute__(A) #endif /* * Layout for the ID3 tag header. */ typedef struct id3_taghdr_t id3_taghdr_t; struct id3_taghdr_t { uint8_t th_version; uint8_t th_revision; uint8_t th_flags; uint32_t th_size; } __attribute__ ((packed)); #define ID3_THFLAG_USYNC 0x80000000 #define ID3_THFLAG_EXT 0x40000000 #define ID3_THFLAG_EXP 0x20000000 #define ID3_SET_SIZE28(size) \ ( ((size << 3) & 0x7f000000) | \ ((size << 2) & 0x007f0000) | \ ((size << 1) & 0x00007f00) | \ ((size ) & 0x0000007f) ) #define ID3_GET_SIZE28(size) \ ( ((size & 0x7f000000) >> 3) | \ ((size & 0x007f0000) >> 2) | \ ((size & 0x00007f00) >> 1) | \ ((size & 0x0000007f) ) ) /* * Layout for the extended header. */ typedef struct id3_exthdr_t id3_exthdr_t; struct id3_exthdr_t { uint32_t eh_size; uint16_t eh_flags; uint32_t eh_padsize; } __attribute__ ((packed)); #define ID3_EHFLAG_CRC 0x80000000 /* * Layout for the frame header. */ typedef struct id3_framehdr_t id3_framehdr_t; struct id3_framehdr_t { uint32_t fh_id; uint32_t fh_size; uint16_t fh_flags; } __attribute__ ((packed)); #define ID3_FHFLAG_TAGALT 0x8000 #define ID3_FHFLAG_FILEALT 0x4000 #define ID3_FHFLAG_RO 0x2000 #define ID3_FHFLAG_COMPRESS 0x0080 #define ID3_FHFLAG_ENCRYPT 0x0040 #define ID3_FHFLAG_GROUP 0x0020 typedef enum { ID3_UNI_LATIN = 0x007f, ID3_UNI_LATIN_1 = 0x00ff, ID3_UNI_SUPPORTED = 0x00ff, ID3_UNI_UNSUPPORTED = 0xffff, } id3_unicode_blocks; #ifdef DEBUG_ID3 #define id3_error(id3, error) \ (void) ( id3->id3_error_msg = error, \ printf( "Error %s, line %d: %s\n", __FILE__, __LINE__, error ) ) #else #define id3_error(id3, error) \ (void) ( id3->id3_error_msg = error ) #endif #endif /* ID3_HEADER_H */ --- NEW FILE: id3_tag.c --- #define err(x) printk(x "\n") /********************************************************************* * * Copyright (C) 1999-2000, Espen Skoglund * Department of Computer Science, University of Tromsø * * Filename: id3_tag.c * Description: Code for handling ID3 tags. * Author: Espen Skoglund <es...@st...> * Created at: Tue Feb 9 21:13:19 1999 * * $Id: id3_tag.c,v 1.1.2.1 2003/08/03 23:10:43 ben_osheroff Exp $ * * 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 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ********************************************************************/ #include <linux/kernel.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/list.h> #include "id3.h" #include "id3_header.h" /* * Function id3_init_tag (id3) * * Initialize an empty ID3 tag. * */ void id3_init_tag(id3_t * id3) { /* * Initialize header. */ id3->id3_version = 3; id3->id3_revision = 0; id3->id3_flags = ID3_THFLAG_USYNC | ID3_THFLAG_EXP; id3->id3_tagsize = 0; id3->id3_altered = 1; id3->id3_newtag = 1; id3->id3_pos = 0; INIT_LIST_HEAD(&id3->id3_frame); } /* * Function id3_read_tag (id3) * * Read the ID3 tag from the input stream. The start of the tag * must be positioned in the next tag in the stream. Return 0 upon * success, or -1 if an error occured. * */ int id3_read_tag(id3_t * id3) { id3_taghdr_t *taghdr; id3_exthdr_t *exthdr; char *id; /* * We know that the tag will be at least this big. */ id3->id3_tagsize = sizeof(*taghdr) + 3; if (!(id3->id3_oflags & ID3_OPENF_NOCHK)) { /* * Check if we have a valid ID3 tag. */ id = id3->id3_read(id3, NULL, 3); if (id == NULL) return -1; if (id[0] != 'I' || id[1] != 'D' || id[2] != '3') { /* * ID3 tag was not detected. */ id3->id3_seek(id3, -3); return -1; } } err("reading the tag header"); /* * Read ID3 tag-header. */ taghdr = id3->id3_read(id3, NULL, sizeof(*taghdr)); if (taghdr == NULL) return -1; id3->id3_version = taghdr->th_version; id3->id3_revision = taghdr->th_revision; id3->id3_flags = taghdr->th_flags; id3->id3_tagsize = ID3_GET_SIZE28(be32_to_cpu(taghdr->th_size)); id3->id3_newtag = 0; id3->id3_pos = 0; /* * Parse extended header. */ err("reading the extended header"); if (taghdr->th_flags & ID3_THFLAG_EXT) { exthdr = id3->id3_read(id3, NULL, sizeof(*exthdr)); if (exthdr == NULL) return -1; } /* * Parse frames. */ err("reading the frames"); INIT_LIST_HEAD(&id3->id3_frame); while (id3->id3_pos < id3->id3_tagsize) { if (id3_read_frame(id3) == -1) return -1; } return 0; } --- NEW FILE: mpg123.c --- #include <linux/kernel.h> #include <linux/string.h> #include "mpg123.h" const char *mpg123_id3_genres[GENRE_MAX] = { "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop" }; --- NEW FILE: mpg123.h --- /* * mpg123 defines * used source: musicout.h from mpegaudio package */ #ifndef __MPG123_H__ #define __MPG123_H__ #include "id3.h" #define real float /* #define MAX_NAME_SIZE 81 */ #define SBLIMIT 32 #define SCALE_BLOCK 12 #define SSLIMIT 18 #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 struct id3v1tag_t { char tag[3]; /* always "TAG": defines ID3v1 tag 128 bytes before EOF */ char title[30]; char artist[30]; char album[30]; char year[4]; union { struct { char comment[30]; } v1_0; struct { char comment[28]; char __zero; unsigned char track_number; } v1_1; } u; unsigned char genre; }; struct id3tag_t { char title[64]; char artist[64]; char album[64]; char comment[256]; char genre[256]; int year; int track_number; }; struct al_table { short bits; short d; }; #define GENRE_MAX 0x94 extern const char *mpg123_id3_genres[GENRE_MAX]; extern int tabsel_123[2][3][16]; #endif |
From: Ben O. <ben...@us...> - 2003-08-03 23:09:09
|
Update of /cvsroot/njbfs/njbfs/mpg123 In directory sc8-pr-cvs1:/tmp/cvs-serv3550/mpg123 Log Message: Directory /cvsroot/njbfs/njbfs/mpg123 added to the repository --> Using per-directory sticky tag `ben' |
From: Ben O. <ben...@us...> - 2002-03-01 09:15:43
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv8286 Modified Files: Tag: ben dir.c njb_usb.c njb_usb.h njbfs.h njbfs_cache.c njbfs_cache.h njbfs_dir.c njbfs_proc.h nomad.c proc.c proc.h Log Message: Ben: first pass at the NJB write cache Index: dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/dir.c,v retrieving revision 1.3.2.2 retrieving revision 1.3.2.3 diff -C2 -d -r1.3.2.2 -r1.3.2.3 *** dir.c 24 Feb 2002 11:33:58 -0000 1.3.2.2 --- dir.c 1 Mar 2002 09:15:40 -0000 1.3.2.3 *************** *** 402,409 **** struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; - char buf[NJBFS_MAXPATHLEN]; ! njbfs_get_name(dentry, buf); ! njbfs_cache_invalidate(dentry->d_parent); ! return njbfs_proc_unlink(info, buf); } --- 402,406 ---- struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; ! return njbfs_proc_unlink(info, dentry); } Index: njb_usb.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.c,v retrieving revision 1.4.2.3 retrieving revision 1.4.2.4 diff -C2 -d -r1.4.2.3 -r1.4.2.4 *** njb_usb.c 24 Feb 2002 11:33:58 -0000 1.4.2.3 --- njb_usb.c 1 Mar 2002 09:15:40 -0000 1.4.2.4 *************** *** 223,227 **** dbg("open: handshake ok"); ! /* Get disk usage */ status = njb_usb_get_disk_usage(njb, &total, &free); if (status < 0) { --- 223,227 ---- dbg("open: handshake ok"); ! /* Get disk usage */ status = njb_usb_get_disk_usage(njb, &total, &free); if (status < 0) { *************** *** 237,243 **** return -ENOSPC; } ! /** ! * Build track, write track tag, and get NJB track id as a result ! */ trackid = 0; track = njb_usb_update_track_tag(njb, fattr, &trackid); --- 237,245 ---- return -ENOSPC; } ! ! ! /** ! * Build track, write track tag, and get NJB track id as a result ! */ trackid = 0; track = njb_usb_update_track_tag(njb, fattr, &trackid); *************** *** 250,258 **** fattr->track = track; /* save track */ fattr->fileid = trackid; /* for requesting the track tag later */ ! return status; } else if (fattr->fileid > 0) { ! dbg("attempting to open '%s'..", fattr->title); /* Open for read track */ --- 252,261 ---- fattr->track = track; /* save track */ fattr->fileid = trackid; /* for requesting the track tag later */ ! return status; } else if (fattr->fileid > 0) { ! printk("attempting to open '%s' (%d)..", fattr->title, ! fattr->fileid); /* Open for read track */ *************** *** 348,365 **** } - if (fattr->fileid == 0) { - - /* update library counter */ - dbg("close: updating lib counter"); - status = njb_usb_update_library_counter(njb); - if (status < 0) { - err - ("close: updating lib count error, status = %d, ", - status); - return -EPROTO; - } - } - - njb->isopen = 0; dbg("close: jukebox closed"); --- 351,354 ---- *************** *** 523,526 **** --- 512,516 ---- ("write: bulk write error, actual_length = %d, status = %d", actual_length, status); + return status; } if (actual_length < count) { *************** *** 535,538 **** --- 525,529 ---- err("write: can't verify last command, status = %d", status); + return status; } *************** *** 568,574 **** * Delete a file from the NJB */ ! int njb_usb_delete(struct nomad_usb_data *nomad, char *file) { ! info("TODO: usb delete"); return 0; } --- 559,603 ---- * Delete a file from the NJB */ ! int njb_usb_delete(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { ! u_int16_t lsw, msw; ! char njb_status; ! int status; ! ! if ( !fattr->fileid ) ! return -ENOENT; ! ! ! lsw = LSW(fattr->fileid); ! msw = MSW(fattr->fileid); ! /* handshake, required for later set library counter */ ! status = njb_usb_handshake(njb); ! if ( status < 0 ) { ! err("handshake failed..."); ! return status; ! } ! ! /* setup phase */ ! status = njb_usb_control(njb, ! usb_rcvctrlpipe(njb->nomad_dev, ! NJB_ENDPOINT_CONTROL), ! NJB_CMD_DELETE_TRACK, ! UT_READ | USB_TYPE_VENDOR | ! USB_RECIP_OTHER, msw, lsw, &njb_status, 1, 3); ! ! if ( status < 0 ) { ! err("error sending delete message"); ! return status; ! } else if ( njb_status != NJB_OK ) { ! err("bad njb status = %d", njb_status); ! return -EIO; ! } ! ! status = njb_usb_update_library_counter(njb); ! if ( status < 0 ) { ! err("couldn't update library counter"); ! return -EIO; ! } ! return 0; } *************** *** 1224,1228 **** /* Set track id, return track */ memcpy(&header->trackid, &data[1], 4); ! dbg("write_track_tag: got new track id = %d", header->trackid); return 0; --- 1253,1257 ---- /* Set track id, return track */ memcpy(&header->trackid, &data[1], 4); ! printk("write_track_tag: got new track id = %d", header->trackid); return 0; *************** *** 1476,1480 **** return NULL; } ! } return track; --- 1505,1509 ---- return NULL; } ! *trackid = header.trackid; } return track; Index: njb_usb.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.h,v retrieving revision 1.3.2.2 retrieving revision 1.3.2.3 diff -C2 -d -r1.3.2.2 -r1.3.2.3 *** njb_usb.h 24 Feb 2002 11:33:58 -0000 1.3.2.2 --- njb_usb.h 1 Mar 2002 09:15:40 -0000 1.3.2.3 *************** *** 158,161 **** --- 158,163 ---- extern int njb_usb_close(struct nomad_usb_data *njb, struct njbfs_fattr *fattr); + extern int njb_usb_close_no_release(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); extern int njb_usb_write(struct nomad_usb_data *njb, char *name, u_int32_t offset, u_int32_t count, void *buffer); *************** *** 163,167 **** extern int njb_usb_rename(struct nomad_usb_data *njb, struct njbfs_fattr *fattr); ! extern int njb_usb_delete(struct nomad_usb_data *njb, char *file); extern int njb_usb_create(struct nomad_usb_data *njb, char *file); extern int njb_usb_handshake(struct nomad_usb_data *njb); --- 165,169 ---- extern int njb_usb_rename(struct nomad_usb_data *njb, struct njbfs_fattr *fattr); ! extern int njb_usb_delete(struct nomad_usb_data *njb, struct njbfs_fattr *); extern int njb_usb_create(struct nomad_usb_data *njb, char *file); extern int njb_usb_handshake(struct nomad_usb_data *njb); Index: njbfs.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs.h,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** njbfs.h 24 Feb 2002 11:33:58 -0000 1.4.2.2 --- njbfs.h 1 Mar 2002 09:15:40 -0000 1.4.2.3 *************** *** 44,48 **** #define NJBFS_BLOCKSIZE_BITS 12 /* 2^x = blocksize */ ! #define NJBFS_ID3SIZE 8192 /* size of the false tag at the top */ #define NJBFS_FOOTERSIZE 4096 /* size of the zeroed footers at the bottom */ --- 44,48 ---- #define NJBFS_BLOCKSIZE_BITS 12 /* 2^x = blocksize */ ! #define NJBFS_ID3SIZE 4096 /* size of the false tag at the top */ #define NJBFS_FOOTERSIZE 4096 /* size of the zeroed footers at the bottom */ *************** *** 100,103 **** --- 100,104 ---- something that will require a reload? */ + struct njbfs_blockcache *bl_cache; }; Index: njbfs_cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.c,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** njbfs_cache.c 26 Feb 2002 02:20:05 -0000 1.1.2.2 --- njbfs_cache.c 1 Mar 2002 09:15:40 -0000 1.1.2.3 *************** *** 112,116 **** } ! static void __njbfs_destroy_hashtable(njbfs_hash_element **table) { njbfs_hash_element *el, *last; --- 112,116 ---- } ! void __njbfs_destroy_hashtable(njbfs_hash_element **table) { njbfs_hash_element *el, *last; *************** *** 146,150 **** */ ! static int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data) { njbfs_hash_element *element; --- 146,150 ---- */ ! int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data) { njbfs_hash_element *element; *************** *** 172,176 **** ! static void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id) { njbfs_hash_element *walk; --- 172,176 ---- ! void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id) { njbfs_hash_element *walk; *************** *** 758,761 **** --- 758,763 ---- (fattr->size + (NJBFS_BLOCKSIZE - 1)) >> (NJBFS_BLOCKSIZE_BITS - 1); + + fattr->bl_cache = NULL; fattr->fileid = track->header.trackid; Index: njbfs_cache.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.h,v retrieving revision 1.4.2.4 retrieving revision 1.4.2.5 diff -C2 -d -r1.4.2.4 -r1.4.2.5 *** njbfs_cache.h 26 Feb 2002 02:22:22 -0000 1.4.2.4 --- njbfs_cache.h 1 Mar 2002 09:15:40 -0000 1.4.2.5 *************** *** 214,217 **** --- 214,223 ---- struct njbfs_fattr_list *add_fattr_to_list(struct njbfs_fattr_list **, struct njbfs_fattr *); + void njbfs_destroy_fattr_cache(); + + + int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data); + void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id); + void __njbfs_destroy_hashtable(njbfs_hash_element **); Index: njbfs_dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_dir.c,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** njbfs_dir.c 26 Feb 2002 02:20:05 -0000 1.1.2.2 --- njbfs_dir.c 1 Mar 2002 09:15:40 -0000 1.1.2.3 *************** *** 60,67 **** switch (*ch) { case '/': - *ch = '_'; case '*': - *ch = '_'; case '?': *ch = '_'; } --- 60,67 ---- switch (*ch) { case '/': case '*': case '?': + case '>': + case '<': *ch = '_'; } *************** *** 223,226 **** --- 223,234 ---- gets a dirlist node (and creates a fattr struct) for our virtual directories + + BUGS: + We are unable to translate bad characters (?><) etc + in directory names for now... because we use + the directory name as a direct index into the hashtables. + + this should be easily cleaned once Jorge introduces the + njbfs_track structure. */ static void njbfs_dirlist_node_directories(struct njbfs_dirlist_node *p, *************** *** 299,302 **** --- 307,320 ---- /** * Get "/albums" directory entries from NJB cache + * + * Ok, albums are the trickiest thing to handle in a cache like this. + * we may have non-unique album names that we want to shove under + * one directory (eg _Unknown_), + * so we use a hashtable add/lookup method here to ensure + * uniqueness. + * + * sigh. + * + * */ int njbfs_load_albumsdir(struct njbfs_sb_info *info, *************** *** 305,309 **** --- 323,335 ---- struct njbfs_dirlist_node *p; struct njbfs_album_list *list; + int hash_size = sizeof(njbfs_hash_element *) * NJBFS_GENERIC_HASH_SIZE; + njbfs_hash_element **table = kmalloc(hash_size, GFP_KERNEL); + + if ( !table ) + return -ENOMEM; + + memset(table, 0, hash_size); + CHECK_FATTR_CACHE(info); *************** *** 316,326 **** --- 342,363 ---- return -ENOMEM; } + + if ( njbfs_get_hash_generic(table, list->album->name) ) + /* already found the album, skip. */ + continue; + + njbfs_add_hash_generic(table, list->album->name, (void *) 1); + memset(p, 0, sizeof(struct njbfs_dirlist_node)); + SAFE_STRDUP(p->entry.name, list->album->name); njbfs_dirlist_node_directories(p,info); + p->prev = NULL; p->next = dir->head; dir->head = p; } + + __njbfs_destroy_hashtable(table); return 0; } *************** *** 345,351 **** --- 382,391 ---- return -ENOMEM; } + memset(p, 0, sizeof(struct njbfs_dirlist_node)); + SAFE_STRDUP(p->entry.name, list->artist->name); njbfs_dirlist_node_directories(p, info); + p->prev = NULL; p->next = dir->head; *************** *** 375,380 **** --- 415,422 ---- } memset(p, 0, sizeof(struct njbfs_dirlist_node)); + SAFE_STRDUP(p->entry.name, list->genre->name); njbfs_dirlist_node_directories(p,info); + p->prev = NULL; p->next = dir->head; Index: njbfs_proc.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_proc.h,v retrieving revision 1.3.2.2 retrieving revision 1.3.2.3 diff -C2 -d -r1.3.2.2 -r1.3.2.3 *** njbfs_proc.h 24 Feb 2002 11:33:58 -0000 1.3.2.2 --- njbfs_proc.h 1 Mar 2002 09:15:40 -0000 1.3.2.3 *************** *** 22,26 **** int njbfs_proc_rename(struct njbfs_sb_info *, struct inode *, struct dentry *, struct inode *, struct dentry *); ! int njbfs_proc_unlink(struct njbfs_sb_info *, char *); int njbfs_proc_create(struct njbfs_sb_info *, char *, struct njbfs_fattr **); int njbfs_write(struct dentry *, unsigned long, unsigned long, char *); --- 22,26 ---- int njbfs_proc_rename(struct njbfs_sb_info *, struct inode *, struct dentry *, struct inode *, struct dentry *); ! int njbfs_proc_unlink(struct njbfs_sb_info *, struct dentry *); int njbfs_proc_create(struct njbfs_sb_info *, char *, struct njbfs_fattr **); int njbfs_write(struct dentry *, unsigned long, unsigned long, char *); Index: nomad.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/nomad.c,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -C2 -d -r1.3.2.1 -r1.3.2.2 *** nomad.c 15 Feb 2002 20:07:32 -0000 1.3.2.1 --- nomad.c 1 Mar 2002 09:15:40 -0000 1.3.2.2 *************** *** 40,44 **** #include <linux/poll.h> #include <linux/init.h> ! #include <linux/malloc.h> #include <linux/spinlock.h> #include <linux/smp_lock.h> --- 40,44 ---- #include <linux/poll.h> #include <linux/init.h> ! #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/smp_lock.h> Index: proc.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.c,v retrieving revision 1.6.2.5 retrieving revision 1.6.2.6 diff -C2 -d -r1.6.2.5 -r1.6.2.6 *** proc.c 26 Feb 2002 02:23:38 -0000 1.6.2.5 --- proc.c 1 Mar 2002 09:15:40 -0000 1.6.2.6 *************** *** 4,7 **** --- 4,8 ---- * * Copyright (C) 2001 Jörg Prante <joe...@gm...> + * Copyright (C) 2002 Ben Osheroff <be...@gi...> * * based on ftpfs by Florin Malita <fm...@ya...> *************** *** 60,63 **** --- 61,65 ---- static int njbfs_parse_filename(struct njbfs_fattr *fattr, const char *file); + int njbfs_write_block_cache(struct dentry *dentry); unsigned char *k_parse_attribute(unsigned char *buf, unsigned char *key); *************** *** 244,247 **** --- 246,252 ---- } + /* + lock, unless the read is called from read_until + */ int njbfs_read_lock(struct inode *i) { *************** *** 309,313 **** { struct njbfs_fattr *f; - int status; if (njbfs_lock(info)) return NULL; --- 314,317 ---- *************** *** 374,377 **** --- 378,384 ---- } + /* + TODO: move this to iget + */ njb_inode_mark_closed(inode); njb_set_pos(inode, 0); *************** *** 403,410 **** } - - njbfs_lock(info); /* here's where we update the cache */ if ( fattr->update_cache ) { --- 410,418 ---- } njbfs_lock(info); + /* any pending writes? */ + njbfs_write_block_cache(dentry); + /* here's where we update the cache */ if ( fattr->update_cache ) { *************** *** 579,583 **** */ - #define PROFILE int njbfs_read_until(struct file *f, unsigned int fileid, char *name, u_int32_t until, char *buffer) --- 587,590 ---- *************** *** 587,594 **** struct inode *i = f->f_dentry->d_inode; - #ifdef PROFILE - time_t start = CURRENT_TIME; - int start_byte = njb_get_pos(i); - #endif if ( until == njb_get_pos(i) ) { --- 594,597 ---- *************** *** 626,640 **** } - #ifdef PROFILE - printk("pushed %d bytes in %d seconds\n", - until - start_byte, CURRENT_TIME - start); - #endif njb_interruption_inode = 0; return 0; } ! /* ! lock, unless the read is called from read_until */ /** --- 629,676 ---- } njb_interruption_inode = 0; return 0; } ! /** ! * If the specified dentry is different than the one we're ! * reading from currently, close down the read. */ + int njbfs_close_current(struct njbfs_sb_info *info, + struct inode *inode, + struct njbfs_fattr *fattr) + { + int status; + struct njbfs_fattr *opened_fattr; + struct dentry *current_dentry; + + if ( !info->njb->current_dentry ) + return 0; + + current_dentry = info->njb->current_dentry; + + opened_fattr = + njbfs_get_attr_nolock(current_dentry, info); + + if ( !opened_fattr ) + return -EINVAL; + + if (fattr->fileid != opened_fattr->fileid) { + /* mark the inode as closed (usually njbfs_close does this) */ + njb_inode_mark_closed(current_dentry->d_inode); + njb_set_pos(current_dentry->d_inode, 0); + + if ( + (status = + njb_usb_close_no_release(info->njb, opened_fattr))) { + if (status != NJB_NOT_CAPTURED) { + err("open: njb wouldn't close."); + njbfs_read_unlock(inode); + return -EIO; + } + } + } + return 0; + } /** *************** *** 651,659 **** { struct inode *inode = dentry->d_inode; - struct super_block *sb = inode->i_sb; struct njbfs_sb_info *info = ! (struct njbfs_sb_info *) sb->u.generic_sbp; struct nomad_usb_data *njb = info->njb; ! struct njbfs_fattr *fattr, *opened_fattr; char buf[NJBFS_MAXPATHLEN], name[NJBFS_MAXPATHLEN]; int bytes, status, faked = 0; --- 687,695 ---- { struct inode *inode = dentry->d_inode; struct njbfs_sb_info *info = ! (struct njbfs_sb_info *) inode->i_sb->u.generic_sbp; struct nomad_usb_data *njb = info->njb; ! struct njbfs_fattr *fattr; ! char buf[NJBFS_MAXPATHLEN], name[NJBFS_MAXPATHLEN]; int bytes, status, faked = 0; *************** *** 679,683 **** create_id3_tag(dentry, buffer); njb_set_pos(inode, 0); - dbg("faked the id3 header."); return NJBFS_BLOCKSIZE; } else if (offset < NJBFS_ID3SIZE) { --- 715,718 ---- *************** *** 685,693 **** njb_set_pos(inode, offset + NJBFS_BLOCKSIZE); memset(buffer, 0, NJBFS_BLOCKSIZE); - dbg("faked the 2nd block."); return NJBFS_BLOCKSIZE; } else if (fattr->size - offset == NJBFS_FOOTERSIZE) { memset(buffer, 0, NJBFS_BLOCKSIZE); - dbg("faked the last block."); return NJBFS_BLOCKSIZE; } else if (fattr->size - offset == NJBFS_FOOTERSIZE * 2) { --- 720,726 ---- *************** *** 700,734 **** return -EINTR; ! if (njb->current_dentry) { ! /* There's a file already open on the jukebox. ! if it's not us, close it down and open our file up. */ ! ! opened_fattr = njbfs_get_attr_nolock(njb->current_dentry, info); ! ! if ( !opened_fattr ) { ! njbfs_read_unlock(inode); ! return -EINVAL; ! } ! ! if (fattr->fileid != opened_fattr->fileid) { ! dbg ! ("closing '%s', opening '%s'", opened_fattr->title, fattr->title); ! ! ! /* mark the inode as closed (usually njbfs_close does this) */ ! njb_inode_mark_closed(njb->current_dentry->d_inode); ! njb_set_pos(njb->current_dentry->d_inode, 0); ! ! if ( ! (status = ! njb_usb_close_no_release(njb, opened_fattr))) { ! if (status != NJB_NOT_CAPTURED) { ! err("open: njb wouldn't close."); ! njbfs_read_unlock(inode); ! return -EIO; ! } ! } ! } ! } if (!njb_inode_is_open(inode)) { --- 733,739 ---- return -EINTR; ! status = njbfs_close_current(info, inode, fattr); ! if ( status ) ! return status; if (!njb_inode_is_open(inode)) { *************** *** 744,748 **** } - /* transfer */ /* this should detect if they're trying to seek in the file. --- 749,752 ---- *************** *** 753,756 **** --- 757,761 ---- njbfs_read_until(file, fattr->fileid, name, offset, buffer); + /* transfer */ if ( (bytes = *************** *** 768,773 **** } /** ! * Write to a file * * @param dentry directory entry to read from --- 773,953 ---- } + void destroy_block_cache(struct njbfs_fattr *fattr) + { + int i; + for(i=0; i < fattr->bl_cache->count; i++) + kfree(fattr->bl_cache->blocks[i].buffer); + + kfree(fattr->bl_cache); + fattr->bl_cache = NULL; + } + + /* + find a block in the given block cache. + returns the pointer offset if found, + -1 if not found + */ + int find_in_block_cache(struct njbfs_blockcache *bl, off_t offset) + { + int i; + for(i=0; i < bl->count; i++) { + if ( bl->blocks[i].offset == offset ) + return i; + } + return -1; + } + + int add_to_block_cache(struct njbfs_fattr *fattr, off_t offset, off_t size, char *buffer) + { + int index; + void *buf; + struct njbfs_blockcache *bl = fattr->bl_cache; + + if ( !fattr->bl_cache ) { + fattr->bl_cache = kmalloc(sizeof(struct njbfs_blockcache), GFP_KERNEL); + if ( !fattr->bl_cache ) { + err("couldn't kmalloc block cache"); + return -ENOMEM; + } + memset(fattr->bl_cache, 0, sizeof(struct njbfs_blockcache)); + fattr->bl_cache->count = 0; + bl = fattr->bl_cache; + } + + + + buf = kmalloc(size, GFP_KERNEL); + if ( !buf ) { + err("couldn't kmalloc block in cache"); + destroy_block_cache(fattr); + return -EINVAL; + } + + /* + see if we already have the block in cache + */ + index = find_in_block_cache(bl, offset); + if ( index == -1 ) { + if ( bl->count >= NJBFS_MAXBLOCKS ) { + err("file size too large, please increase NBFS_MAXBLOCKS"); + kfree(buf); + destroy_block_cache(fattr); + return -EINVAL; + } + memcpy(buf, buffer, size); + bl->blocks[bl->count].buffer = buf; + bl->blocks[bl->count].size = size; + bl->blocks[bl->count].offset = offset; + bl->count++; + } else { + kfree(bl->blocks[index].buffer); + memcpy(buf, buffer, size); + bl->blocks[index].buffer = buf; + bl->blocks[size].size = size; + bl->blocks[bl->count].offset = offset; + } + return 0; + } + + int njbfs_write_block_cache(struct dentry *dentry) + { + off_t offset, size; + int i, status; + struct njbfs_fattr *fattr; + struct njbfs_sb_info *info = + (struct njbfs_sb_info *) dentry->d_inode->i_sb->u.generic_sbp; + + fattr = njbfs_get_attr_nolock(dentry, info); + if ( !fattr ) + return -ENOENT; + + if ( !fattr->bl_cache || !fattr->bl_cache->count ) + return 0; + + + /* + calculate file size. + */ + for(i= 0, size = 0; i < fattr->bl_cache->count; i++) + size += fattr->bl_cache->blocks[i].size; + + + /* + make sure no read is in progress. + */ + status = njbfs_close_current(info, dentry->d_inode, fattr); + if ( status ) + return status; + + /* + give the real size of the file to open + so the nomad will know how much to expect + */ + fattr->size = size; + + /* + change to open_write + */ + status = njb_usb_open(info->njb, fattr); + if ( status ) + return status; + + + /* + now set the size to the ID3 faking size + */ + fattr->size = + size + NJBFS_ID3SIZE + NJBFS_FOOTERSIZE + + (NJBFS_BLOCKSIZE - (size % NJBFS_BLOCKSIZE)); + fattr->real_size = size; + + /* + set the cache to update. + */ + fattr->update_cache = 1; + + /* + do some tricky fun stuff here to + parse id3 headers and rewrite the file if there + was an old file, etc. + */ + + + for(i = 0; i < fattr->bl_cache->count; i++) { + offset = find_in_block_cache(fattr->bl_cache, i * NJBFS_BLOCKSIZE); + status = njb_usb_write(info->njb, fattr->title, + fattr->bl_cache->blocks[offset].offset, + fattr->bl_cache->blocks[offset].size, + fattr->bl_cache->blocks[offset].buffer); + if ( status < 0 ) { + destroy_block_cache(fattr); + njb_usb_close(info->njb, fattr); + return status; + } + } + + destroy_block_cache(fattr); + + status = njb_usb_close(info->njb, fattr); + + /* update library counter */ + dbg("write_block_cache: updating lib counter"); + status = njb_usb_update_library_counter(info->njb); + if (status < 0) { + err + ("close: updating lib count error, status = %d, ", + status); + return -EPROTO; + } + + if ( status < 0 ) + return status; + else + return 0; + + } + /** ! * Write to a file - actually, just add to the block cache. * * @param dentry directory entry to read from *************** *** 780,789 **** unsigned long count, char *buffer) { - struct inode *inode = dentry->d_inode; - struct super_block *sb = inode->i_sb; struct njbfs_sb_info *info = ! (struct njbfs_sb_info *) sb->u.generic_sbp; char buf[NJBFS_MAXPATHLEN], name[NJBFS_MAXPATHLEN]; ! int bytes; njbfs_get_name(dentry, buf); --- 960,969 ---- unsigned long count, char *buffer) { struct njbfs_sb_info *info = ! (struct njbfs_sb_info *) dentry->d_inode->i_sb->u.generic_sbp; ! ! struct njbfs_fattr *fattr; char buf[NJBFS_MAXPATHLEN], name[NJBFS_MAXPATHLEN]; ! int status; njbfs_get_name(dentry, buf); *************** *** 800,803 **** --- 980,993 ---- if (njbfs_lock(info)) return (-EINTR); + + fattr = njbfs_get_attr_nolock(dentry, info); + if ( !fattr ) { + err("couldn't find fattr"); + return -EINVAL; + } + + status = add_to_block_cache(fattr, offset, count, buffer); + + #if 0 if ( (bytes = *************** *** 808,819 **** return bytes; } njbfs_unlock(info); ! /* unload dir cache */ ! /* ! njbfs_cache_invalidate(dentry->d_parent); ! info("write: offset=%ld, count=%ld, bytes=%d", offset, count, bytes); ! */ ! return bytes; } --- 998,1009 ---- return bytes; } + #endif + njbfs_unlock(info); ! if ( status == 0 ) ! return count; ! else ! return status; } *************** *** 879,883 **** char old_buf[NJBFS_MAXPATHLEN + 6], new_buf[NJBFS_MAXPATHLEN + 6]; struct njbfs_fattr *old_fattr, *new_fattr; ! int status; njbfs_get_name(old_dentry, old_buf); --- 1069,1073 ---- char old_buf[NJBFS_MAXPATHLEN + 6], new_buf[NJBFS_MAXPATHLEN + 6]; struct njbfs_fattr *old_fattr, *new_fattr; ! int status = 0; njbfs_get_name(old_dentry, old_buf); *************** *** 940,961 **** * Delete a file */ ! int njbfs_proc_unlink(struct njbfs_sb_info *info, char *file) { ! char buf[NJBFS_MAXPATHLEN + 6]; int status; - if (strlen(info->mnt.root) + strlen(file) > NJBFS_MAXPATHLEN) { - err("unlink: path too long!"); - return -EINVAL; - } - sprintf(buf, "%s%s", info->mnt.root, file); - if (njbfs_lock(info)) return -EINVAL; ! if ((status = njb_usb_delete(info->njb, buf)) < 0) { err("unlink: couldn't delete file!"); status = -EIO; } njbfs_unlock(info); return status; --- 1130,1156 ---- * Delete a file */ ! int njbfs_proc_unlink(struct njbfs_sb_info *info, struct dentry *dentry) { ! struct njbfs_fattr *fattr; int status; if (njbfs_lock(info)) return -EINVAL; ! fattr = njbfs_get_attr_nolock(dentry, info); ! if ( ! fattr ) { ! err("couldn't find fattr."); ! njbfs_unlock(info); ! return -ENOENT; ! } ! ! if ((status = njb_usb_delete(info->njb, fattr)) < 0) { err("unlink: couldn't delete file!"); status = -EIO; } + + njbfs_remove_fattr(fattr); + njbfs_cache_empty(info); + njbfs_unlock(info); return status; Index: proc.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** proc.h 24 Feb 2002 11:33:58 -0000 1.1.2.1 --- proc.h 1 Mar 2002 09:15:40 -0000 1.1.2.2 *************** *** 4,8 **** #include "nomad_usb.h" ! #define UNKNOWN_STRING "__unknown__" #endif --- 4,30 ---- #include "nomad_usb.h" ! /* ! This is about 24 MB worth of data. ! If more is needed, well... ! ! hmm. ! Maybe later we can add a "large_transfers" ! flag or something. ! */ ! ! #define NJBFS_MAXBLOCKS 6000 ! + struct njbfs_block { + off_t offset; + off_t size; + void *buffer; + }; + + struct njbfs_blockcache { + int count; + struct njbfs_block blocks[NJBFS_MAXBLOCKS]; + }; + + #define UNKNOWN_STRING "<Unknown>" #endif |
From: Ben O. <ben...@us...> - 2002-02-28 10:24:41
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv22358 Modified Files: cache.c Log Message: ben: fix dumb bug Index: cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/cache.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** cache.c 24 Feb 2002 00:17:14 -0000 1.5 --- cache.c 28 Feb 2002 10:24:39 -0000 1.6 *************** *** 215,219 **** struct njbfs_hashlist_node *p; ! for (i = 0; i < NJBFS_CACHE_HASH; i++) for (j = 0; j < dir_cache.len[i]; j++) { p = dir_cache.hash[i]; --- 215,219 ---- struct njbfs_hashlist_node *p; ! for (i = 0; i < NJBFS_CACHE_HASH; i++) { for (j = 0; j < dir_cache.len[i]; j++) { p = dir_cache.hash[i]; *************** *** 223,226 **** --- 223,228 ---- dir_cache.len[i] = 0; dir_cache.hash[i] = NULL; + } + return 0; } |
From: Ben O. <ben...@us...> - 2002-02-28 10:23:19
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv21997 Modified Files: Tag: ben cache.c Log Message: ben: fix dumb bug Index: cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/cache.c,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** cache.c 24 Feb 2002 11:33:58 -0000 1.4.2.2 --- cache.c 28 Feb 2002 10:23:14 -0000 1.4.2.3 *************** *** 215,219 **** struct njbfs_hashlist_node *p; ! for (i = 0; i < NJBFS_CACHE_HASH; i++) for (j = 0; j < dir_cache.len[i]; j++) { p = dir_cache.hash[i]; --- 215,219 ---- struct njbfs_hashlist_node *p; ! for (i = 0; i < NJBFS_CACHE_HASH; i++) { for (j = 0; j < dir_cache.len[i]; j++) { p = dir_cache.hash[i]; *************** *** 223,226 **** --- 223,228 ---- dir_cache.len[i] = 0; dir_cache.hash[i] = NULL; + } + return 0; } |
From: Ben O. <ben...@us...> - 2002-02-26 12:20:25
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv10214 Modified Files: njbfs_cache.c njbfs_cache.h njbfs_dir.c Log Message: Ben: Fix bug where /albums was listing multiple "<Unknown>" directories Index: njbfs_cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** njbfs_cache.c 26 Feb 2002 02:11:47 -0000 1.2 --- njbfs_cache.c 26 Feb 2002 12:20:23 -0000 1.3 *************** *** 112,116 **** } ! static void __njbfs_destroy_hashtable(njbfs_hash_element **table) { njbfs_hash_element *el, *last; --- 112,116 ---- } ! void __njbfs_destroy_hashtable(njbfs_hash_element **table) { njbfs_hash_element *el, *last; *************** *** 146,150 **** */ ! static int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data) { njbfs_hash_element *element; --- 146,150 ---- */ ! int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data) { njbfs_hash_element *element; *************** *** 172,176 **** ! static void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id) { njbfs_hash_element *walk; --- 172,176 ---- ! void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id) { njbfs_hash_element *walk; Index: njbfs_cache.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** njbfs_cache.h 24 Feb 2002 00:23:12 -0000 1.5 --- njbfs_cache.h 26 Feb 2002 12:20:23 -0000 1.6 *************** *** 216,219 **** --- 216,224 ---- + int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data); + void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id); + void __njbfs_destroy_hashtable(njbfs_hash_element **); + + /* the linked lists that make up the core of our cache */ extern struct njbfs_album_list *album_list_head; Index: njbfs_dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_dir.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** njbfs_dir.c 26 Feb 2002 11:29:48 -0000 1.3 --- njbfs_dir.c 26 Feb 2002 12:20:23 -0000 1.4 *************** *** 223,226 **** --- 223,234 ---- /* gets a dirlist node (and creates a fattr struct) + + BUGS: + We are unable to translate bad characters (?><) etc + in directory names for now... because we use + the directory name as a direct index into the hashtables. + + this should be easily cleaned once Jorge introduces the + njbfs_track structure. for our virtual directories */ *************** *** 299,302 **** --- 307,320 ---- /** + * + * Ok, albums are the trickiest thing to handle in a cache like this. + * we may have non-unique album names that we want to shove under + * one directory (eg _Unknown_), + * so we use a hashtable add/lookup method here to ensure + * uniqueness. + * + * sigh. + * + * * Get "/albums" directory entries from NJB cache */ *************** *** 305,309 **** --- 323,335 ---- { struct njbfs_dirlist_node *p; + int hash_size = sizeof(njbfs_hash_element *) * NJBFS_GENERIC_HASH_SIZE; + + njbfs_hash_element **table = kmalloc(hash_size, GFP_KERNEL); struct njbfs_album_list *list; + if ( !table ) + return -ENOMEM; + + memset(table, 0, hash_size); + CHECK_FATTR_CACHE(info); *************** *** 316,326 **** --- 342,363 ---- err("loaddir: kmalloc error"); return -ENOMEM; + + if ( njbfs_get_hash_generic(table, list->album->name) ) + /* already found the album, skip. */ + continue; + + njbfs_add_hash_generic(table, list->album->name, (void *) 1); + } + memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->album->name); + njbfs_dirlist_node_directories(p,info); p->prev = NULL; p->next = dir->head; dir->head = p; + + __njbfs_destroy_hashtable(table); } return 0; *************** *** 345,351 **** --- 382,391 ---- err("loaddir: kmalloc error"); return -ENOMEM; + } + memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->artist->name); + njbfs_dirlist_node_directories(p, info); p->prev = NULL; *************** *** 375,380 **** --- 415,422 ---- return -ENOMEM; } + memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->genre->name); + njbfs_dirlist_node_directories(p,info); p->prev = NULL; |
From: Ben O. <ben...@us...> - 2002-02-26 11:29:52
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv26830 Modified Files: njbfs_dir.c proc.h Log Message: Ben: Add '<' and '>' to bad character list (samba as well as bash seems to hate this) Also change the defintion of UNKNOWN_STRING to "<Unknown>" to stay in convention with what others (playcenter, etc) are doing. Index: njbfs_dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_dir.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** njbfs_dir.c 26 Feb 2002 02:11:47 -0000 1.2 --- njbfs_dir.c 26 Feb 2002 11:29:48 -0000 1.3 *************** *** 61,68 **** switch (*ch) { case '/': - *ch = '_'; case '*': - *ch = '_'; case '?': *ch = '_'; } --- 61,68 ---- switch (*ch) { case '/': case '*': case '?': + case '>': + case '<': *ch = '_'; } Index: proc.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** proc.h 24 Feb 2002 00:15:13 -0000 1.1 --- proc.h 26 Feb 2002 11:29:48 -0000 1.2 *************** *** 32,35 **** u_int64_t * total, u_int64_t * free); ! #define UNKNOWN_STRING "__unknown__" #endif --- 32,35 ---- u_int64_t * total, u_int64_t * free); ! #define UNKNOWN_STRING "<Unknown>" #endif |
From: Ben O. <ben...@us...> - 2002-02-26 08:04:51
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv10927 Modified Files: Tag: ben Makefile Log Message: ben: include makefile in ben branch Index: Makefile =================================================================== RCS file: /cvsroot/njbfs/njbfs/Makefile,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -C2 -d -r1.4 -r1.4.2.1 *** Makefile 23 Dec 2001 05:59:08 -0000 1.4 --- Makefile 26 Feb 2002 08:04:48 -0000 1.4.2.1 *************** *** 33,37 **** # njbfs.o ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} --- 33,37 ---- # njbfs.o ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ./njbfs_cache.o ./njbfs_dir.o ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} |
From: Ben O. <ben...@us...> - 2002-02-26 02:23:40
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv449 Modified Files: Tag: ben proc.c Log Message: ben: whoops back that out Index: proc.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.c,v retrieving revision 1.6.2.4 retrieving revision 1.6.2.5 diff -C2 -d -r1.6.2.4 -r1.6.2.5 *** proc.c 26 Feb 2002 02:20:05 -0000 1.6.2.4 --- proc.c 26 Feb 2002 02:23:38 -0000 1.6.2.5 *************** *** 428,431 **** --- 428,520 ---- } + int write_id3_frame(char *buf, char *id, char *val) + { + u_int32_t size; + int i, count = 0; + + for (i = 0; i < 4; i++, count++) { + buf[count] = id[i]; + } + size = __cpu_to_be32((u_int32_t) strlen(val) + 1); + + memcpy((void *) buf + count, &size, 4); + count += 4; + + /* defaults for frame header tag, zero */ + buf[count++] = 0x0; + buf[count++] = 0x0; + + /* this signifies iso-whatever (standard) encoding */ + buf[count++] = 0x0; + + for (i = 0; val[i]; i++) + buf[count++] = val[i]; + + return count; + } + + int write_id3_frame_numeric(char *buf, char *id, u_int32_t val) + { + static char vbuf[80]; + sprintf(vbuf, "%u", val); + return write_id3_frame(buf, id, vbuf); + } + + int create_id3_tag(struct dentry *dentry, char *buffer) + { + struct njbfs_fattr *fattr; + char *p = buffer; + struct njbfs_sb_info *info = + (struct njbfs_sb_info *) dentry->d_inode->i_sb->u.generic_sbp; + u_int32_t size = NJBFS_ID3SIZE - 10; + /* our blocksize minus 10 for the tag header */ + int i; + + njbfs_read_lock(dentry->d_inode); + fattr = njbfs_get_attr_nolock(dentry, info); + if ( ! fattr ) + return -EINVAL; + njbfs_read_unlock(dentry->d_inode); + + memset(buffer, 0, NJBFS_BLOCKSIZE); + + strcat(buffer, "ID3"); + + /* set to version 2.3.0 */ + buffer[3] = 0x03; + buffer[4] = 0x00; + + /* all id3 flags empty */ + buffer[5] = 0x00; + + /* id3 uses a 28 bit number for tag size. how odd. */ + for (i = 0; i <= 4; i++) { + buffer[9 - i] = (char) size & 0x7F; + size >>= 7; + } + + p = buffer + 10; + /* write da tags, biznatch */ + if ( fattr->artist ) + p += write_id3_frame(p, "TPE1", fattr->artist); + + if ( fattr->title ) + p += write_id3_frame(p, "TIT2", fattr->title); + + if ( fattr->album ) + p += write_id3_frame(p, "TALB", fattr->album); + + if ( fattr->genre ) + p += write_id3_frame(p, "TCON", fattr->genre); + + if ( fattr->tracknum ) + p += write_id3_frame_numeric(p, "TRCK", fattr->tracknum); + + if ( fattr->year ) + p += write_id3_frame_numeric(p, "TYER", fattr->year); + + return 0; + } + /* we pass this function into generic_file_read. *************** *** 678,683 **** return bytes + faked; } - - /** --- 767,770 ---- |
From: Ben O. <ben...@us...> - 2002-02-26 02:22:25
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv32676 Modified Files: Tag: ben njbfs_cache.h Log Message: ben: whoops didnt mean to check that in Index: njbfs_cache.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.h,v retrieving revision 1.4.2.3 retrieving revision 1.4.2.4 diff -C2 -d -r1.4.2.3 -r1.4.2.4 *** njbfs_cache.h 26 Feb 2002 02:20:05 -0000 1.4.2.3 --- njbfs_cache.h 26 Feb 2002 02:22:22 -0000 1.4.2.4 *************** *** 192,204 **** }; - struct njbfs_write_cache { - int fileid; - off_t offset; - void *page; - struct njbfs_write_cache *prev; - struct njbfs_write_cache *next; - }; - - struct njbfs_sb_info; --- 192,195 ---- |
From: Ben O. <ben...@us...> - 2002-02-26 02:20:08
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv32132 Modified Files: Tag: ben njbfs_cache.c njbfs_cache.h njbfs_dir.c proc.c Log Message: ben: memory issue changes from head of branch Index: njbfs_cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.c,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** njbfs_cache.c 24 Feb 2002 11:33:58 -0000 1.1.2.1 --- njbfs_cache.c 26 Feb 2002 02:20:05 -0000 1.1.2.2 *************** *** 552,561 **** while(fattr_list) { fattr = fattr_list->fattr; - kfree(fattr->fname); - kfree(fattr->codec); - kfree(fattr->title); - kfree(fattr->artist); - kfree(fattr->album); - kfree(fattr->genre); track_destroy(fattr->track); --- 552,555 ---- *************** *** 724,738 **** while (frame != NULL) { if (!strcmp(FR_ARTIST, frame->label)) { ! SAFE_STRDUP_NULL(fattr->artist, (char *) frame->data); } else if (!strcmp(FR_FNAME, frame->label)) { ! SAFE_STRDUP_NULL(fattr->fname, (char *) frame->data); } else if (!strcmp(FR_TITLE, frame->label)) { ! SAFE_STRDUP_NULL(fattr->title, (char *) frame->data); } else if (!strcmp(FR_CODEC, frame->label)) { ! SAFE_STRDUP_NULL(fattr->codec, (char *) frame->data); } else if (!strcmp(FR_ALBUM, frame->label)) { ! SAFE_STRDUP_NULL(fattr->album, (char *) frame->data); } else if (!strcmp(FR_GENRE, frame->label)) { ! SAFE_STRDUP_NULL(fattr->genre, (char *) frame->data); } else if (!strcmp(FR_SIZE, frame->label)) { fattr->size = get_track_size(frame); --- 718,732 ---- while (frame != NULL) { if (!strcmp(FR_ARTIST, frame->label)) { ! fattr->artist = frame->data; } else if (!strcmp(FR_FNAME, frame->label)) { ! fattr->fname = frame->data; } else if (!strcmp(FR_TITLE, frame->label)) { ! fattr->title = frame->data; } else if (!strcmp(FR_CODEC, frame->label)) { ! fattr->codec = frame->data; } else if (!strcmp(FR_ALBUM, frame->label)) { ! fattr->album = frame->data; } else if (!strcmp(FR_GENRE, frame->label)) { ! fattr->genre = frame->data; } else if (!strcmp(FR_SIZE, frame->label)) { fattr->size = get_track_size(frame); Index: njbfs_cache.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.h,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** njbfs_cache.h 24 Feb 2002 11:33:58 -0000 1.4.2.2 --- njbfs_cache.h 26 Feb 2002 02:20:05 -0000 1.4.2.3 *************** *** 192,195 **** --- 192,204 ---- }; + struct njbfs_write_cache { + int fileid; + off_t offset; + void *page; + struct njbfs_write_cache *prev; + struct njbfs_write_cache *next; + }; + + struct njbfs_sb_info; Index: njbfs_dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_dir.c,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** njbfs_dir.c 24 Feb 2002 11:33:58 -0000 1.1.2.1 --- njbfs_dir.c 26 Feb 2002 02:20:05 -0000 1.1.2.2 *************** *** 177,180 **** --- 177,185 ---- p->entry.atime = CURRENT_TIME; + kfree(album); + kfree(artist); + kfree(title); + kfree(codec); + return 0; } Index: proc.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.c,v retrieving revision 1.6.2.3 retrieving revision 1.6.2.4 diff -C2 -d -r1.6.2.3 -r1.6.2.4 *** proc.c 24 Feb 2002 11:33:58 -0000 1.6.2.3 --- proc.c 26 Feb 2002 02:20:05 -0000 1.6.2.4 *************** *** 428,520 **** } - int write_id3_frame(char *buf, char *id, char *val) - { - u_int32_t size; - int i, count = 0; - - for (i = 0; i < 4; i++, count++) { - buf[count] = id[i]; - } - size = __cpu_to_be32((u_int32_t) strlen(val) + 1); - - memcpy((void *) buf + count, &size, 4); - count += 4; - - /* defaults for frame header tag, zero */ - buf[count++] = 0x0; - buf[count++] = 0x0; - - /* this signifies iso-whatever (standard) encoding */ - buf[count++] = 0x0; - - for (i = 0; val[i]; i++) - buf[count++] = val[i]; - - return count; - } - - int write_id3_frame_numeric(char *buf, char *id, u_int32_t val) - { - static char vbuf[80]; - sprintf(vbuf, "%u", val); - return write_id3_frame(buf, id, vbuf); - } - - int create_id3_tag(struct dentry *dentry, char *buffer) - { - struct njbfs_fattr *fattr; - char *p = buffer; - struct njbfs_sb_info *info = - (struct njbfs_sb_info *) dentry->d_inode->i_sb->u.generic_sbp; - u_int32_t size = NJBFS_ID3SIZE - 10; - /* our blocksize minus 10 for the tag header */ - int i; - - njbfs_read_lock(dentry->d_inode); - fattr = njbfs_get_attr_nolock(dentry, info); - if ( ! fattr ) - return -EINVAL; - njbfs_read_unlock(dentry->d_inode); - - memset(buffer, 0, NJBFS_BLOCKSIZE); - - strcat(buffer, "ID3"); - - /* set to version 2.3.0 */ - buffer[3] = 0x03; - buffer[4] = 0x00; - - /* all id3 flags empty */ - buffer[5] = 0x00; - - /* id3 uses a 28 bit number for tag size. how odd. */ - for (i = 0; i <= 4; i++) { - buffer[9 - i] = (char) size & 0x7F; - size >>= 7; - } - - p = buffer + 10; - /* write da tags, biznatch */ - if ( fattr->artist ) - p += write_id3_frame(p, "TPE1", fattr->artist); - - if ( fattr->title ) - p += write_id3_frame(p, "TIT2", fattr->title); - - if ( fattr->album ) - p += write_id3_frame(p, "TALB", fattr->album); - - if ( fattr->genre ) - p += write_id3_frame(p, "TCON", fattr->genre); - - if ( fattr->tracknum ) - p += write_id3_frame_numeric(p, "TRCK", fattr->tracknum); - - if ( fattr->year ) - p += write_id3_frame_numeric(p, "TYER", fattr->year); - - return 0; - } - /* we pass this function into generic_file_read. --- 428,431 ---- *************** *** 767,770 **** --- 678,683 ---- return bytes + faked; } + + /** |
From: Ben O. <ben...@us...> - 2002-02-26 02:11:50
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv30325 Modified Files: njbfs_cache.c njbfs_dir.c Log Message: Ben: fix memory issues/ leaks Index: njbfs_cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** njbfs_cache.c 24 Feb 2002 00:15:13 -0000 1.1 --- njbfs_cache.c 26 Feb 2002 02:11:47 -0000 1.2 *************** *** 552,561 **** while(fattr_list) { fattr = fattr_list->fattr; - kfree(fattr->fname); - kfree(fattr->codec); - kfree(fattr->title); - kfree(fattr->artist); - kfree(fattr->album); - kfree(fattr->genre); track_destroy(fattr->track); --- 552,555 ---- *************** *** 724,738 **** while (frame != NULL) { if (!strcmp(FR_ARTIST, frame->label)) { ! SAFE_STRDUP_NULL(fattr->artist, (char *) frame->data); } else if (!strcmp(FR_FNAME, frame->label)) { ! SAFE_STRDUP_NULL(fattr->fname, (char *) frame->data); } else if (!strcmp(FR_TITLE, frame->label)) { ! SAFE_STRDUP_NULL(fattr->title, (char *) frame->data); } else if (!strcmp(FR_CODEC, frame->label)) { ! SAFE_STRDUP_NULL(fattr->codec, (char *) frame->data); } else if (!strcmp(FR_ALBUM, frame->label)) { ! SAFE_STRDUP_NULL(fattr->album, (char *) frame->data); } else if (!strcmp(FR_GENRE, frame->label)) { ! SAFE_STRDUP_NULL(fattr->genre, (char *) frame->data); } else if (!strcmp(FR_SIZE, frame->label)) { fattr->size = get_track_size(frame); --- 718,732 ---- while (frame != NULL) { if (!strcmp(FR_ARTIST, frame->label)) { ! fattr->artist = frame->data; } else if (!strcmp(FR_FNAME, frame->label)) { ! fattr->fname = frame->data; } else if (!strcmp(FR_TITLE, frame->label)) { ! fattr->title = frame->data; } else if (!strcmp(FR_CODEC, frame->label)) { ! fattr->codec = frame->data; } else if (!strcmp(FR_ALBUM, frame->label)) { ! fattr->album = frame->data; } else if (!strcmp(FR_GENRE, frame->label)) { ! fattr->genre = frame->data; } else if (!strcmp(FR_SIZE, frame->label)) { fattr->size = get_track_size(frame); Index: njbfs_dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_dir.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** njbfs_dir.c 24 Feb 2002 00:15:13 -0000 1.1 --- njbfs_dir.c 26 Feb 2002 02:11:47 -0000 1.2 *************** *** 178,181 **** --- 178,186 ---- p->entry.atime = CURRENT_TIME; + kfree(album); + kfree(artist); + kfree(title); + kfree(codec); + return 0; } |
From: Ben O. <ben...@us...> - 2002-02-24 11:34:02
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv3625 Modified Files: Tag: ben automount.c cache.c dir.c inode.c njb_usb.c njb_usb.h njbfs.h njbfs_cache.h njbfs_proc.h nomad_usb.h proc.c track.c Added Files: Tag: ben njbfs_cache.c njbfs_dir.c njbfs_dir.h proc.h Log Message: Roll changes from the cvs head (directory break-down) into this branch. --- NEW FILE: njbfs_cache.c --- /* * Nomad Jukebox filesystem for Linux. * * Copyright (C) 2001 Jörg Prante <joe...@gm...> * Copyright (C) 2002 Ben Osheroff <be...@gi...> * * based on ftpfs by Florin Malita <fm...@ya...> * * 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 of the * License, 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. * */ /** * Processing the directives from the VFS and delegate them to the * NJB USB subsystem */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/usb.h> #include <linux/time.h> #include <linux/ctype.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/errno.h> #include "njbfs.h" #include "track.h" #include "proc.h" #include "njbfs_cache.h" #include "njb_usb.h" /* linked lists that we use as our primary cache mechanism. */ struct njbfs_fattr_list *track_list_head = NULL; struct njbfs_album_list *album_list_head = NULL; struct njbfs_artist_list *artist_list_head = NULL; struct njbfs_genre_list *genre_list_head = NULL; /* here is a listing of "virtual" fattr structures... ie they are only directories in our fs, not actual tracks. */ struct njbfs_fattr_list *virtual_list_head = NULL; /* forward decl */ static struct njbfs_fattr *get_fattr_from_track(struct njbfs_sb_info *info, track_t * track); /* BEGIN HASHTABLE FUNCTIONS. Unfortuneately, the hashing functions in cache.c are not quite generic enough (too directory-specific) for our purposes here. */ njbfs_hash_element **artist_hash = NULL; njbfs_hash_element **album_hash = NULL; njbfs_hash_element **genre_hash = NULL; unsigned long njbfs_generic_hash(char *name) { unsigned long hash = 0; int i; for (i = 0; i < strlen(name); i++) hash += name[i]; return hash % NJBFS_GENERIC_HASH_SIZE; } static int njbfs_init_hashtables() { int size = sizeof(njbfs_hash_element *) * NJBFS_GENERIC_HASH_SIZE; artist_hash = kmalloc(size, GFP_KERNEL); album_hash = kmalloc(size, GFP_KERNEL); genre_hash = kmalloc(size, GFP_KERNEL); if ( !artist_hash || !album_hash || !genre_hash ) return -ENOMEM; memset(artist_hash, 0, size); memset(album_hash, 0, size); memset(genre_hash, 0, size); return 0; } static void __njbfs_destroy_hashtable(njbfs_hash_element **table) { njbfs_hash_element *el, *last; int i; if ( !table) return; for (i = 0; i < NJBFS_GENERIC_HASH_SIZE; i++) { el = table[i]; while (el) { last = el; el = el->next; kfree(last); } } kfree(table); } void njbfs_destroy_hashtables() { __njbfs_destroy_hashtable(artist_hash); __njbfs_destroy_hashtable(album_hash); __njbfs_destroy_hashtable(genre_hash); artist_hash = album_hash = genre_hash = NULL; } /* this assumes you've already determined that the element isn't in the hash table. ie will add duplicates if you're not careful. */ static int njbfs_add_hash_generic(njbfs_hash_element **table, char *id, void *data) { njbfs_hash_element *element; unsigned long hash; if ( !table ) return -1; hash = njbfs_generic_hash(id); element = NULL; element = kmalloc(sizeof (njbfs_hash_element), GFP_KERNEL); if ( !element ) { err("couldn't kmalloc hash_element"); return -ENOMEM; } element->next = table[hash]; element->data = data; element->id = id; table[hash] = element; return 0; } static void* njbfs_get_hash_generic(njbfs_hash_element **table, char *id) { njbfs_hash_element *walk; unsigned long hash; if ( !table ) return NULL; hash = njbfs_generic_hash(id); if ( ! table[hash] ) { return NULL; } else { walk = table[hash]; for(walk = table[hash]; walk != NULL; walk = walk->next) { if ( strcmp(walk->id, id) == 0) return walk->data; } } return NULL; } struct njbfs_artist *njbfs_get_artist(char *name) { return njbfs_get_hash_generic(artist_hash, name); } /* albums are the one item in our world not guaranteed to be unique.... we don't want to allocate "__unknown__" to just one artist. so we have to use a special hash function that guarantees uniquity. */ struct njbfs_album *njbfs_get_album(char *name, char *artist) { struct njbfs_album *a; njbfs_hash_element **table = album_hash; njbfs_hash_element *walk; unsigned long hash; if ( !table ) return NULL; hash = njbfs_generic_hash(name); if ( ! table[hash] ) return NULL; walk = table[hash]; for(walk = table[hash]; walk != NULL; walk = walk->next) { if ( strcmp(walk->id, name) == 0) { a = walk->data; if ( a->artist && !strcmp(a->artist->name, artist) ) return walk->data; } } return NULL; } /* this returns a (kmalloc'ed) album list of all albums matching the specified name. Please free when done. Used when listing /albums/<unknown> or another non-unique album name. */ struct njbfs_album_list *njbfs_get_albums(char *name) { struct njbfs_album_list *a = NULL, *b; njbfs_hash_element **table = album_hash; njbfs_hash_element *walk; unsigned long hash; if ( !table ) return NULL; hash = njbfs_generic_hash(name); if ( ! table[hash] ) return NULL; walk = table[hash]; for(walk = table[hash]; walk != NULL; walk = walk->next) { if ( strcmp(walk->id, name) == 0) { b = kmalloc(sizeof(struct njbfs_album_list), GFP_KERNEL); if ( !b ) return NULL; b->album = walk->data; b->next = a; a = b; } } return a; } struct njbfs_genre *njbfs_get_genre(char *name) { return njbfs_get_hash_generic(genre_hash, name); } struct njbfs_artist *njbfs_add_artist(char *name) { struct njbfs_artist_list *artist_list; struct njbfs_artist *artist; artist_list = kmalloc(sizeof(struct njbfs_artist_list), GFP_KERNEL); if ( !artist_list ) { err("couldn't kmalloc njbfs_artist"); return NULL; } artist = kmalloc(sizeof(struct njbfs_artist), GFP_KERNEL); if ( !artist ) { err("couldn't kmalloc njbfs_artist"); return NULL; } /* init the artist structure */ artist->name = name; artist->albums = NULL; artist->tracks = NULL; artist_list->artist = artist; /* add to the big linked list */ artist_list->next = artist_list_head; artist_list_head = artist_list; /* add to the hash table */ if ( njbfs_add_hash_generic(artist_hash, name, artist) ) return NULL; return artist; } struct njbfs_album *njbfs_add_album(char *name, struct njbfs_artist *artist) { struct njbfs_album_list *album_list; struct njbfs_album *album; album_list = kmalloc(sizeof(struct njbfs_album_list), GFP_KERNEL); if ( !album_list ) { err("couldn't kmalloc njbfs_album"); return NULL; } album = kmalloc(sizeof(struct njbfs_album), GFP_KERNEL); if ( !album ) { err("couldn't kmalloc njbfs_album"); return NULL; } /* init the album structure */ album->name = name; album->artist = artist; album->tracks = NULL; /* add to the big linked list */ album_list->album = album; album_list->next = album_list_head; album_list_head = album_list; /* add to the artist's albums. we re-use album_list here. I realized I probably could've stolen all this from libnjb. Damn. */ album_list = kmalloc(sizeof(struct njbfs_album_list), GFP_KERNEL); if ( !album_list ) { err("couldn't kmalloc njbfs_album"); return NULL; } album_list->album = album; if ( !artist->albums ) { album_list->next = NULL; artist->albums = album_list; } else { album_list->next = artist->albums; artist->albums = album_list; } /* add to the hash table */ if ( njbfs_add_hash_generic(album_hash, name, album) ) return NULL; return album; } struct njbfs_genre *njbfs_add_genre(char *name) { struct njbfs_genre_list *genre_list; struct njbfs_genre *genre; genre_list = kmalloc(sizeof(struct njbfs_genre_list), GFP_KERNEL); if ( !genre_list ) { err("Couldn't kmalloc genre_list"); return NULL; } genre = kmalloc(sizeof(struct njbfs_genre), GFP_KERNEL); if ( !genre ) { err("Couldn't kmalloc genre"); return NULL; } genre->name = name; genre->tracks = NULL; genre_list->genre = genre; genre_list->next = genre_list_head; genre_list_head = genre_list; /* add to the hash table */ if ( njbfs_add_hash_generic(genre_hash, name, genre) ) return NULL; return genre; } struct njbfs_fattr_list* add_fattr_to_list(struct njbfs_fattr_list **list, struct njbfs_fattr *fattr) { struct njbfs_fattr_list * list_element = kmalloc(sizeof(struct njbfs_fattr_list), GFP_KERNEL); if ( ! list_element ){ err("couldn't kmalloc njbfs_fattr_list"); return NULL; } list_element->next = *list; list_element->fattr = fattr; *list = list_element; return (list_element); } /* Add a particular fattr structure to all of our cache structures (lists, hashtables) This is the main entry point for adding a track into the cache. */ int njbfs_add_fattr(struct njbfs_fattr *fattr) { struct njbfs_fattr_list *list; struct njbfs_artist *njbfs_artist; struct njbfs_album *njbfs_album; struct njbfs_genre *njbfs_genre; list = kmalloc(sizeof(struct njbfs_fattr_list), GFP_KERNEL); if ( !list ) { err("Couldn't kmalloc fattr_lists"); return -ENOMEM; } /* try to get the associated artist */ njbfs_artist = njbfs_get_artist(fattr->artist); if ( !njbfs_artist ) { njbfs_artist = njbfs_add_artist(fattr->artist); if ( !njbfs_artist ) return -ENOMEM; } /* now try to find the album it belongs to. */ njbfs_album = njbfs_get_album(fattr->album, fattr->artist); if ( !njbfs_album) { njbfs_album = njbfs_add_album(fattr->album, njbfs_artist); if ( !njbfs_album ) return -ENOMEM; } /* and the genre, do be do be do */ njbfs_genre = njbfs_get_genre(fattr->genre); if ( !njbfs_genre ) { njbfs_genre = njbfs_add_genre(fattr->genre); if ( !njbfs_album ) return -ENOMEM; } if ( !add_fattr_to_list(&njbfs_album->tracks, fattr) ) return -ENOMEM; if ( !add_fattr_to_list(&njbfs_artist->tracks, fattr) ) return -ENOMEM; if ( !add_fattr_to_list(&njbfs_genre->tracks, fattr) ) return -ENOMEM; if ( !add_fattr_to_list(&track_list_head, fattr) ) return -ENOMEM; return 0; } /* remove a fattr pointer from a single linked list */ void njbfs_remove_fattr_from_list(struct njbfs_fattr_list **list, struct njbfs_fattr *fattr) { struct njbfs_fattr_list *last, *cur; if (!list || !*list) return; if ( (*list)->fattr == fattr ) { *list = (*list)->next; return; } else { last = *list; cur = (*list)->next; while ( cur ) { if (cur->fattr == fattr) { last->next = cur->next; return; } last = cur; cur = cur->next; } } } void njbfs_remove_fattr(struct njbfs_fattr *fattr) { struct njbfs_artist *njbfs_artist; struct njbfs_album *njbfs_album; struct njbfs_genre *njbfs_genre; /* try to get the associated artist */ njbfs_artist = njbfs_get_hash_generic(artist_hash, fattr->artist); if ( njbfs_artist ) njbfs_remove_fattr_from_list(&njbfs_artist->tracks, fattr); /* now try to find the album it belongs to. */ njbfs_album = njbfs_get_hash_generic(album_hash, fattr->album); if ( njbfs_album) njbfs_remove_fattr_from_list(&njbfs_album->tracks, fattr); /* and the genre, do be do be do */ njbfs_genre = njbfs_get_hash_generic(genre_hash, fattr->genre); if ( njbfs_genre ) njbfs_remove_fattr_from_list(&njbfs_genre->tracks, fattr); njbfs_remove_fattr_from_list(&track_list_head, fattr); return; } void njbfs_destroy_fattr_cache() { struct njbfs_fattr *fattr; struct njbfs_fattr_list *fattr_list; struct njbfs_artist *artist; struct njbfs_artist_list *artist_list; struct njbfs_album_list *album_list; struct njbfs_album *album; struct njbfs_genre_list *genre_list; struct njbfs_genre *genre; void *last; /* first free all the file attribute structures and the tracks linked list */ fattr_list = track_list_head; while(fattr_list) { fattr = fattr_list->fattr; kfree(fattr->fname); kfree(fattr->codec); kfree(fattr->title); kfree(fattr->artist); kfree(fattr->album); kfree(fattr->genre); track_destroy(fattr->track); last = fattr_list; fattr_list = fattr_list->next; kfree(last); } track_list_head = NULL; /* now destroy the virtual directories linked list */ fattr_list = virtual_list_head; while(fattr_list) { fattr = fattr_list->fattr; kfree(fattr->fname); last = fattr_list; fattr_list = fattr_list->next; kfree(last); } virtual_list_head = NULL; /* now the artist list */ artist_list = artist_list_head; while(artist_list) { artist = artist_list->artist; /* strip away the "shells" */ album_list = artist->albums; while (album_list) { last = album_list; album_list = album_list->next; kfree(last); } fattr_list = artist->tracks; while ( fattr_list ) { last = fattr_list; fattr_list = fattr_list->next; kfree(last); } kfree(artist); last = artist_list; artist_list = artist_list->next; kfree(last); } artist_list_head = NULL; /* and the albums */ album_list = album_list_head; while(album_list) { album = album_list->album; fattr_list = album->tracks; while ( fattr_list ) { last = fattr_list; fattr_list = fattr_list->next; kfree(last); } kfree(album); last = album_list; album_list = album_list->next; kfree(last); } album_list_head = NULL; /* and the genres */ genre_list = genre_list_head; while(genre_list) { genre = genre_list->genre; fattr_list = genre->tracks; while ( fattr_list ) { last = fattr_list; fattr_list = fattr_list->next; kfree(last); } kfree(genre); last = genre_list; genre_list = genre_list->next; kfree(last); } album_list_head = NULL; /* now the hashtables */ njbfs_destroy_hashtables(); } int init_fattr_cache(struct njbfs_sb_info *info) { struct nomad_usb_data *njb = info->njb; struct njbfs_fattr *fattr; njbttaghdr_t header; track_t *track; int status; /* sanity check: have we been through this already? */ if ( track_list_head ) return 0; if ( njbfs_init_hashtables() ) { err("couldn't initialize hashtables!"); return -ENOMEM; } /* capture njb */ status = njb_usb_capture(njb); if (status < 0) { err("loaddir: capture failed, status=%d", status); return -EIO; } status = njb_usb_get_first_track_tag_header(njb, &header); while (status != -ENOENT) { track = njb_usb_get_track_tag(njb, &header); if (track == NULL) break; fattr = get_fattr_from_track(info, track); if ( !fattr ) { err("Bad track: Nomad track_id %d", track->header.trackid); status = njb_usb_release(njb); return -EIO; } status = njbfs_add_fattr(fattr); if ( status ) break; status = njb_usb_get_next_track_tag_header(njb, &header); } /* release njb */ status = njb_usb_release(njb); if (status < 0) { err("loaddir: release failed, status=%d", status); return -EIO; } return 0; } /** * Get a fattr struct from a track structure */ static struct njbfs_fattr *get_fattr_from_track(struct njbfs_sb_info *info, track_t * track) { struct njbfs_fattr *fattr; track_frame_t *frame; char *ch; fattr = kmalloc(sizeof (struct njbfs_fattr), GFP_KERNEL); if ( !fattr ) { err("Couldn't kmalloc fattr struct!"); return NULL; } memset(fattr, 0, sizeof(struct njbfs_fattr)); track->cur = track->first; frame = track->cur; while (frame != NULL) { if (!strcmp(FR_ARTIST, frame->label)) { SAFE_STRDUP_NULL(fattr->artist, (char *) frame->data); } else if (!strcmp(FR_FNAME, frame->label)) { SAFE_STRDUP_NULL(fattr->fname, (char *) frame->data); } else if (!strcmp(FR_TITLE, frame->label)) { SAFE_STRDUP_NULL(fattr->title, (char *) frame->data); } else if (!strcmp(FR_CODEC, frame->label)) { SAFE_STRDUP_NULL(fattr->codec, (char *) frame->data); } else if (!strcmp(FR_ALBUM, frame->label)) { SAFE_STRDUP_NULL(fattr->album, (char *) frame->data); } else if (!strcmp(FR_GENRE, frame->label)) { SAFE_STRDUP_NULL(fattr->genre, (char *) frame->data); } else if (!strcmp(FR_SIZE, frame->label)) { fattr->size = get_track_size(frame); } else if (!strcmp(FR_TRACK, frame->label)) { memcpy(&fattr->tracknum, frame->data, 4); } frame = track_getframe(track); } /* codec to lower case (MP3 ->mp3) */ ch = fattr->codec; while ((*ch = tolower(*ch)) != 0) ch++; fattr->f_ino = 0; fattr->f_mode = info->mnt.file_mode; fattr->f_uid = info->mnt.uid; fattr->f_gid = info->mnt.gid; fattr->f_atime = fattr->f_mtime = CURRENT_TIME; /* support for ID3 tag faking */ fattr->real_size = fattr->size; fattr->size = fattr->size + NJBFS_ID3SIZE + NJBFS_FOOTERSIZE + (NJBFS_BLOCKSIZE - (fattr->size % NJBFS_BLOCKSIZE)); fattr->f_blksize = NJBFS_BLOCKSIZE; fattr->f_blocks = (fattr->size + (NJBFS_BLOCKSIZE - 1)) >> (NJBFS_BLOCKSIZE_BITS - 1); fattr->fileid = track->header.trackid; fattr->track = track; return fattr; } --- NEW FILE: njbfs_dir.c --- #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/usb.h> #include <linux/time.h> #include <linux/ctype.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/errno.h> #include "njbfs.h" #include "njbfs_cache.h" #include "njbfs_dir.h" /* with an empty jukebox, we'll keep querying and querying. or maybe get an error. I'm not sure. This is also not the right place for this comment. But hey. */ #define CHECK_FATTR_CACHE(info) \ if ( !track_list_head ) { \ int status; \ status = init_fattr_cache(info); \ if ( status ) \ return status; \ } /** * Initialize root directory */ void njbfs_init_root_dirent(struct njbfs_sb_info *server, struct njbfs_fattr *fattr) { memset(fattr, 0, sizeof(*fattr)); fattr->f_nlink = 1; fattr->f_uid = server->mnt.uid; fattr->f_gid = server->mnt.gid; fattr->f_blksize = NJBFS_BLOCKSIZE; fattr->f_ino = 2; fattr->f_mtime = CURRENT_TIME; fattr->f_mode = S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH | S_IFDIR | server->mnt.dir_mode; fattr->size = NJBFS_BLOCKSIZE; fattr->f_blocks = 0; } static void translate_bad_chars(char *ch) { while (*ch) { switch (*ch) { case '/': *ch = '_'; case '*': *ch = '_'; case '?': *ch = '_'; } ch++; } } int njbfs_get_dirlist_node_from_fattr(struct njbfs_dirlist_node *p, struct njbfs_fattr *fattr, int whereami) { char buf[NJBFS_MAXPATHLEN]; char *ch, *codec, *album, *artist, *title; /* do we use the exact file name? If we don't have enough info, yeah. */ if ((!fattr->artist) || (!fattr->title) || (!fattr->codec) || (!fattr->album)) { if (fattr->fname) { SAFE_STRDUP(p->entry.name, fattr->fname); } else { return -EINVAL; } } SAFE_STRDUP(album, fattr->album); SAFE_STRDUP(artist, fattr->artist); SAFE_STRDUP(codec, fattr->codec); SAFE_STRDUP(title, fattr->title); /* codec to lower case (MP3 ->mp3) */ ch = fattr->codec; while ((*ch = tolower(*ch)) != 0) ch++; translate_bad_chars(album); translate_bad_chars(artist); translate_bad_chars(title); /* set the filename conditionally, based on what directory we're in. */ switch(whereami) { case LOADDIR_AN_ALBUM: case LOADDIR_ARTIST_ALBUM: sprintf(buf, NJBFS_FILENAME_ALBUMDIR(artist, album, title, fattr->tracknum, codec)); break; case LOADDIR_AN_ALBUM_MULTIPLE: sprintf(buf, NJBFS_FILENAME_MULTIPLEALBUMDIR(artist, album, title, fattr->tracknum, codec)); break; case LOADDIR_TRACKS: sprintf(buf, NJBFS_FILENAME_TRACKSDIR(artist, album, title, fattr->tracknum, codec)); break; case LOADDIR_ARTIST_ALLTRACKS: sprintf(buf, NJBFS_FILENAME_ALLTRACKSDIR(artist, album, title, fattr->tracknum, codec)); break; case LOADDIR_A_GENRE: sprintf(buf, NJBFS_FILENAME_GENREDIR(artist, album, title, fattr->tracknum, codec)); break; case LOADDIR_EXACTNAME: sprintf(buf, fattr->fname); break; default: sprintf(buf, NJBFS_FILENAME_GENERIC(artist, album, title, fattr->tracknum, codec)); break; } SAFE_STRDUP(p->entry.name, buf); p->entry.fattr = fattr; /* attributes */ p->entry.size = fattr->size; p->entry.blocksize = NJBFS_BLOCKSIZE; p->entry.blocks = (p->entry.size + (NJBFS_BLOCKSIZE - 1)) >> (NJBFS_BLOCKSIZE_BITS - 1); p->entry.mode |= S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; p->entry.atime = CURRENT_TIME; return 0; } /* * Load the given fattr list into the directory */ int njbfs_load_fattr_list(struct njbfs_fattr_list *list, int whereami, struct njbfs_directory *dir) { int status; struct njbfs_dirlist_node *p; for ( ; list != NULL; list = list->next ) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); status = njbfs_get_dirlist_node_from_fattr(p, list->fattr, whereami); if (status < 0) { err ("loaddir: unable to get dirlist node from fattr"); kfree(p); return -EIO; } p->prev = NULL; p->next = dir->head; dir->head = p; } return 0; } /* gets a dirlist node (and creates a fattr struct) for our virtual directories */ static void njbfs_dirlist_node_directories(struct njbfs_dirlist_node *p, struct njbfs_sb_info *info) { struct njbfs_fattr *f; f = kmalloc(sizeof(struct njbfs_fattr), GFP_KERNEL); if ( !f ) return; memset(f, 0, sizeof(struct njbfs_fattr)); f->f_mode = p->entry.mode = info->mnt.dir_mode | S_IFDIR; f->f_uid = info->mnt.uid; f->f_gid = info->mnt.gid; f->size = p->entry.size = NJBFS_BLOCKSIZE; f->f_atime = p->entry.atime = CURRENT_TIME; f->f_mtime = CURRENT_TIME; f->f_ctime = CURRENT_TIME; add_fattr_to_list(&virtual_list_head, f); p->entry.fattr = f; } int njbfs_load_rootdir(struct njbfs_sb_info *info, struct njbfs_directory *dir) { int i; struct njbfs_dirlist_node *p; for(i=0; i<4; i++) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); switch ( i ) { case 0: SAFE_STRDUP(p->entry.name, "artists"); break; case 1: SAFE_STRDUP(p->entry.name, "albums"); break; case 2: SAFE_STRDUP(p->entry.name, "genres"); break; case 3: SAFE_STRDUP(p->entry.name, "tracks"); break; } njbfs_dirlist_node_directories(p, info); p->prev = NULL; p->next = dir->head; dir->head = p; } return 0; } /** * Get "track" directory entries from NJB */ int njbfs_load_trackdir(struct njbfs_sb_info *info, struct njbfs_directory *dir) { CHECK_FATTR_CACHE(info); return njbfs_load_fattr_list(track_list_head, LOADDIR_TRACKS, dir); } /** * Get "/albums" directory entries from NJB cache */ int njbfs_load_albumsdir(struct njbfs_sb_info *info, struct njbfs_directory *dir) { struct njbfs_dirlist_node *p; struct njbfs_album_list *list; CHECK_FATTR_CACHE(info); for ( list = album_list_head; list != NULL; list = list->next ) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->album->name); njbfs_dirlist_node_directories(p,info); p->prev = NULL; p->next = dir->head; dir->head = p; } return 0; } /** * Get "/artists" directory entries from NJB cache */ int njbfs_load_artistsdir(struct njbfs_sb_info *info, struct njbfs_directory *dir) { struct njbfs_dirlist_node *p; struct njbfs_artist_list *list; CHECK_FATTR_CACHE(info); for ( list = artist_list_head; list != NULL; list = list->next ) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->artist->name); njbfs_dirlist_node_directories(p, info); p->prev = NULL; p->next = dir->head; dir->head = p; } return 0; } /** * Get "/genres" directory entries from NJB cache */ int njbfs_load_genresdir(struct njbfs_sb_info *info, struct njbfs_directory *dir) { struct njbfs_dirlist_node *p; struct njbfs_genre_list *list; CHECK_FATTR_CACHE(info); for ( list = genre_list_head; list != NULL; list = list->next ) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, list->genre->name); njbfs_dirlist_node_directories(p,info); p->prev = NULL; p->next = dir->head; dir->head = p; } return 0; } /** * Get "/genre/hamster music" directory entries from NJB */ int njbfs_load_a_genredir(struct njbfs_sb_info *info, struct njbfs_directory *dir, char *genre) { struct njbfs_genre *g; CHECK_FATTR_CACHE(info); g = njbfs_get_genre(genre); if (! g) { err("failed to find genre in hash tables!"); return -EINVAL; } return njbfs_load_fattr_list(g->tracks, LOADDIR_A_GENRE, dir); } /** * Get "/artists/Tom Waits" directory entries from NJB cache */ int njbfs_load_an_artistdir(struct njbfs_sb_info *info, struct njbfs_directory *dir, char *artistname) { struct njbfs_dirlist_node *p; struct njbfs_artist *artist; struct njbfs_album_list *list; CHECK_FATTR_CACHE(info); artist = njbfs_get_artist(artistname); if ( ! artist ) return -EINVAL; for ( list = artist->albums; list != NULL; list = list->next ) { p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name,list->album->name); njbfs_dirlist_node_directories(p, info); p->prev = NULL; p->next = dir->head; dir->head = p; } /* add the "__all__" (all tracks) dir */ p = (struct njbfs_dirlist_node *) kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); if (!p) { err("loaddir: kmalloc error"); return -ENOMEM; } memset(p, 0, sizeof(struct njbfs_dirlist_node)); SAFE_STRDUP(p->entry.name, NJBFS_ALLTRACKS_DIR); njbfs_dirlist_node_directories(p, info); p->prev = NULL; p->next = dir->head; dir->head = p; return 0; } /** * Get "/artist/Tom Waits/Rain Dogs" directory entries from NJB */ int njbfs_load_artist_alltracks(struct njbfs_sb_info *info, struct njbfs_directory *dir, char *artist) { struct njbfs_artist *a; CHECK_FATTR_CACHE(info); a = njbfs_get_artist(artist); if (! artist) { err("failed to find artist in hash tables!"); return -EINVAL; } return njbfs_load_fattr_list(a->tracks, LOADDIR_ARTIST_ALLTRACKS, dir); } /** * Get "/artist/Tom Waits/Rain Dogs" directory entries from NJB */ int njbfs_load_artist_albumdir(struct njbfs_sb_info *info, struct njbfs_directory *dir, char *album, char *artist) { struct njbfs_album *a; CHECK_FATTR_CACHE(info); a = njbfs_get_album(album, artist); if (! album) { err("failed to find album in hash tables!"); return -EINVAL; } return njbfs_load_fattr_list(a->tracks, LOADDIR_ARTIST_ALBUM, dir); } /** * Get "/albums/Rain Dogs" directory entries from NJB */ int njbfs_load_an_albumdir(struct njbfs_sb_info *info, struct njbfs_directory *dir, char *title) { struct njbfs_album_list *list, *tmp; int status = 0, count = 0, whereami; CHECK_FATTR_CACHE(info); list = njbfs_get_albums(title); if (! list) { err("failed to find album in hash tables!"); return -EINVAL; } /* count the number of albums so we know if we're dealing with multiple albums or not. (and change whereami accordingly) */ tmp = list; while (list) { count++; list = list->next; } if (count > 1) whereami = LOADDIR_AN_ALBUM_MULTIPLE; else whereami = LOADDIR_AN_ALBUM; list = tmp; while (list) { status = njbfs_load_fattr_list(list->album->tracks, whereami, dir); if ( status ) break; list = list->next; } list = tmp; while (list) { tmp = list; list = list->next; kfree(tmp); } return status; } /* parses up a full pathname, returns an integer indicating the type of directory, and info is filled with malloc'ed information. */ int __loaddir_whereami(char *name, char **info, char **info2) { char *work, *p; char *ar = NULL, *al = NULL, *gn = NULL; *info = NULL; if ( strcmp(name, "/") == 0 ) return LOADDIR_ROOT; else if ( strcmp(name, "/artists") == 0 ) return LOADDIR_ARTISTS; else if ( strcmp(name, "/albums") == 0 ) return LOADDIR_ALBUMS; else if ( strcmp(name, "/tracks") == 0 ) return LOADDIR_TRACKS; else if ( strcmp(name, "/genres") == 0 ) return LOADDIR_GENRES; else { SAFE_STRDUP_ZERO(work, name); if ( strncmp(name, "/artists", 8) == 0) { p = strtok(work, "/"); ar = strtok(NULL, "/"); al = strtok(NULL, "/"); if ( al ) { if ( strcmp(al, NJBFS_ALLTRACKS_DIR) == 0 ) { SAFE_STRDUP_ZERO(*info, ar); kfree(work); return LOADDIR_ARTIST_ALLTRACKS; } SAFE_STRDUP_ZERO(*info, al); SAFE_STRDUP_ZERO(*info2, ar); kfree(work); return LOADDIR_ARTIST_ALBUM; } else if ( ar ) { SAFE_STRDUP_ZERO(*info, ar); kfree(work); return LOADDIR_AN_ARTIST; } else { kfree(work); return 0; } } else if ( strncmp(name, "/albums", 7) == 0) { p = strtok(work, "/"); al = strtok(NULL, "/"); if ( al ) { SAFE_STRDUP_ZERO(*info, al); kfree(work); return LOADDIR_AN_ALBUM; } else { kfree(work); return 0; } } else if ( strncmp (name, "/genres", 7) == 0) { p = strtok(work, "/"); gn = strtok(NULL, "/"); if ( gn ) { SAFE_STRDUP_ZERO(*info, gn); kfree(work); return LOADDIR_A_GENRE; } else { kfree(work); return 0; } } } return 0; } /* here's the main entry point from cache_add. figures out where we are in the njbfs heirarchy and calls the appropriate function. */ int njbfs_loaddir(struct njbfs_sb_info *info, char *name, struct njbfs_directory *dir) { char *xinfo, *yinfo; int ret; int status = __loaddir_whereami(name, &xinfo, &yinfo); switch(status) { case LOADDIR_ROOT: return njbfs_load_rootdir(info, dir); case LOADDIR_ARTISTS: return njbfs_load_artistsdir(info,dir); case LOADDIR_ALBUMS: return njbfs_load_albumsdir(info,dir); case LOADDIR_GENRES: return njbfs_load_genresdir(info,dir); case LOADDIR_TRACKS: return njbfs_load_trackdir(info,dir); case LOADDIR_AN_ARTIST: ret = njbfs_load_an_artistdir(info, dir, xinfo); kfree(xinfo); return(ret); case LOADDIR_ARTIST_ALLTRACKS: ret = njbfs_load_artist_alltracks(info, dir,xinfo); kfree(xinfo); return ret; case LOADDIR_AN_ALBUM: ret = njbfs_load_an_albumdir(info, dir, xinfo); kfree(xinfo); return(ret); case LOADDIR_ARTIST_ALBUM: ret = njbfs_load_artist_albumdir(info, dir, xinfo, yinfo); kfree(xinfo); kfree(yinfo); return(ret); case LOADDIR_A_GENRE: ret = njbfs_load_a_genredir(info, dir, xinfo); kfree(xinfo); return(ret); default: return(-1); } } --- NEW FILE: njbfs_dir.h --- #ifndef _NJBFS_DIR_H #define _NJBFS_DIR_H int njbfs_get_dirlist_node_from_fattr(struct njbfs_dirlist_node *p, struct njbfs_fattr *fattr, int whereami); /* oh, yes, these could be an enum. Used when we're loading up a directory. */ #define LOADDIR_ROOT 1 #define LOADDIR_ARTISTS 2 #define LOADDIR_ALBUMS 3 #define LOADDIR_AN_ARTIST 4 #define LOADDIR_AN_ALBUM 5 #define LOADDIR_ARTIST_ALLTRACKS 6 #define LOADDIR_GENRES 7 #define LOADDIR_A_GENRE 8 #define LOADDIR_TRACKS 9 #define LOADDIR_EXACTNAME 10 /* used when "create" needs a temp dirlist node */ #define LOADDIR_AN_ALBUM_MULTIPLE 11 /* used when an album name is non-unique */ #define LOADDIR_ARTIST_ALBUM 12 /* for /artist/album/foo */ #endif --- NEW FILE: proc.h --- #ifndef _NJB_PROC_H_ #define _NJB_PROC_H_ #include "nomad_usb.h" #define UNKNOWN_STRING "__unknown__" #endif Index: automount.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/automount.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** automount.c 10 Feb 2002 21:59:23 -0000 1.2 --- automount.c 24 Feb 2002 11:33:58 -0000 1.2.2.1 *************** *** 28,46 **** int main(int argc, char **argv) { - - char *virtualdirectory; /* "tracks", "playlists", "artists", "albums" */ - - if ((argc < 2) || - (strcmp("tracks", argv[1]) && - strcmp("playlists", argv[1]) && - strcmp("artists", argv[1]) && strcmp("albums", argv[1]))) { - - fprintf(stderr, - "Need virtual directory name here: 'tracks', 'playlists', 'albums' or 'artists'\n"); - exit(-1); - } - - virtualdirectory = argv[1]; - printf("-fstype=njbfs,dir=%s none\n", virtualdirectory); return 0; } --- 28,31 ---- Index: cache.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/cache.c,v retrieving revision 1.4.2.1 retrieving revision 1.4.2.2 diff -C2 -d -r1.4.2.1 -r1.4.2.2 *** cache.c 15 Feb 2002 20:07:32 -0000 1.4.2.1 --- cache.c 24 Feb 2002 11:33:58 -0000 1.4.2.2 *************** *** 113,116 **** --- 113,138 ---- } + int njbfs_cache_addnode(struct njbfs_sb_info *info, + char *dirname, struct njbfs_dirlist_node *n) + { + struct njbfs_hashlist_node *p; + + unsigned long hsh = njbfs_cache_hash(dirname); + + for(p = dir_cache.hash[hsh]; p; p = p->next) { + if ( strcmp(p->directory.name, dirname) == 0 ) + break; + } + + if ( !p ) + return -EINVAL; + + n->next = p->directory.head; + n->prev = NULL; + p->directory.head = n; + return 0; + } + + int njbfs_cache_add(struct njbfs_sb_info *info, char *name, struct njbfs_directory **dir) *************** *** 144,148 **** strcpy(p->directory.name, name); - info("cache_add: loading directory '%s'....", name); if ((res = njbfs_loaddir(info, name, &p->directory)) < 0) { err("cache_add: couldn't load directory"); --- 166,169 ---- *************** *** 200,203 **** --- 221,226 ---- njbfs_cache_deldir(p); } + dir_cache.len[i] = 0; + dir_cache.hash[i] = NULL; return 0; } Index: dir.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/dir.c,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -C2 -d -r1.3.2.1 -r1.3.2.2 *** dir.c 15 Feb 2002 20:07:32 -0000 1.3.2.1 --- dir.c 24 Feb 2002 11:33:58 -0000 1.3.2.2 *************** *** 22,25 **** --- 22,26 ---- */ + #include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> *************** *** 35,38 **** --- 36,40 ---- #include "njbfs.h" #include "njbfs_proc.h" + #include "njbfs_dir.h" static int njbfs_lookup_validate(struct dentry *, int); *************** *** 220,232 **** struct njbfs_sb_info *info = (struct njbfs_sb_info *) sb->u.generic_sbp; ! struct njbfs_fattr fattr; struct inode *inode; ! int res; ! dbg("dname:%s", dentry->d_name.name); ! if ((res = njbfs_get_attr(dentry, &fattr, ! (struct njbfs_sb_info *) dir->i_sb->u. ! generic_sbp, 0) < 0)) { ! inode = NULL; dentry->d_op = &njbfs_dentry_operations; --- 222,234 ---- struct njbfs_sb_info *info = (struct njbfs_sb_info *) sb->u.generic_sbp; ! struct njbfs_fattr *fattr; struct inode *inode; ! int res = 0; ! /* ben: I'm not sure where -ERESTARTSYS could be returned ! from, so this is kinda broken... */ ! ! fattr = njbfs_get_attr(dentry, info); ! if (!fattr) { inode = NULL; dentry->d_op = &njbfs_dentry_operations; *************** *** 240,246 **** return NULL; } - fattr.f_ino = iunique(dentry->d_sb, 2); - inode = njbfs_iget(dir->i_sb, &fattr); if (inode) { dentry->d_op = &njbfs_dentry_operations; --- 242,249 ---- return NULL; } + + fattr->f_ino = iunique(dentry->d_sb, 2); + inode = njbfs_iget(dir->i_sb, fattr); if (inode) { dentry->d_op = &njbfs_dentry_operations; *************** *** 255,268 **** struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; ! struct njbfs_fattr fattr; struct inode *inode; ! ! if (njbfs_get_attr(dentry, &fattr, info, 0) < 0) { info("njbfs_get_attr failed"); return -1; } ! fattr.f_ino = iunique(dentry->d_sb, 2); ! inode = njbfs_iget(dentry->d_sb, &fattr); if (!inode) return -EACCES; --- 258,272 ---- struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; ! struct njbfs_fattr *fattr; struct inode *inode; ! ! fattr = njbfs_get_attr(dentry, info); ! if ( !fattr ) { info("njbfs_get_attr failed"); return -1; } ! fattr->f_ino = iunique(dentry->d_sb, 2); ! inode = njbfs_iget(dentry->d_sb, fattr); if (!inode) return -EACCES; *************** *** 280,283 **** --- 284,291 ---- int res; + /* ben: can't think of a great use for mkdir now. */ + info("sorry, no making of directories."); + return -EINVAL; + njbfs_get_name(dentry, buf); if ((res = njbfs_proc_mkdir(info, buf)) < 0) { *************** *** 291,307 **** static int njbfs_create(struct inode *dir, struct dentry *dentry, int mode) { struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; ! char buf[NJBFS_MAXPATHLEN]; int res; ! njbfs_get_name(dentry, buf); ! if ((res = njbfs_proc_create(info, buf)) < 0) { err("create failed"); return res; } ! njbfs_cache_invalidate(dentry->d_parent); ! return njbfs_instantiate(dentry); } --- 299,352 ---- static int njbfs_create(struct inode *dir, struct dentry *dentry, int mode) { + struct inode *inode; + struct njbfs_fattr *fattr; + struct njbfs_dirlist_node *p; struct njbfs_sb_info *info = (struct njbfs_sb_info *) dentry->d_sb->u.generic_sbp; ! static char buf[NJBFS_MAXPATHLEN]; int res; ! strncpy(buf, dentry->d_name.name, dentry->d_name.len); ! buf[dentry->d_name.len] = '\0'; ! ! if ((res = njbfs_proc_create(info, buf, &fattr)) < 0) { err("create failed"); return res; } + SAFE_STRDUP(fattr->fname, buf); ! p = kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); ! if (!p ) { ! err("couldn't kmalloc dirlist_node"); ! return -ENOMEM; ! } ! ! /* give us a dirlist node with the exact requested filename */ ! res = njbfs_get_dirlist_node_from_fattr(p, ! fattr, LOADDIR_EXACTNAME); ! if ( res < 0 ) { ! err("couldn't create dirlist_node!"); ! return res; ! } ! ! /* get the directory name under which we are trying to ! create the file, and add the dirlist_node to ! this directories cache */ ! njbfs_get_dirname(dentry, buf); ! res = njbfs_cache_addnode(info, buf, p); ! if ( res < 0 ) { ! err("couldn't add the created file to the cache"); ! kfree(p); ! return res; ! } ! ! fattr->f_ino = iunique(dentry->d_sb, 2); ! inode = njbfs_iget(dentry->d_sb, fattr); ! if ( !inode ) { ! return -EINVAL; ! } ! ! d_instantiate(dentry, inode); ! return 0; } *************** *** 329,332 **** --- 374,385 ---- (struct njbfs_sb_info *) old_dentry->d_sb->u.generic_sbp; int res; + + /* + ben: this code is still mostly broken... + I don't know if I broke it or what. + I think it might never have worked right. + */ + info("njbfs: sorry, this feature is broken for now."); + return -EINVAL; if (new_dentry->d_inode) { Index: inode.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/inode.c,v retrieving revision 1.5.2.1 retrieving revision 1.5.2.2 diff -C2 -d -r1.5.2.1 -r1.5.2.2 *** inode.c 15 Feb 2002 20:07:32 -0000 1.5.2.1 --- inode.c 24 Feb 2002 11:33:58 -0000 1.5.2.2 *************** *** 77,82 **** { struct inode *res; - res = new_inode(sb); if (!res) return NULL; --- 77,82 ---- { struct inode *res; res = new_inode(sb); + if (!res) return NULL; *************** *** 112,116 **** inode->i_blksize = fattr->f_blksize; inode->i_blocks = fattr->f_blocks; ! inode->i_size = fattr->f_size; } --- 112,116 ---- inode->i_blksize = fattr->f_blksize; inode->i_blocks = fattr->f_blocks; ! inode->i_size = fattr->size; } *************** *** 170,175 **** info->mnt.active = 0; ! info->mnt.file_mode = (S_IRUSR | S_IFREG); ! info->mnt.dir_mode = (S_IRUSR | S_IXUSR | S_IFDIR); info->mnt.uid = current->uid; info->mnt.gid = current->gid; --- 170,175 ---- info->mnt.active = 0; ! info->mnt.file_mode = (S_IRUSR | S_IFREG | S_IROTH | S_IRGRP); ! info->mnt.dir_mode = (S_IRUSR | S_IXUSR | S_IFDIR | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH); info->mnt.uid = current->uid; info->mnt.gid = current->gid; *************** *** 178,184 **** info->njb->sb = info; - info->virtual_mode = 0; - strcpy(info->virtual_dir, ""); - init_MUTEX(&info->sem); --- 178,181 ---- *************** *** 245,248 **** --- 242,246 ---- proc_njb_destroy(); #endif + njbfs_destroy_fattr_cache(); usb_nomad_cleanup(); Index: njb_usb.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.c,v retrieving revision 1.4.2.2 retrieving revision 1.4.2.3 diff -C2 -d -r1.4.2.2 -r1.4.2.3 *** njb_usb.c 19 Feb 2002 06:26:47 -0000 1.4.2.2 --- njb_usb.c 24 Feb 2002 11:33:58 -0000 1.4.2.3 *************** *** 38,73 **** #include "track.h" #include "playlist.h" #include "njbfs_proc.h" - #define dbg err - /* forward decl's */ - static int njb_usb_connect(struct nomad_usb_data *nomad); - static int njb_usb_disconnect(struct nomad_usb_data *nomad); - static int njb_usb_open(struct nomad_usb_data *nomad, - struct njbfs_fattr *fattr); - static int njb_usb_close(struct nomad_usb_data *nomad, - struct njbfs_fattr *fattr); - static int njb_usb_write(struct nomad_usb_data *nomad, char *name, - u_int32_t offset, u_int32_t count, void *buffer); - static int njb_usb_read(struct nomad_usb_data *nomad, - u_int32_t offset, u_int32_t count, void *buffer); - static int njb_usb_rename(struct nomad_usb_data *nomad, - struct njbfs_fattr *fattr); - static int njb_usb_delete(struct nomad_usb_data *nomad, char *file); - static int njb_usb_create(struct nomad_usb_data *nomad, char *file); - static int njb_usb_check(struct nomad_usb_data *njb); - static int njb_usb_capture(struct nomad_usb_data *njb); - static int njb_usb_handshake(struct nomad_usb_data *njb); - static int njb_usb_release(struct nomad_usb_data *njb); - static int njb_usb_control(struct nomad_usb_data *njb, unsigned int pipe, - int request, int requesttype, int value, - int index, void *data, int size, int retries); - static int njb_usb_verify_last_command(struct nomad_usb_data *njb); - static int njb_usb_update_library_counter(struct nomad_usb_data *njb); - static track_t *njb_usb_update_track_tag(struct nomad_usb_data *njb, - struct njbfs_fattr *fattr, - u_int32_t * trackid); - static int njb_usb_get_disk_usage(struct nomad_usb_data *njb, - u_int64_t * total, u_int64_t * free); #ifdef DEBUG --- 38,44 ---- #include "track.h" #include "playlist.h" + #include "proc.h" #include "njbfs_proc.h" #ifdef DEBUG *************** *** 75,78 **** --- 46,125 ---- #endif + /** + * Check the internal state of the NJB connection. + * The NJB USB structure and the device should be plugged in. + * These are sanity checks. It is never assumed that a NJB + * structure is missing, this function makes it only harder to + * bypass the internal NJB connection management. + * + * @param njb the NJB USB structure + * @return 0 if success, otherwise < 0 + */ + int njb_usb_check(struct nomad_usb_data *njb) + { + if (!njb) { + err("check: driver not installed"); + return -ENXIO; + } + if (!(njb->nomad_dev)) { + err("check: jukebox not connected"); + return -ENODEV; + } + return 0; + } + + /** + * Send NJB control message. On the USB, all communications are + * initiated by the host through the control pipe. A request packet + * is sent, followed by a data phase for that request, if there is + * data associated with the request. The setup and data phases are + * done on the control pipe, with the setup packet indicating the + * direction flow for the data phase. Additional data may be sent + * after the control message via the bulk data pipes in response to a + * request. + * + * @param njb the NJB USB structure + * @param pipe the control pipe + * @param request the request + * @param requesttype the type of the request + * @param value a value for the request + * @param index an index for the request + * @param data the data buffer for the request (not NULL) + * @param size the size of the data buffer + * @param retries how many times the control message shall be retried + */ + int + njb_usb_control(struct nomad_usb_data *njb, unsigned int pipe, + int request, int requesttype, int value, int index, + void *data, int size, int retries) + { + int status; + + if ((status = njb_usb_check(njb)) < 0) + return status; + + if (down_interruptible(&(njb->lock))) + return -EINTR; + + while (retries) { + status = + usb_control_msg(njb->nomad_dev, pipe, request, + requesttype, value, index, data, size, + USB_CONTROL_TIMEOUT); + if (status == -ETIMEDOUT) { + dbg("control: got a timeout, retrying..."); + retries--; + } else if (status < 0) { + err("control: error, result = %d", + le32_to_cpu(status)); + retries = 0; + } else { + retries = 0; + } + } + up(&(njb->lock)); + + return 0; + } *************** *** 84,88 **** * @param 0 if success, otherwise < 0 */ ! static int njb_usb_connect(struct nomad_usb_data *njb) { int status; --- 131,135 ---- * @param 0 if success, otherwise < 0 */ ! int njb_usb_connect(struct nomad_usb_data *njb) { int status; *************** *** 104,108 **** * @param 0 if success, otherwise < 0 */ ! static int njb_usb_disconnect(struct nomad_usb_data *njb) { int status; --- 151,155 ---- * @param 0 if success, otherwise < 0 */ ! int njb_usb_disconnect(struct nomad_usb_data *njb) { int status; *************** *** 123,127 **** * @param fattr the file attributes */ ! static int njb_usb_open(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { --- 170,174 ---- * @param fattr the file attributes */ ! int njb_usb_open(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { *************** *** 323,327 **** * Close a file NJB on USB. */ ! static int njb_usb_close(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { --- 370,374 ---- * Close a file NJB on USB. */ ! int njb_usb_close(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { *************** *** 331,335 **** njb_usb_release(njb); } ! static int njb_usb_close_no_release(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) --- 378,383 ---- njb_usb_release(njb); } ! ! int njb_usb_close_no_release(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) *************** *** 339,348 **** /** - * - - /** * Read block from USB NJB */ ! static int njb_usb_read(struct nomad_usb_data *njb, u_int32_t offset, u_int32_t count, void *buffer) { --- 387,393 ---- /** * Read block from USB NJB */ ! int njb_usb_read(struct nomad_usb_data *njb, u_int32_t offset, u_int32_t count, void *buffer) { *************** *** 425,429 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_write(struct nomad_usb_data *njb, char *name, u_int32_t offset, u_int32_t count, void *buffer) --- 470,474 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_write(struct nomad_usb_data *njb, char *name, u_int32_t offset, u_int32_t count, void *buffer) *************** *** 502,506 **** */ ! static int njb_usb_rename(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { --- 547,551 ---- */ ! int njb_usb_rename(struct nomad_usb_data *njb, struct njbfs_fattr *fattr) { *************** *** 523,527 **** * Delete a file from the NJB */ ! static int njb_usb_delete(struct nomad_usb_data *nomad, char *file) { info("TODO: usb delete"); --- 568,572 ---- * Delete a file from the NJB */ ! int njb_usb_delete(struct nomad_usb_data *nomad, char *file) { info("TODO: usb delete"); *************** *** 533,537 **** * Create a file on the NJB */ ! static int njb_usb_create(struct nomad_usb_data *njb, char *file) { info("TODO: create"); --- 578,582 ---- * Create a file on the NJB */ ! int njb_usb_create(struct nomad_usb_data *njb, char *file) { info("TODO: create"); *************** *** 542,621 **** /* ----------------------- NJB functions -------------------------- */ - /** - * Check the internal state of the NJB connection. - * The NJB USB structure and the device should be plugged in. - * These are sanity checks. It is never assumed that a NJB - * structure is missing, this function makes it only harder to - * bypass the internal NJB connection management. - * - * @param njb the NJB USB structure - * @return 0 if success, otherwise < 0 - */ - int njb_usb_check(struct nomad_usb_data *njb) - { - if (!njb) { - err("check: driver not installed"); - return -ENXIO; - } - if (!(njb->nomad_dev)) { - err("check: jukebox not connected"); - return -ENODEV; - } - return 0; - } - - /** - * Send NJB control message. On the USB, all communications are - * initiated by the host through the control pipe. A request packet - * is sent, followed by a data phase for that request, if there is - * data associated with the request. The setup and data phases are - * done on the control pipe, with the setup packet indicating the - * direction flow for the data phase. Additional data may be sent - * after the control message via the bulk data pipes in response to a - * request. - * - * @param njb the NJB USB structure - * @param pipe the control pipe - * @param request the request - * @param requesttype the type of the request - * @param value a value for the request - * @param index an index for the request - * @param data the data buffer for the request (not NULL) - * @param size the size of the data buffer - * @param retries how mny times the control message shall be retried - */ - static int - njb_usb_control(struct nomad_usb_data *njb, unsigned int pipe, - int request, int requesttype, int value, int index, - void *data, int size, int retries) - { - int status; - - if ((status = njb_usb_check(njb)) < 0) - return status; - - if (down_interruptible(&(njb->lock))) - return -EINTR; - - while (retries) { - status = - usb_control_msg(njb->nomad_dev, pipe, request, - requesttype, value, index, data, size, - USB_CONTROL_TIMEOUT); - if (status == -ETIMEDOUT) { - dbg("control: got a timeout, retrying..."); - retries--; - } else if (status < 0) { - err("control: error, result = %d", - le32_to_cpu(status)); - retries = 0; - } else { - retries = 0; - } - } - up(&(njb->lock)); - - return 0; - } /** --- 587,590 ---- *************** *** 629,633 **** * */ ! static int njb_usb_capture(struct nomad_usb_data *njb) { int status; --- 598,602 ---- * */ ! int njb_usb_capture(struct nomad_usb_data *njb) { int status; *************** *** 667,671 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_release(struct nomad_usb_data *njb) { int status; --- 636,640 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_release(struct nomad_usb_data *njb) { int status; *************** *** 697,701 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_verify_last_command(struct nomad_usb_data *njb) { int status; --- 666,670 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_verify_last_command(struct nomad_usb_data *njb) { int status; *************** *** 724,728 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_ping(struct nomad_usb_data *njb, njbid_t * njbid) { unsigned char data[58]; --- 693,697 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_ping(struct nomad_usb_data *njb, njbid_t * njbid) { unsigned char data[58]; *************** *** 780,784 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_set_library_counter(struct nomad_usb_data *njb, u_int64_t count) { --- 749,753 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_set_library_counter(struct nomad_usb_data *njb, u_int64_t count) { *************** *** 815,819 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_get_library_counter(struct nomad_usb_data *njb, njblibctr_t * lcount) --- 784,788 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_get_library_counter(struct nomad_usb_data *njb, njblibctr_t * lcount) *************** *** 859,863 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_handshake(struct nomad_usb_data *njb) { int status; --- 828,832 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_handshake(struct nomad_usb_data *njb) { int status; *************** *** 944,948 **** * @return 0 if success, otherwise < 0 */ ! static int njb_usb_update_library_counter(struct nomad_usb_data *njb) { int status; --- 913,917 ---- * @return 0 if success, otherwise < 0 */ ! int njb_usb_update_library_counter(struct nomad_usb_data *njb) { int status; *************** *** 987,991 **** * @return 0 if everything is ok or <0 if there was an error */ ! static int njb_usb_get_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header, int cmd) --- 956,960 ---- * @return 0 if everything is ok or <0 if there was an error */ ! int njb_usb_get_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header, int cmd) *************** *** 1034,1038 **** ! inline static int njb_usb_get_first_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header) --- 1003,1007 ---- ! inline int njb_usb_get_first_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header) *************** *** 1042,1046 **** } ! inline static int njb_usb_get_next_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header) --- 1011,1015 ---- } ! inline int njb_usb_get_next_track_tag_header(struct nomad_usb_data *njb, njbttaghdr_t * header) *************** *** 1056,1060 **** * previously "Get Track Tag Header" request. */ ! static track_t *njb_usb_get_track_tag(struct nomad_usb_data *njb, njbttaghdr_t * header) { --- 1025,1029 ---- * previously "Get Track Tag Header" request. */ ! track_t *njb_usb_get_track_tag(struct nomad_usb_data *njb, njbttaghdr_t * header) { *************** *** 1095,1098 **** --- 1064,1068 ---- if (status < 0) { err("get_track_tag: njb control error"); + kfree(data); return NULL; } *************** *** 1139,1143 **** * @return status */ ! static int njb_usb_get_disk_usage(struct nomad_usb_data *njb, u_int64_t * total, u_int64_t * free) --- 1109,1113 ---- * @return status */ ! int njb_usb_get_disk_usage(struct nomad_usb_data *njb, u_int64_t * total, u_int64_t * free) *************** *** 1185,1189 **** */ ! static int njb_usb_new_track_tag(struct nomad_usb_data *njb, void *tag, njbttaghdr_t * header) --- 1155,1159 ---- */ ! int njb_usb_new_track_tag(struct nomad_usb_data *njb, void *tag, njbttaghdr_t * header) *************** *** 1268,1272 **** * @return status */ ! static int njb_usb_replace_track_tag(struct nomad_usb_data *njb, void *tag, njbttaghdr_t * header) --- 1238,1242 ---- * @return status */ ! int njb_usb_replace_track_tag(struct nomad_usb_data *njb, void *tag, njbttaghdr_t * header) *************** *** 1335,1339 **** * @return a valid new track, or NULL if an error occured */ ! static track_t *njb_usb_update_track_tag(struct nomad_usb_data *njb, struct njbfs_fattr *fattr, u_int32_t * trackid) --- 1305,1309 ---- * @return a valid new track, or NULL if an error occured */ ! track_t *njb_usb_update_track_tag(struct nomad_usb_data *njb, struct njbfs_fattr *fattr, u_int32_t * trackid) *************** *** 1522,1526 **** * @return 0 if everything is ok or <0 if there was an error */ ! static int njb_usb_get_playlist_header(struct nomad_usb_data *njb, njbplhdr_t * header, int cmd) --- 1492,1496 ---- * @return 0 if everything is ok or <0 if there was an error */ ! int njb_usb_get_playlist_header(struct nomad_usb_data *njb, njbplhdr_t * header, int cmd) *************** *** 1571,1575 **** * */ ! static playlist_t *njb_usb_get_playlist(struct nomad_usb_data *njb, njbplhdr_t * header) { --- 1541,1545 ---- * */ ! playlist_t *njb_usb_get_playlist(struct nomad_usb_data *njb, njbplhdr_t * header) { Index: njb_usb.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.h,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -C2 -d -r1.3.2.1 -r1.3.2.2 *** njb_usb.h 15 Feb 2002 19:23:15 -0000 1.3.2.1 --- njb_usb.h 24 Feb 2002 11:33:58 -0000 1.3.2.2 *************** *** 2,5 **** --- 2,7 ---- #define _NJB_USB_H_ + #include "njbfs.h" + #define LSW(x) (uint16_t)(x) #define MSW(x) (uint16_t)((uint32_t)(x) >> 16) *************** *** 142,144 **** --- 144,174 ---- #define NJB_UNDEFINED_ERR 0xff + extern int njb_usb_capture(struct nomad_usb_data *njb); + extern int njb_usb_release(struct nomad_usb_data *njb); + extern int njb_usb_get_first_track_tag_header(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern int njb_usb_get_next_track_tag_header(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern track_t *njb_usb_get_track_tag(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern int njb_usb_connect(struct nomad_usb_data *njb); + extern int njb_usb_disconnect(struct nomad_usb_data *njb); + extern int njb_usb_open(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_close(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_write(struct nomad_usb_data *njb, char *name, + u_int32_t offset, u_int32_t count, void *buffer); + extern int njb_usb_read(struct nomad_usb_data *njb, u_int32_t offset, u_int32_t count, void *buffer); + extern int njb_usb_rename(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_delete(struct nomad_usb_data *njb, char *file); + extern int njb_usb_create(struct nomad_usb_data *njb, char *file); + extern int njb_usb_handshake(struct nomad_usb_data *njb); + extern int njb_usb... [truncated message content] |
From: Ben O. <ben...@us...> - 2002-02-24 00:28:03
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv3297 Modified Files: Makefile Log Message: Ben: support for all this Index: Makefile =================================================================== RCS file: /cvsroot/njbfs/njbfs/Makefile,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Makefile 23 Dec 2001 05:59:08 -0000 1.4 --- Makefile 24 Feb 2002 00:28:01 -0000 1.5 *************** *** 33,37 **** # njbfs.o ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} --- 33,37 ---- # njbfs.o ! njbfs.o : ./nomad.o ./cache.o ./dir.o ./file.o ./inode.o ./proc.o ./symlink.o ./njb_usb.o ./track.o ./playlist.o ./driver.o ./njbfs_cache.o ./njbfs_dir.o ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} |
From: Ben O. <ben...@us...> - 2002-02-24 00:27:52
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv3264 Modified Files: README Log Message: ben: remove some cruft that no longer applies Index: README =================================================================== RCS file: /cvsroot/njbfs/njbfs/README,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** README 9 Dec 2001 23:12:25 -0000 1.4 --- README 24 Feb 2002 00:27:49 -0000 1.5 *************** *** 1,5 **** This is the README file for Nomad Jukebox File System (njbfs) ! Current version: 0.2 About njbfs --- 1,5 ---- This is the README file for Nomad Jukebox File System (njbfs) ! Current version: 0.2.2 About njbfs *************** *** 96,103 **** file size. ! Do not worry about uploading takes longer than on the PlayCenter2. The ! reason is that njbfs transfers in 1024 byte buffers. This is a file system ! restriction and will be improved in future versions. Genres and album ! titles can't be submitted yet, this will also be improved. You can watch driver info messages with 'tail -f /var/log/messages' as root. --- 96,100 ---- file size. ! Genres and album titles can't be submitted yet, this will be improved. You can watch driver info messages with 'tail -f /var/log/messages' as root. |
From: Ben O. <ben...@us...> - 2002-02-24 00:27:21
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv3190 Modified Files: RELEASE.NOTES Log Message: ben: change RELEASE NOTES Index: RELEASE.NOTES =================================================================== RCS file: /cvsroot/njbfs/njbfs/RELEASE.NOTES,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RELEASE.NOTES 4 Dec 2001 21:09:31 -0000 1.3 --- RELEASE.NOTES 24 Feb 2002 00:27:19 -0000 1.4 *************** *** 1 **** ! This is release 0.3 of njbfs for Linux kernel 2.4.x \ No newline at end of file --- 1,8 ---- ! This is release 0.22 of njbfs for Linux kernel 2.4.x ! ! this release adds the breakdown of tracks into ! /albums, /artists, /genres, and /tracks. ! All within one fs. ! ! yay. ! |
From: Ben O. <ben...@us...> - 2002-02-24 00:26:47
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv3087 Modified Files: track.c Log Message: ben: fix bugs in track_replaceframe and track_updateframe (they were not closing the linked list) Index: track.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/track.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** track.c 10 Feb 2002 21:59:23 -0000 1.4 --- track.c 24 Feb 2002 00:26:43 -0000 1.5 *************** *** 38,43 **** const void *data); static void track_addframe(track_t * track, track_frame_t * frame); - static void track_replaceframe(track_t * track, track_frame_t * oldframe, - track_frame_t * newframe); static void track_frame_destroy(track_frame_t * frame); static void track_updateframe(track_t * track, track_frame_t * frame); --- 38,41 ---- *************** *** 177,211 **** } ! static void track_replaceframe(track_t * track, track_frame_t * oldframe, track_frame_t * newframe) { ! track_frame_t *frame; track_reset_getframe(track); while ((frame = track_getframe(track)) != NULL) { if (!strcmp(frame->label, oldframe->label)) { ! track_frame_destroy(oldframe); ! track_addframe(track, newframe); ! return; } } ! } static void track_updateframe(track_t * track, track_frame_t * newframe) { ! track_frame_t *frame; track_reset_getframe(track); while ((frame = track_getframe(track)) != NULL) { if (!strcmp(frame->label, newframe->label)) { track_frame_destroy(frame); - track_addframe(track, newframe); return; } } track_addframe(track, newframe); - } --- 175,227 ---- } ! /* ! returns 1 if it replaced the frame, ! 0 if it didn't. ! */ ! ! static int track_replaceframe(track_t * track, track_frame_t * oldframe, track_frame_t * newframe) { ! track_frame_t *frame, *prev = NULL; track_reset_getframe(track); while ((frame = track_getframe(track)) != NULL) { if (!strcmp(frame->label, oldframe->label)) { ! if ( track->first == frame ) { ! newframe->next = track->first->next; ! track->first = newframe; ! } else if (prev) { ! newframe->next = frame->next; ! prev->next = newframe; ! } ! track_frame_destroy(frame); ! return 1; } + prev = frame; } ! return 0; } static void track_updateframe(track_t * track, track_frame_t * newframe) { ! track_frame_t *frame, *prev = NULL; track_reset_getframe(track); while ((frame = track_getframe(track)) != NULL) { if (!strcmp(frame->label, newframe->label)) { + if ( track->first == frame ) { + newframe->next = frame->next; + track->first = newframe; + } else if (prev) { + newframe->next = frame->next; + prev->next = newframe; + } track_frame_destroy(frame); return; } + prev = frame; } track_addframe(track, newframe); } |
From: Ben O. <ben...@us...> - 2002-02-24 00:25:55
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2937 Modified Files: nomad_usb.h Log Message: ben: add proper ifndefs Index: nomad_usb.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/nomad_usb.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** nomad_usb.h 15 Feb 2002 19:28:47 -0000 1.6 --- nomad_usb.h 24 Feb 2002 00:25:52 -0000 1.7 *************** *** 22,25 **** --- 22,27 ---- */ + #ifndef _NOMAD_USB_H + #define _NOMAD_USB_H *************** *** 88,89 **** --- 90,93 ---- int session_updated; }; + + #endif |
From: Ben O. <ben...@us...> - 2002-02-24 00:25:27
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2850 Modified Files: proc.c Log Message: ben: change get_attr, proc_create, add get_dirname, use SAFE_STRDUP in some places Index: proc.c =================================================================== RCS file: /cvsroot/njbfs/njbfs/proc.c,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** proc.c 10 Feb 2002 21:59:23 -0000 1.6 --- proc.c 24 Feb 2002 00:25:25 -0000 1.7 *************** *** 1,2 **** --- 1,3 ---- + /* * Nomad Jukebox filesystem for Linux. *************** *** 45,76 **** #include "njbfs.h" #include "nomad_usb.h" #include "track.h" ! ! /* njb_usb */ ! extern int njb_usb_capture(struct nomad_usb_data *njb); ! extern int njb_usb_release(struct nomad_usb_data *njb); ! extern int njb_usb_get_first_track_tag_header(struct nomad_usb_data *njb, ! njbttaghdr_t * header); ! extern int njb_usb_get_next_track_tag_header(struct nomad_usb_data *njb, ! njbttaghdr_t * header); ! extern track_t *njb_usb_get_track_tag(struct nomad_usb_data *njb, ! njbttaghdr_t * header); ! extern int njb_usb_connect(struct nomad_usb_data *njb); ! extern int njb_usb_disconnect(struct nomad_usb_data *njb); ! extern int njb_usb_open(struct nomad_usb_data *njb, ! struct njbfs_fattr *fattr); ! extern int njb_usb_close(struct nomad_usb_data *njb, ! struct njbfs_fattr *fattr); ! extern int njb_usb_write(struct nomad_usb_data *njb, char *name, ! u_int32_t offset, u_int32_t count, void *buffer); ! extern int njb_usb_read(struct nomad_usb_data *njb, char *name, ! u_int32_t offset, u_int32_t count, void *buffer); ! extern int njb_usb_rename(struct nomad_usb_data *njb, ! struct njbfs_fattr *fattr); ! extern int njb_usb_delete(struct nomad_usb_data *njb, char *file); ! extern int njb_usb_create(struct nomad_usb_data *njb, char *file); ! ! /* forward decl */ static int njbfs_parse_filename(struct njbfs_fattr *fattr, const char *file); --- 46,58 ---- #include "njbfs.h" #include "nomad_usb.h" + #include "njb_usb.h" + #include "njbfs_cache.h" #include "track.h" + #include "proc.h" + #include "njbfs_proc.h" ! /* ! forward decl ! */ static int njbfs_parse_filename(struct njbfs_fattr *fattr, const char *file); *************** *** 97,121 **** - /** - * Initialize root directory - */ - void njbfs_init_root_dirent(struct njbfs_sb_info *server, - struct njbfs_fattr *fattr) - { - memset(fattr, 0, sizeof(*fattr)); - fattr->f_nlink = 1; - fattr->f_uid = server->mnt.uid; - fattr->f_gid = server->mnt.gid; - fattr->f_blksize = NJBFS_BLOCKSIZE; - - fattr->f_ino = 2; - fattr->f_mtime = CURRENT_TIME; - fattr->f_mode = - S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH | - S_IFDIR | server->mnt.dir_mode; - fattr->f_size = NJBFS_BLOCKSIZE; - fattr->f_blocks = 0; - } - int njbfs_parse_mode(char *mode) --- 79,82 ---- *************** *** 126,152 **** /** ! * Parse directory */ int njbfs_parse_options(struct njbfs_sb_info *info, void *opts) { ! char *p; ! int optcnt = 0; ! ! strcpy(info->virtual_dir, "tracks"); ! ! if (!opts) ! return 0; ! p = strtok(opts, ","); ! for (; p; p = strtok(NULL, ",")) { ! if (strncmp(p, "dir=", 5) == 0) { ! if (strlen(p + 5) > NJBFS_MAXVIRTUALDIRLEN) { ! err("ugly opts, go away!"); ! return -EINVAL; ! } ! strcpy(info->virtual_dir, p + 5); ! optcnt++; ! } ! } ! return optcnt; } --- 87,95 ---- /** ! * Parse options. Lost the virtual directory, so nothing here for now. */ int njbfs_parse_options(struct njbfs_sb_info *info, void *opts) { ! return 0; } *************** *** 177,180 **** --- 120,126 ---- } + /* + TODO here: endian safe-ness + */ u_int32_t get_track_size(track_frame_t * frame) *************** *** 197,372 **** ! /** ! * Get directory node from a track structure ! */ ! int njbfs_get_dirlist_node_from_track(struct njbfs_dirlist_node *p, ! track_t * track) { ! char buf[NJBFS_MAXPATHLEN]; ! track_frame_t *frame; ! char *artist = NULL; ! char *title = NULL; ! char *codec = NULL; ! char *fname = NULL; ! char *ch; ! u_int32_t filesize = 0; ! int status; ! ! track->cur = track->first; ! frame = track->cur; ! ! while (frame != NULL) { ! if (!strcmp(FR_ARTIST, frame->label)) ! artist = (char *) frame->data; ! else if (!strcmp(FR_TITLE, frame->label)) ! title = (char *) frame->data; ! else if (!strcmp(FR_CODEC, frame->label)) ! codec = (char *) frame->data; ! else if (!strcmp(FR_SIZE, frame->label)) ! filesize = get_track_size(frame); ! else if (!strcmp(FR_FNAME, frame->label)) ! fname = (char *) frame->data; ! ! frame = track_getframe(track); ! } ! ! /* file name */ ! if (fname) { ! strcpy(buf, fname); ! } ! if ((!artist) || (!title) || (!codec)) ! return -EINVAL; ! ! /* codec to lower case (MP3 ->mp3) */ ! ch = codec; ! while ((*ch = tolower(*ch)) != 0) ! ch++; ! ! /* ! Replace characters like '?', '*' or '/' in ! artist and title with placeholder ! */ ! ch = artist; ! while (*ch) { ! switch (*ch) { ! case '/': ! *ch = '_'; ! case '*': ! *ch = '_'; ! case '?': ! *ch = '_'; ! } ! ch++; ! } ! ch = title; ! while (*ch) { ! switch (*ch) { ! case '/': ! *ch = '_'; ! case '*': ! *ch = '_'; ! case '?': ! *ch = '_'; ! } ! ch++; ! } ! ! status = sprintf(buf, "%s - %s.%s", artist, title, codec); ! ! p->entry.name = (char *) kmalloc(strlen(buf) + 1, GFP_KERNEL); ! if (!p->entry.name) { ! err("kmalloc error"); ! return -ENOMEM; ! } ! strcpy(p->entry.name, buf); ! ! /* attributes */ ! p->entry.size = filesize; ! p->entry.blocksize = NJBFS_BLOCKSIZE; ! p->entry.blocks = ! (p->entry.size + ! (NJBFS_BLOCKSIZE - 1)) >> (NJBFS_BLOCKSIZE_BITS - 1); ! ! p->entry.mode |= ! S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | ! S_IWOTH; ! p->entry.atime = CURRENT_TIME; ! ! p->entry.fileid = track->header.trackid; ! p->entry.track = track; ! ! return 0; } ! ! ! ! /** ! * Get directory entries from NJB ! */ ! int njbfs_loaddir(struct njbfs_sb_info *info, char *name, ! struct njbfs_directory *dir) { ! struct njbfs_dirlist_node *p; ! ! struct nomad_usb_data *njb = info->njb; ! njbttaghdr_t header; ! track_t *track; ! int status; ! ! if (strlen(info->mnt.root) + strlen(name) > NJBFS_MAXPATHLEN) { ! err("loaddir: path too long"); ! return -EINVAL; ! } ! ! /* capture njb */ ! status = njb_usb_capture(njb); ! if (status < 0) { ! err("loaddir: capture failed, status=%d", status); ! return -EIO; ! } ! ! status = njb_usb_get_first_track_tag_header(njb, &header); ! ! while (status != -ENOENT) { ! track = njb_usb_get_track_tag(njb, &header); ! if (track == NULL) ! break; ! ! p = ! (struct njbfs_dirlist_node *) ! kmalloc(sizeof(struct njbfs_dirlist_node), GFP_KERNEL); ! if (!p) { ! err("loaddir: kmalloc error"); ! return -ENOMEM; ! } ! memset(p, 0, sizeof(struct njbfs_dirlist_node)); ! ! status = njbfs_get_dirlist_node_from_track(p, track); ! if (status < 0) { ! err ! ("loaddir: unable to get dirlist node from track"); ! kfree(p); ! return -EIO; ! } ! ! p->prev = NULL; ! p->next = dir->head; ! dir->head = p; ! ! status = njb_usb_get_next_track_tag_header(njb, &header); ! } ! ! /* release njb */ ! status = njb_usb_release(njb); ! if (status < 0) { ! err("loaddir: release failed, status=%d", status); ! return -EIO; ! } ! return 0; ! } - - int njbfs_get_name(struct dentry *d, char *name) { --- 143,160 ---- ! char *njbfs_strdup(char *in) { ! char *out; ! if (!in) ! return NULL; ! out = kmalloc(strlen(in) * sizeof(char) + 1, GFP_KERNEL); ! strcpy(out, in); ! return out; } ! int njbfs_get_dirname(struct dentry *d, char *name) { ! return (njbfs_get_name(d->d_parent, name)); } int njbfs_get_name(struct dentry *d, char *name) { *************** *** 410,421 **** /** * Get attributes of a dentry */ ! int njbfs_get_attr(struct dentry *dentry, struct njbfs_fattr *fattr, ! struct njbfs_sb_info *info) { struct njbfs_directory *dir; char buf[NJBFS_MAX_LINE]; struct njbfs_dirlist_node *file; int status; --- 198,211 ---- /** * Get attributes of a dentry + * */ ! struct njbfs_fattr * ! njbfs_get_attr(struct dentry *dentry, struct njbfs_sb_info *info) { struct njbfs_directory *dir; char buf[NJBFS_MAX_LINE]; struct njbfs_dirlist_node *file; + struct njbfs_fattr *fattr; int status; *************** *** 427,431 **** if (status < 0) { err("njbfs_get_attr: cache get failed"); ! return status; } --- 217,221 ---- if (status < 0) { err("njbfs_get_attr: cache get failed"); ! return NULL; } *************** *** 438,489 **** if (!file) { ! fattr->f_mode = ! S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | ! S_IROTH | S_IWOTH; ! fattr->f_size = NJBFS_BLOCKSIZE; ! fattr->f_blksize = NJBFS_BLOCKSIZE; ! fattr->f_blocks = 0; ! fattr->f_atime = CURRENT_TIME; ! fattr->f_mtime = CURRENT_TIME; ! fattr->f_uid = info->mnt.uid; ! fattr->f_gid = info->mnt.gid; ! ! /* NJB attributes */ ! fattr->fileid = 0; ! fattr->track = NULL; ! fattr->size = 0; ! ! status = njbfs_parse_filename(fattr, dentry->d_name.name); ! ! return status; } ! ! fattr->f_mode = file->entry.mode; ! if (file->entry.mode & S_IFDIR) ! fattr->f_mode |= info->mnt.dir_mode; ! else ! fattr->f_mode |= info->mnt.file_mode; ! ! fattr->f_size = file->entry.size; ! fattr->f_blksize = file->entry.blocksize; ! fattr->f_blocks = file->entry.blocks; ! fattr->f_nlink = file->entry.nlink; ! fattr->f_atime = file->entry.atime; ! ! /*Any way to get the real mtime, ctime? */ ! fattr->f_mtime = file->entry.atime; ! fattr->f_ctime = file->entry.atime; ! fattr->f_uid = info->mnt.uid; ! fattr->f_gid = info->mnt.gid; ! ! /* get the NJB attributes */ ! fattr->fileid = file->entry.fileid; ! fattr->track = NULL; ! fattr->size = 0; ! ! status = njbfs_parse_filename(fattr, dentry->d_name.name); ! ! return status; ! } --- 228,241 ---- if (!file) { ! return (NULL); ! } else if (!file->entry.fattr) { ! /* this shouldn't happen. */ ! err("couldn't find a fattr struct!"); ! return (NULL); ! } else { ! fattr = file->entry.fattr; ! return (fattr); } ! return NULL; } *************** *** 531,551 **** (struct njbfs_sb_info *) sb->u.generic_sbp; struct dentry *dentry = f->f_dentry; ! struct njbfs_fattr fattr; int status; ! ! if ((status = njbfs_get_attr(dentry, &fattr, info)) < 0) { info("open: file not found"); ! njbfs_free_attr(&fattr); ! return status; } ! dbg("open: opening file, file id=%d", fattr.fileid); ! ! status = njb_usb_open(info->njb, &fattr); ! njbfs_free_attr(&fattr); return status; - } --- 283,300 ---- (struct njbfs_sb_info *) sb->u.generic_sbp; struct dentry *dentry = f->f_dentry; ! struct njbfs_fattr *fattr; int status; ! ! fattr = njbfs_get_attr(dentry, info); ! if (!fattr) { info("open: file not found"); ! return -ENOENT; } ! dbg("open: opening file, file id=%d", fattr->fileid); ! status = njb_usb_open(info->njb, fattr); return status; } *************** *** 559,578 **** (struct njbfs_sb_info *) sb->u.generic_sbp; struct dentry *dentry = f->f_dentry; ! struct njbfs_fattr fattr; int status; ! if ((status = njbfs_get_attr(dentry, &fattr, info)) < 0) { ! err("njbfs_close: file not found, status=%d", status); ! goto out; } ! dbg("close: closing file, file id=%d", fattr.fileid); ! status = njb_usb_close(info->njb, &fattr); ! out: ! njbfs_free_attr(&fattr); ! return status; } --- 308,331 ---- (struct njbfs_sb_info *) sb->u.generic_sbp; struct dentry *dentry = f->f_dentry; ! struct njbfs_fattr *fattr; int status; ! fattr = njbfs_get_attr(dentry, info); ! if ( !fattr ) { ! info("njbfs_close: file not found"); ! return -ENOENT; } ! dbg("close: closing file, file id=%d", fattr->fileid); ! status = njb_usb_close(info->njb, fattr); ! /* here's where we update the cache */ ! if ( fattr->update_cache ) { ! njbfs_cache_empty(info); ! fattr->update_cache = 0; ! } + return status; } *************** *** 715,718 **** --- 468,475 ---- /** * Rename file or directory + * + * TODO: will we even allow this in the new world order? + * (id3 smart recognition) + * */ int *************** *** 722,726 **** { char old_buf[NJBFS_MAXPATHLEN + 6], new_buf[NJBFS_MAXPATHLEN + 6]; ! struct njbfs_fattr old_fattr, new_fattr; int status; --- 479,483 ---- { char old_buf[NJBFS_MAXPATHLEN + 6], new_buf[NJBFS_MAXPATHLEN + 6]; ! struct njbfs_fattr *old_fattr, *new_fattr; int status; *************** *** 728,765 **** njbfs_get_name(new_dentry, new_buf); ! if ((status = njbfs_get_attr(old_dentry, &old_fattr, info)) < 0) { err("rename: file '%s' not found", old_buf); - njbfs_free_attr(&old_fattr); return status; } njbfs_lock(info); /* copy fattr */ ! new_fattr.f_mode = old_fattr.f_mode; ! new_fattr.f_size = old_fattr.f_mode; ! new_fattr.f_blksize = old_fattr.f_blksize; ! new_fattr.f_blocks = old_fattr.f_blocks; ! new_fattr.f_atime = CURRENT_TIME; ! new_fattr.f_mtime = CURRENT_TIME; ! new_fattr.f_uid = old_fattr.f_uid; ! new_fattr.f_gid = old_fattr.f_gid; ! new_fattr.fileid = old_fattr.fileid; ! new_fattr.track = NULL; ! new_fattr.size = old_fattr.size; /* default attributes */ ! new_fattr.codec = old_fattr.codec; ! new_fattr.title = old_fattr.title; ! new_fattr.artist = old_fattr.artist; ! new_fattr.album = old_fattr.album; ! new_fattr.genre = old_fattr.genre; /* parse new attributes from file name */ ! status = njbfs_parse_filename(&new_fattr, new_buf); /* rename */ ! ! if ((status = njb_usb_rename(info->njb, &new_fattr)) < 0) { err("rename: couldn't rename!"); } njbfs_unlock(info); --- 485,534 ---- njbfs_get_name(new_dentry, new_buf); ! old_fattr = njbfs_get_attr(old_dentry, info); ! if (!old_fattr) { err("rename: file '%s' not found", old_buf); return status; } + new_fattr = kmalloc(sizeof(struct njbfs_fattr), GFP_KERNEL); + if ( !new_fattr ) { + err("couldn't kmalloc new_fattr"); + return -ENOMEM; + } njbfs_lock(info); /* copy fattr */ ! new_fattr->f_mode = old_fattr->f_mode; ! new_fattr->size = old_fattr->size; ! new_fattr->f_blksize = old_fattr->f_blksize; ! new_fattr->f_blocks = old_fattr->f_blocks; ! new_fattr->f_atime = CURRENT_TIME; ! new_fattr->f_mtime = CURRENT_TIME; ! new_fattr->f_uid = old_fattr->f_uid; ! new_fattr->f_gid = old_fattr->f_gid; ! new_fattr->fileid = old_fattr->fileid; ! new_fattr->track = old_fattr->track; ! new_fattr->size = old_fattr->size; /* default attributes */ ! new_fattr->codec = old_fattr->codec; ! new_fattr->title = old_fattr->title; ! new_fattr->artist = old_fattr->artist; ! new_fattr->album = old_fattr->album; ! new_fattr->genre = old_fattr->genre; /* parse new attributes from file name */ ! status = njbfs_parse_filename(new_fattr, new_buf); /* rename */ ! if ((status = njb_usb_rename(info->njb, new_fattr)) < 0) { err("rename: couldn't rename!"); + return status; } + + /* now remove the old fattr, add the new */ + njbfs_remove_fattr(old_fattr); + njbfs_add_fattr(new_fattr); + + /* a little extreme, but it works... */ + njbfs_cache_empty(info); njbfs_unlock(info); *************** *** 792,801 **** /** ! * Create a new file ! * A created file is being reopened before written to. ! * We just parse the file name and that's it. */ ! int njbfs_proc_create(struct njbfs_sb_info *info, char *file) { char buf[NJBFS_MAXPATHLEN + 6]; int status; --- 561,571 ---- /** ! * Create a new file, fill the given fattr */ ! int njbfs_proc_create(struct njbfs_sb_info *info, ! char *file, ! struct njbfs_fattr **f) { + struct njbfs_fattr *fattr = *f; char buf[NJBFS_MAXPATHLEN + 6]; int status; *************** *** 807,819 **** sprintf(buf, "%s%s", info->mnt.root, file); - njbfs_lock(info); - ! if ((status = njb_usb_create(info->njb, buf)) < 0) { ! err("create: couldn't create file!"); ! status = -EINVAL; } njbfs_unlock(info); return status; } --- 577,625 ---- sprintf(buf, "%s%s", info->mnt.root, file); ! fattr = kmalloc(sizeof(struct njbfs_fattr), GFP_KERNEL); ! if ( !fattr ) { ! err("couldn't kmalloc fattr"); ! return -ENOMEM; } + memset(fattr, 0, sizeof(struct njbfs_fattr)); + fattr->f_mode = info->mnt.file_mode; + fattr->f_blksize = NJBFS_BLOCKSIZE; + fattr->f_blocks = 0; + fattr->f_atime = CURRENT_TIME; + fattr->f_mtime = CURRENT_TIME; + fattr->f_uid = info->mnt.uid; + fattr->f_gid = info->mnt.gid; + + /* NJB attributes */ + fattr->fileid = 0; + fattr->track = NULL; + fattr->size = 0; + + /* tell close() on the other end of all this rot + to re-init our dirlist cache */ + fattr->update_cache = 1; + + status = njbfs_parse_filename(fattr, file); + /* fill in any unkown info */ + if ( !fattr->artist ) + SAFE_STRDUP(fattr->artist, UNKNOWN_STRING); + if ( !fattr->title ) + SAFE_STRDUP(fattr->title, UNKNOWN_STRING); + if ( !fattr->album ) + SAFE_STRDUP(fattr->album, UNKNOWN_STRING); + if ( !fattr->genre ) + SAFE_STRDUP(fattr->genre, UNKNOWN_STRING); + if ( !fattr->codec ) + SAFE_STRDUP(fattr->codec, "mp3"); + + /* add to our linked lists */ + njbfs_lock(info); + + njbfs_add_fattr(fattr); + njbfs_unlock(info); + *f = fattr; return status; } *************** *** 847,865 **** } ! /* parse codec */ if ((strstr(buf, ".mp3") != NULL) || (strstr(buf, ".MP3") != NULL)) { ! fattr->codec = ! (char *) kmalloc(strlen(NJB_CODEC_MP3) + 1, ! GFP_KERNEL); ! strcpy(fattr->codec, NJB_CODEC_MP3); } else { p = k_parse_attribute(buf, "codec"); ! if (p && (!strcmp(p, "mp3") || !strcmp(p, "MP3"))) { ! fattr->codec = ! (char *) kmalloc(strlen(NJB_CODEC_MP3) + 1, ! GFP_KERNEL); ! strcpy(fattr->codec, NJB_CODEC_MP3); kfree(p); ! } else { /* default is MP3 */ fattr->codec = (char *) kmalloc(strlen(NJB_CODEC_MP3) + 1, --- 653,665 ---- } ! /* parse codec. */ if ((strstr(buf, ".mp3") != NULL) || (strstr(buf, ".MP3") != NULL)) { ! SAFE_STRDUP(fattr->codec, NJB_CODEC_MP3); } else { p = k_parse_attribute(buf, "codec"); ! if (p) { ! SAFE_STRDUP(fattr->codec, p); kfree(p); ! } else { /* Default to mp3 */ fattr->codec = (char *) kmalloc(strlen(NJB_CODEC_MP3) + 1, *************** *** 876,889 **** *q = '\0'; } ! fattr->title = ! (char *) kmalloc(strlen(p + 3) + 1, GFP_KERNEL); ! strcpy(fattr->title, p + 3); } else { fattr->title = k_parse_attribute(buf, "title"); if (!fattr->title) { ! fattr->title = ! (char *) kmalloc(strlen("<title unknown>") + 1, ! GFP_KERNEL); ! strcpy(fattr->title, "<title unknown>"); } } --- 676,684 ---- *q = '\0'; } ! SAFE_STRDUP(fattr->title, p + 3); } else { fattr->title = k_parse_attribute(buf, "title"); if (!fattr->title) { ! SAFE_STRDUP(fattr->title, UNKNOWN_STRING); } } *************** *** 894,918 **** } fattr->artist = k_parse_attribute(buf, "artist"); ! if (!fattr->artist) { ! fattr->artist = ! (char *) kmalloc(strlen(buf) + 1, GFP_KERNEL); ! strcpy(fattr->artist, buf); ! } /* parse album */ fattr->album = k_parse_attribute(buf, "album"); ! if (!fattr->album) { ! fattr->album = ! (char *) kmalloc(strlen("<unknown>") + 1, GFP_KERNEL); ! strcpy(fattr->album, "<unknown>"); ! } /* parse genre */ fattr->genre = k_parse_attribute(buf, "genre"); ! if (!fattr->genre) { ! fattr->genre = ! (char *) kmalloc(strlen("<unknown>") + 1, GFP_KERNEL); ! strcpy(fattr->genre, "<unknown>"); ! } /* parse length in milliseconds */ --- 689,704 ---- } fattr->artist = k_parse_attribute(buf, "artist"); ! if (!fattr->artist) ! SAFE_STRDUP(fattr->artist, buf); /* parse album */ fattr->album = k_parse_attribute(buf, "album"); ! if (!fattr->album) ! SAFE_STRDUP(fattr->album, UNKNOWN_STRING); /* parse genre */ fattr->genre = k_parse_attribute(buf, "genre"); ! if (!fattr->genre) ! SAFE_STRDUP(fattr->genre, UNKNOWN_STRING); /* parse length in milliseconds */ |
From: Ben O. <ben...@us...> - 2002-02-24 00:24:03
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2575 Modified Files: njbfs_proc.h Log Message: ben: change get_attr, proc_create, add get_dirname Index: njbfs_proc.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_proc.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** njbfs_proc.h 10 Feb 2002 21:59:23 -0000 1.3 --- njbfs_proc.h 24 Feb 2002 00:24:00 -0000 1.4 *************** *** 7,18 **** int njbfs_parse_options(struct njbfs_sb_info *, void *); int njbfs_connect(struct njbfs_sb_info *); ! void njbfs_disconnect(struct njbfs_sb_info *); int njbfs_loaddir(struct njbfs_sb_info *, char *, struct njbfs_directory *); int njbfs_get_name(struct dentry *, char *); inline void njbfs_lock(struct njbfs_sb_info *); inline void njbfs_unlock(struct njbfs_sb_info *); ! int njbfs_get_attr(struct dentry *, struct njbfs_fattr *, ! struct njbfs_sb_info *); struct inode *njbfs_iget(struct super_block *, struct njbfs_fattr *); int njbfs_read(struct dentry *, unsigned long, unsigned long, char *); --- 7,20 ---- int njbfs_parse_options(struct njbfs_sb_info *, void *); int njbfs_connect(struct njbfs_sb_info *); ! int njbfs_disconnect(struct njbfs_sb_info *); int njbfs_loaddir(struct njbfs_sb_info *, char *, struct njbfs_directory *); int njbfs_get_name(struct dentry *, char *); + int njbfs_get_dirname(struct dentry *, char *); inline void njbfs_lock(struct njbfs_sb_info *); inline void njbfs_unlock(struct njbfs_sb_info *); ! struct njbfs_fattr * ! njbfs_get_attr(struct dentry *dentry, struct njbfs_sb_info *info); ! struct inode *njbfs_iget(struct super_block *, struct njbfs_fattr *); int njbfs_read(struct dentry *, unsigned long, unsigned long, char *); *************** *** 22,26 **** struct dentry *, struct inode *, struct dentry *); int njbfs_proc_unlink(struct njbfs_sb_info *, char *); ! int njbfs_proc_create(struct njbfs_sb_info *, char *); int njbfs_write(struct dentry *, unsigned long, unsigned long, char *); --- 24,28 ---- struct dentry *, struct inode *, struct dentry *); int njbfs_proc_unlink(struct njbfs_sb_info *, char *); ! int njbfs_proc_create(struct njbfs_sb_info *, char *, struct njbfs_fattr **); int njbfs_write(struct dentry *, unsigned long, unsigned long, char *); |
From: Ben O. <ben...@us...> - 2002-02-24 00:23:14
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2357 Modified Files: njbfs_cache.h Log Message: ben: support for new directory structure Index: njbfs_cache.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs_cache.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** njbfs_cache.h 10 Feb 2002 21:59:23 -0000 1.4 --- njbfs_cache.h 24 Feb 2002 00:23:12 -0000 1.5 *************** *** 2,7 **** #define _NJBFS_CACHE_H_ ! #define NJBFS_CACHE_LEN 5 ! #define NJBFS_CACHE_HASH 5 #define NJBFS_CACHE_TTL 300 --- 2,7 ---- #define _NJBFS_CACHE_H_ ! #define NJBFS_CACHE_LEN 2048 ! #define NJBFS_CACHE_HASH 2048 #define NJBFS_CACHE_TTL 300 *************** *** 107,110 **** --- 107,158 ---- } datafile_t; + struct njbfs_fattr_list { + struct njbfs_fattr *fattr; + struct njbfs_fattr_list *next; + }; + + struct njbfs_album { + char *name; + struct njbfs_fattr_list *tracks; + struct njbfs_artist *artist; + }; + + struct njbfs_album_list { + struct njbfs_album *album; + struct njbfs_album_list *next; + }; + + + struct njbfs_artist { + char *name; + struct njbfs_fattr_list *tracks; + struct njbfs_album_list *albums; + }; + + struct njbfs_artist_list { + struct njbfs_artist *artist; + struct njbfs_artist_list *next; + }; + + struct njbfs_genre { + char *name; + struct njbfs_fattr_list *tracks; + }; + + struct njbfs_genre_list { + struct njbfs_genre *genre; + struct njbfs_genre_list *next; + }; + + + #define NJBFS_GENERIC_HASH_SIZE 1024 + + typedef struct __njbfs_hash_element { + char *id; + void *data; + struct __njbfs_hash_element *next; + } njbfs_hash_element; + + /* ----------------- NJB file system cache ------------------------ */ *************** *** 119,133 **** unsigned long blocks; time_t atime; ! u_int32_t fileid; /* the NJB file id */ ! /* NJB attributes */ ! char *codec; /* codec frame */ ! char *title; /* title frame */ ! char *artist; /* artist frame */ ! char *album; /* album frame */ ! char *genre; /* genre frame */ ! u_int32_t length; /* optional frame: length in seconds */ ! u_int32_t tracknum; /* optional frame: album track number */ ! track_t *track; /* track */ ! int update_track_tag; /* should track tag be updated? 1=yes 0=no */ }; --- 167,171 ---- unsigned long blocks; time_t atime; ! struct njbfs_fattr *fattr; }; *************** *** 156,164 **** struct njbfs_sb_info; ! void njbfs_cache_init(struct njbfs_sb_info *); ! int njbfs_cache_empty(struct njbfs_sb_info *); ! int njbfs_cache_get(struct njbfs_sb_info *, char *, struct njbfs_directory **); ! void njbfs_cache_invalidate(struct dentry *); #endif --- 194,225 ---- struct njbfs_sb_info; ! /* directory specific caching functions (cache.c) */ ! void njbfs_cache_init(struct njbfs_sb_info *); ! int njbfs_cache_empty(struct njbfs_sb_info *); ! int njbfs_cache_get(struct njbfs_sb_info *, char *, struct njbfs_directory **); ! void njbfs_cache_invalidate(struct dentry *); ! int njbfs_cache_addnode(struct njbfs_sb_info *, char *, ! struct njbfs_dirlist_node *); ! ! int init_fattr_cache(struct njbfs_sb_info *); ! ! /* functions for the outside world to access the track cache */ ! struct njbfs_artist *njbfs_get_artist(char *); ! struct njbfs_album *njbfs_get_album(char *, char *); ! struct njbfs_album_list *njbfs_get_albums(char *); ! struct njbfs_genre *njbfs_get_genre(char *); ! int njbfs_add_fattr(struct njbfs_fattr *); ! void njbfs_remove_fattr(struct njbfs_fattr *); ! struct njbfs_fattr_list *add_fattr_to_list(struct njbfs_fattr_list **, ! struct njbfs_fattr *); ! ! ! /* the linked lists that make up the core of our cache */ ! extern struct njbfs_album_list *album_list_head; ! extern struct njbfs_artist_list *artist_list_head; ! extern struct njbfs_genre_list *genre_list_head; ! extern struct njbfs_fattr_list *track_list_head; ! extern struct njbfs_fattr_list *virtual_list_head; #endif |
From: Ben O. <ben...@us...> - 2002-02-24 00:22:46
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2237 Modified Files: njb_usb.h Log Message: Ben: add prototypes Index: njb_usb.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njb_usb.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** njb_usb.h 23 Dec 2001 20:16:56 -0000 1.3 --- njb_usb.h 24 Feb 2002 00:22:43 -0000 1.4 *************** *** 2,5 **** --- 2,7 ---- #define _NJB_USB_H_ + #include "njbfs.h" + #define LSW(x) (uint16_t)(x) #define MSW(x) (uint16_t)((uint32_t)(x) >> 16) *************** *** 141,143 **** --- 143,174 ---- #define NJB_UNDEFINED_ERR 0xff + extern int njb_usb_capture(struct nomad_usb_data *njb); + extern int njb_usb_release(struct nomad_usb_data *njb); + extern int njb_usb_get_first_track_tag_header(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern int njb_usb_get_next_track_tag_header(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern track_t *njb_usb_get_track_tag(struct nomad_usb_data *njb, + njbttaghdr_t * header); + extern int njb_usb_connect(struct nomad_usb_data *njb); + extern int njb_usb_disconnect(struct nomad_usb_data *njb); + extern int njb_usb_open(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_close(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_write(struct nomad_usb_data *njb, char *name, + u_int32_t offset, u_int32_t count, void *buffer); + extern int njb_usb_read(struct nomad_usb_data *njb, char *name, + u_int32_t offset, u_int32_t count, void *buffer); + extern int njb_usb_rename(struct nomad_usb_data *njb, + struct njbfs_fattr *fattr); + extern int njb_usb_delete(struct nomad_usb_data *njb, char *file); + extern int njb_usb_create(struct nomad_usb_data *njb, char *file); + extern int njb_usb_handshake(struct nomad_usb_data *njb); + extern int njb_usb_get_disk_usage(struct nomad_usb_data *njb, u_int64_t * total, u_int64_t * free); + extern track_t *njb_usb_update_track_tag(struct nomad_usb_data *njb, struct njbfs_fattr *fattr, u_int32_t * trackid); + extern int njb_usb_verify_last_command(struct nomad_usb_data *njb); + extern int njb_usb_update_library_counter(struct nomad_usb_data *njb); + #endif + |
From: Ben O. <ben...@us...> - 2002-02-24 00:22:21
|
Update of /cvsroot/njbfs/njbfs In directory usw-pr-cvs1:/tmp/cvs-serv2122 Modified Files: njbfs.h Log Message: Ben: add njbfs_strdup, support for new directory structure Index: njbfs.h =================================================================== RCS file: /cvsroot/njbfs/njbfs/njbfs.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** njbfs.h 15 Feb 2002 19:26:25 -0000 1.6 --- njbfs.h 24 Feb 2002 00:22:18 -0000 1.7 *************** *** 2,9 **** #define _NJBFS_H_ ! #define NJBFS_VERSION "0.1" ! #define NJBFS_DEBUG 1 #include "njbfs_cache.h" --- 2,33 ---- #define _NJBFS_H_ ! #define NJBFS_VERSION "0.22" #define NJBFS_DEBUG 1 + /* + how would you like your filenames today, sir? + Would you like fries with that? + */ + + #define NJBFS_FILENAME_GENERIC(artist, album, title, tracknum, codec) \ + "%s - %s.%s", artist, title, codec + + #define NJBFS_FILENAME_TRACKSDIR(artist, album, title, tracknum, codec) \ + "%s - %s [%s].%s", artist, title, album, codec + + #define NJBFS_FILENAME_ALBUMDIR(artist, album, title, tracknum, codec) \ + "%02d %s.%s", tracknum, title, codec + + #define NJBFS_FILENAME_MULTIPLEALBUMDIR(artist, album, title, tracknum, codec) \ + "%s - %s.%s", artist, title, codec + + #define NJBFS_FILENAME_ALLTRACKSDIR(artist, album, title, tracknum, codec) \ + "%s - %s.%s", album, title, codec + + #define NJBFS_FILENAME_GENREDIR(artist, album, title, tracknum, codec) \ + "%s - %s - %s.%s", artist, album, title, codec + + /* this defines the name of the "all tracks" directory under an artist */ + #define NJBFS_ALLTRACKS_DIR "__all__" #include "njbfs_cache.h" *************** *** 41,46 **** struct njbfs_dir_cache cache; struct nomad_usb_data *njb; - int virtual_mode; - char virtual_dir[NJBFS_MAXVIRTUALDIRLEN]; }; --- 65,68 ---- *************** *** 52,56 **** gid_t f_gid; kdev_t f_rdev; - off_t f_size; time_t f_atime; time_t f_mtime; --- 74,77 ---- *************** *** 58,64 **** --- 79,87 ---- unsigned long f_blksize; unsigned long f_blocks; + struct inode *inode; u_int32_t fileid; /* file id of the NJB */ /* file name parsing */ u_int32_t size; /* size */ + char *fname; /* o.g. filename */ char *codec; /* codec frame */ char *title; /* title frame */ *************** *** 69,74 **** u_int32_t tracknum; /* optional frame: album track number */ track_t *track; /* track */ ! }; #endif --- 92,105 ---- u_int32_t tracknum; /* optional frame: album track number */ track_t *track; /* track */ ! int update_cache; /* did we change the attributes or do ! something that will require ! a reload? */ }; + + extern char *njbfs_strdup(char *y); + #define SAFE_STRDUP(x, y) if ( !(x=njbfs_strdup(y)) ) return -ENOMEM + #define SAFE_STRDUP_NULL(x, y) if ( !(x=njbfs_strdup(y)) ) return NULL + #define SAFE_STRDUP_ZERO(x, y) if ( !(x=njbfs_strdup(y)) ) return 0 + #endif |