⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 base.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 5 页
字号:
    namelen = strlen (name);    if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen,					       &leaf_pos) ) == NULL )    {	printk ("%s: prepare_leaf(%s): could not create parent path\n",		DEVFS_NAME, name);	return NULL;    }    if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) )	 == NULL )    {	printk ("%s: prepare_leaf(%s): could not allocate entry\n",		DEVFS_NAME, name);	devfs_put (*dir);	return NULL;    }    return de;}   /*  End Function _devfs_prepare_leaf  */static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,					const char *name, int namelen,					int traverse_symlink){    int next_pos = 0;    if (dir == NULL) dir = _devfs_get_root_entry ();    if (dir == NULL) return NULL;    devfs_get (dir);    for (; namelen > 0; name += next_pos, namelen -= next_pos)    {	struct devfs_entry *de, *link;	if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL )	{	    devfs_put (dir);	    return NULL;	}	if (S_ISLNK (de->mode) && traverse_symlink)	{   /*  Need to follow the link: this is a stack chomper  */	    link = _devfs_walk_path (dir, de->u.symlink.linkname,				     de->u.symlink.length, TRUE);	    devfs_put (de);	    if (!link)	    {		devfs_put (dir);		return NULL;	    }	    de = link;	}	devfs_put (dir);	dir = de;	if (name[next_pos] == '/') ++next_pos;    }    return dir;}   /*  End Function _devfs_walk_path  *//** *	find_by_dev - Find a devfs entry in a directory. *	@dir: The directory where to search *	@major: The major number to search for. *	@minor: The minor number to search for. *	@type: The type of special file to search for. This may be either *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK. * *	Returns the devfs_entry pointer on success, else %NULL. An implicit *	devfs_get() is performed. */static struct devfs_entry *find_by_dev (struct devfs_entry *dir,					unsigned int major, unsigned int minor,					char type){    struct devfs_entry *entry, *de;    devfs_get (dir);    if (dir == NULL) return NULL;    if ( !S_ISDIR (dir->mode) )    {	printk ("%s: find_by_dev(): not a directory\n", DEVFS_NAME);	devfs_put (dir);	return NULL;    }    /*  First search files in this directory  */    read_lock (&dir->u.dir.lock);    for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)    {	if ( !S_ISCHR (entry->mode) && !S_ISBLK (entry->mode) ) continue;	if ( S_ISCHR (entry->mode) && (type != DEVFS_SPECIAL_CHR) ) continue;	if ( S_ISBLK (entry->mode) && (type != DEVFS_SPECIAL_BLK) ) continue;	if ( (entry->u.fcb.u.device.major == major) &&	     (entry->u.fcb.u.device.minor == minor) )	{	    devfs_get (entry);	    read_unlock (&dir->u.dir.lock);	    devfs_put (dir);	    return entry;	}	/*  Not found: try the next one  */    }    /*  Now recursively search the subdirectories: this is a stack chomper  */    for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)    {	if ( !S_ISDIR (entry->mode) ) continue;	de = find_by_dev (entry, major, minor, type);	if (de)	{	    read_unlock (&dir->u.dir.lock);	    devfs_put (dir);	    return de;	}    }    read_unlock (&dir->u.dir.lock);    devfs_put (dir);    return NULL;}   /*  End Function find_by_dev  *//** *	find_entry - Find a devfs entry. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		name is relative to the root of the devfs. *	@name: The name of the entry. This may be %NULL. *	@major: The major number. This is used if lookup by @name fails. *	@minor: The minor number. This is used if lookup by @name fails. *		NOTE: If @major and @minor are both 0, searching by major and minor *		numbers is disabled. *	@type: The type of special file to search for. This may be either *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK. *	@traverse_symlink: If %TRUE then symbolic links are traversed. * *	Returns the devfs_entry pointer on success, else %NULL. An implicit *	devfs_get() is performed. */static struct devfs_entry *find_entry (devfs_handle_t dir, const char *name,				       unsigned int major, unsigned int minor,				       char type, int traverse_symlink){    struct devfs_entry *entry;    if (name != NULL)    {	unsigned int namelen = strlen (name);	if (name[0] == '/')	{	    /*  Skip leading pathname component  */	    if (namelen < 2)	    {		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);		return NULL;	    }	    for (++name, --namelen; (*name != '/') && (namelen > 0);		 ++name, --namelen);	    if (namelen < 2)	    {		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);		return NULL;	    }	    ++name;	    --namelen;	}	entry = _devfs_walk_path (dir, name, namelen, traverse_symlink);	if (entry != NULL) return entry;    }    /*  Have to search by major and minor: slow  */    if ( (major == 0) && (minor == 0) ) return NULL;    return find_by_dev (root_entry, major, minor, type);}   /*  End Function find_entry  */static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode){    if (inode == NULL) return NULL;    return inode->u.generic_ip;}   /*  End Function get_devfs_entry_from_vfs_inode  *//** *	free_dentry - Free the dentry for a device entry and invalidate inode. *	@de: The entry. * *	This must only be called after the entry has been unhooked from it's *	 parent directory. */static void free_dentry (struct devfs_entry *de){    struct dentry *dentry = de->inode.dentry;    if (!dentry) return;    spin_lock (&dcache_lock);    dget_locked (dentry);    spin_unlock (&dcache_lock);    /*  Forcefully remove the inode  */    if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;    d_drop (dentry);    dput (dentry);}   /*  End Function free_dentry  *//** *	is_devfsd_or_child - Test if the current process is devfsd or one of its children. *	@fs_info: The filesystem information. * *	Returns %TRUE if devfsd or child, else %FALSE. */static int is_devfsd_or_child (struct fs_info *fs_info){    struct task_struct *p;    if (current == fs_info->devfsd_task) return (TRUE);    if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)    for (p = current->p_opptr; p != &init_task; p = p->p_opptr)    {	if (p == fs_info->devfsd_task) return (TRUE);    }#endif    return (FALSE);}   /*  End Function is_devfsd_or_child  *//** *	devfsd_queue_empty - Test if devfsd has work pending in its event queue. *	@fs_info: The filesystem information. * *	Returns %TRUE if the queue is empty, else %FALSE. */static inline int devfsd_queue_empty (struct fs_info *fs_info){    return (fs_info->devfsd_last_event) ? FALSE : TRUE;}   /*  End Function devfsd_queue_empty  *//** *	wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue. *	@fs_info: The filesystem information. * *	Returns %TRUE if no more waiting will be required, else %FALSE. */static int wait_for_devfsd_finished (struct fs_info *fs_info){    DECLARE_WAITQUEUE (wait, current);    if (fs_info->devfsd_task == NULL) return (TRUE);    if (devfsd_queue_empty (fs_info) && fs_info->devfsd_sleeping) return TRUE;    if ( is_devfsd_or_child (fs_info) ) return (FALSE);    add_wait_queue (&fs_info->revalidate_wait_queue, &wait);    current->state = TASK_UNINTERRUPTIBLE;    if (!devfsd_queue_empty (fs_info) || !fs_info->devfsd_sleeping)	if (fs_info->devfsd_task) schedule ();    remove_wait_queue (&fs_info->revalidate_wait_queue, &wait);    current->state = TASK_RUNNING;    return (TRUE);}   /*  End Function wait_for_devfsd_finished  *//** *	devfsd_notify_de - Notify the devfsd daemon of a change. *	@de: The devfs entry that has changed. This and all parent entries will *            have their reference counts incremented if the event was queued. *	@type: The type of change. *	@mode: The mode of the entry. *	@uid: The user ID. *	@gid: The group ID. *	@fs_info: The filesystem info. * *	Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. */static int devfsd_notify_de (struct devfs_entry *de,			     unsigned short type, umode_t mode,			     uid_t uid, gid_t gid, struct fs_info *fs_info,			     int atomic){    struct devfsd_buf_entry *entry;    struct devfs_entry *curr;    if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE);    if ( ( entry = kmem_cache_alloc (devfsd_buf_cache,				     atomic ? SLAB_ATOMIC : SLAB_KERNEL) )	 == NULL )    {	atomic_inc (&fs_info->devfsd_overrun_count);	return (FALSE);    }    for (curr = de; curr != NULL; curr = curr->parent) devfs_get (curr);    entry->de = de;    entry->type = type;    entry->mode = mode;    entry->uid = uid;    entry->gid = gid;    entry->next = NULL;    spin_lock (&fs_info->devfsd_buffer_lock);    if (!fs_info->devfsd_first_event) fs_info->devfsd_first_event = entry;    if (fs_info->devfsd_last_event) fs_info->devfsd_last_event->next = entry;    fs_info->devfsd_last_event = entry;    spin_unlock (&fs_info->devfsd_buffer_lock);    wake_up_interruptible (&fs_info->devfsd_wait_queue);    return (TRUE);}   /*  End Function devfsd_notify_de  *//** *	devfsd_notify - Notify the devfsd daemon of a change. *	@de: The devfs entry that has changed. *	@type: The type of change event. *	@wait: If TRUE, the function waits for the daemon to finish processing *		the event. */static void devfsd_notify (struct devfs_entry *de,unsigned short type,int wait){    if (devfsd_notify_de (de, type, de->mode, current->euid,			  current->egid, &fs_info, 0) && wait)	wait_for_devfsd_finished (&fs_info);}   /*  End Function devfsd_notify  *//** *	devfs_register - Register a device entry. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		new name is relative to the root of the devfs. *	@name: The name of the entry. *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*). *	@major: The major number. Not needed for regular files. *	@minor: The minor number. Not needed for regular files. *	@mode: The default file mode. *	@ops: The &file_operations or &block_device_operations structure. *		This must not be externally deallocated. *	@info: An arbitrary pointer which will be written to the @private_data *		field of the &file structure passed to the device driver. You can set *		this to whatever you like, and change it once the file is opened (the next *		file opened will not see this change). * *	Returns a handle which may later be used in a call to devfs_unregister(). *	On failure %NULL is returned. */devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,			       unsigned int flags,			       unsigned int major, unsigned int minor,			       umode_t mode, void *ops, void *info){    char devtype = S_ISCHR (mode) ? DEVFS_SPECIAL_CHR : DEVFS_SPECIAL_BLK;    int err;    kdev_t devnum = NODEV;    struct devfs_entry *de;    if (name == NULL)    {	printk ("%s: devfs_register(): NULL name pointer\n", DEVFS_NAME);	return NULL;    }    if (ops == NULL)    {	if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);	if (ops == NULL)	{	    printk ("%s: devfs_register(%s): NULL ops pointer\n",		    DEVFS_NAME, name);	    return NULL;	}	printk ("%s: devfs_register(%s): NULL ops, got %p from major table\n",		DEVFS_NAME, name, ops);    }    if ( S_ISDIR (mode) )    {	printk("%s: devfs_register(%s): creating directories is not allowed\n",	       DEVFS_NAME, name);	return NULL;    }    if ( S_ISLNK (mode) )    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -