/** * sysfs_create_dir - create a directory for an object. * @kobj: object we're creating directory for. */ int sysfs_create_dir( struct kobject * kobj ) { struct sysfs_dirent *parent; BUG_ON(!kobj); if (kobj->parent) parent = kobj->parent->sd; else parent = sysfs_root; //printk(KERN_WARNING "%s creating dir %s/%s\n", __FUNCTION__,parent->name,kobject_name(kobj)); kobj->sd = kfs_mkdirent( parent, kobject_name(kobj), NULL, &kfs_default_fops, 0777 | S_IFDIR, NULL, 0 ); return (kobj->sd == NULL); }
struct inode * kfs_create(const char * full_filename, const struct inode_operations * iops, const struct kfs_fops * fops, unsigned mode, void * priv, size_t priv_len) { struct inode *dir; const char *filename = strrchr( full_filename, '/' ); dbg("name=`%s`\n",full_filename); if( !filename ) { printk( "%s: Non-absolute path name! '%s'\n", __func__, full_filename ); return NULL; } filename++; dir = kfs_lookup( kfs_root, full_filename, 0777 ); if( !dir ) return NULL; // Create the file entry in the directory return kfs_mkdirent(dir, filename, iops, fops, mode, priv, priv_len); }
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr) { BUG_ON(!kobj || !kobj->sd || !attr); struct sysfs_buffer *buffer; struct inode *inode; /* TODO: Actually implement this! */ //printk(KERN_WARNING "%s creating %s %s\n", __FUNCTION__,kobject_name(kobj), attr->name); buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if(NULL == buffer) return -1; buffer->kobj = kobj; if (buffer->kobj->ktype && buffer->kobj->ktype->sysfs_ops) { buffer->ops = buffer->kobj->ktype->sysfs_ops; } else { WARN(1, KERN_ERR "missing sysfs attribute operations for " "kobject: %s\n", kobject_name(kobj)); } buffer->attr = (struct attribute *) attr; inode = kfs_mkdirent( kobj->sd, attr->name, NULL, &sysfs_file_operations, attr->mode & ~S_IFMT, // should be 0444 as we don't support writes.. buffer, sizeof(struct sysfs_buffer) ); if(NULL == inode) { kfree(buffer); return -1; } /* TODO: silently forgetting this inode is not cool; we will have to destroy it, eventually (or will we do this recursively by destroyxing the parent inode?) ... */ return 0; return (0); }
struct inode * kfs_create_at(struct inode * root_inode, const char * full_filename, const struct inode_operations * iops, const struct kfs_fops * fops, unsigned mode, void * priv, size_t priv_len) { struct inode *dir; const char * filename = strrchr( full_filename, '/' ); BUG_ON(!root_inode); if ( full_filename[0] == '/' ) { root_inode = kfs_root; } dbg("name=`%s`\n", full_filename); if( !filename ) { //printk( "%s: Non-absolute path name! '%s'\n", // __func__, full_filename ); //return NULL; root_inode = kfs_root; }else{ filename++; } dir = kfs_lookup( root_inode, full_filename, 0777 ); if( !dir ) return NULL; // Create the file entry in the directory return kfs_mkdirent(dir, filename, iops, fops, mode, priv, priv_len); }
struct inode * kfs_lookup(struct inode * root, const char * dirname, unsigned create_mode) { dbg("name=`%s`\n", dirname ); // Special case -- use the root if root is null. if( !root ) root = kfs_root; while(1) { /* resolve possible link */ if( root->link_target ) root = root->link_target; // Trim any leading / characters while( *dirname && *dirname == '/' ) dirname++; // Special case -- if the file is empty, return the root if( *dirname == '\0' ) return root; // Find the next slash in the directory name char * next_slash = strchr( dirname, '/' ); // If there is no next slash and we're in create mode, // then we have reached the end of the lookup and we // return a pointer to the directory that will contain // the file once the caller creates it. if( !next_slash && create_mode ) return root; // If we have a mount point descend into its lookup routine if( root->i_op && root->i_op->lookup ) return (struct inode *) root->i_op->lookup( root, (struct dentry*) dirname, (struct nameidata*) (unsigned long) create_mode ); /* current entry is not a directory, so we can't search any further */ if( !S_ISDIR(root->mode) ) return NULL; // Search for the next / char struct inode *child = htable_lookup(root->files, dirname); // If it does not exist and we're not auto-creating // then return no match if( !child && !create_mode ) return NULL; // If it does not exist, but we are auto-creating, // create a subdirectory entry for this position with // the default operations. if( !child ) child = kfs_mkdirent(root, dirname, NULL, &kfs_default_fops, (create_mode & ~S_IFMT) | S_IFDIR, 0, 0); // If we do not have another component to search, // we return the found child if( !next_slash ) return child; // Move to the next component of the directory dirname = next_slash + 1; root = child; } }
int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { BUG_ON(!kobj || !kobj->sd); struct inode *dir_sd; int error = 0, i; struct attribute *const* attr; struct sysfs_buffer *buffer; struct inode *inode; if (grp->name) { dir_sd = kfs_mkdirent( kobj->sd, grp->name, NULL, &kfs_default_fops, 0777 | S_IFDIR, NULL, 0 ); if (error) return error; } else dir_sd = kobj->sd; for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { mode_t mode = 0; if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) continue; } buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if(NULL == buffer) { error = -1; break; } buffer->kobj = kobj; if (buffer->kobj->ktype && buffer->kobj->ktype->sysfs_ops) { buffer->ops = buffer->kobj->ktype->sysfs_ops; } else { WARN(1,KERN_ERR "missing sysfs attribute operations for" "kobject: %s\n", kobject_name(kobj)); } buffer->attr = (struct attribute *) (*attr); inode = kfs_mkdirent( dir_sd, (*attr)->name, NULL, &sysfs_file_operations, ((*attr)->mode | mode) & ~S_IFMT, buffer, sizeof(struct sysfs_buffer) ); if(NULL == inode) { kfree(buffer); error = -1; break; } error = 0; } return error; }