📄 databasefs.c
字号:
} if ( drow->fileqry[0] == '\0' ) { errno = EISDIR; return -1; } /* check if we have the query stored in the cache */ /* we need to break this into a function as it is duplicated above in * opendir */ replace(drow->fileqry, &sstack, filledqry, mydata->sock); cache_entry = (struct cache_node *)ubi_cacheGet(mydata->cache, filledqry); if ( cache_entry == NULL ) { /* couldn't find it in the cache. we have to load it */ songs = (struct song_entry *) cache_load(SONG, filledqry, mydata->sock, mydata->cache); } else { /* found in the cache */ songs = (struct song_entry *) ubi_slFirst((ubi_slListPtr)cache_entry->data); } /* now traverse through songs and find the file */ while ( songs ) { if ( strncmp(songs->fname, leaf, 128) == 0 ) return module_open(songs); songs = (struct song_entry *)ubi_slNext(songs); } errno = ENOENT; return -1;}static int musicdb_close(struct vfs_handle_struct *musicdb_handle, struct files_struct *fsp, int fd){ return module_close(fd);}static ssize_t musicdb_read(struct vfs_handle_struct *musicdb_handle, struct files_struct *fsp, int fd, void *data, size_t n){ return module_read(fd, data, n);}static SMB_OFF_T musicdb_lseek(struct vfs_handle_struct *musicdb_handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence){ return module_lseek(fd, offset, whence);}/************************************************************************** * int musicdb_stat * * Lookup the data for the filename. Need to add caching. * ************************************************************************/static int musicdb_stat(struct vfs_handle_struct *musicdb_handle, struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf){ struct dirtbl_row *drow; struct strstack sstack; char *p, leaf[128], base[512]; struct musicdb_ctx *mydata = (struct musicdb_ctx *)musicdb_handle->data; pstring filequery, dirquery; if ( !strcmp(fname, ".") ) return generic_dir_stat(sbuf); sstack.stackptr = 0; /* split fname into base and leaf */ strncpy(base, fname, 512); if ( (p = strrchr(base, '/')) != NULL ) { strncpy(leaf, p+1, 128); *(p+1) = '\0'; } else { /* is this correct? can we get a stat request for a file with no /? */ strncpy(leaf, base, 128); strncpy(base, "./", 512); } if ( strstr(fname, "desktop.ini") ) // return default_vfs_ops.stat(conn, fname, sbuf); return SMB_VFS_NEXT_STAT(musicdb_handle, conn, fname, sbuf); /* search the base */ if ( !search(1, base, &drow, &sstack, mydata->dtable) ) { errno = ENOTDIR; return -1; } if ( drow->fileqry[0] != '\0' ) { replace(drow->fileqry, &sstack, filequery, mydata->sock); if ( stat_find_file(filequery, leaf, sbuf, conn, musicdb_handle) ) return 0; } if ( drow->dirqry[0] != '\0' ) { replace(drow->dirqry, &sstack, dirquery, mydata->sock); if ( stat_find_dir(dirquery, leaf, sbuf, mydata->sock, conn, musicdb_handle) ) return 0; } if ( drow->subptr > 0 ) { leaf[strlen(leaf)] = '/'; if ( stat_find_sdir(leaf, drow->subptr, sbuf, mydata->dtable) ) return 0; } errno = ENOENT; return -1;}static int stat_find_file(char *query, const char *leaf, SMB_STRUCT_STAT *sbuf, struct connection_struct *conn, struct vfs_handle_struct *musicdb_handle){ struct song_entry *entry; struct cache_node *cache_entry; struct musicdb_ctx *mydata = (struct musicdb_ctx *)musicdb_handle->data; MYSQL *sock = mydata->sock; cache_entry = (struct cache_node *)ubi_cacheGet(mydata->cache, query); if ( cache_entry == NULL ) { /* couldn't find it in the cache. we have to load it. */ entry = (struct song_entry *) cache_load(SONG, query, sock, mydata->cache); } else { /* found it set song_entry */ entry = (struct song_entry *) ubi_slFirst((ubi_slListPtr)cache_entry->data); } while ( entry ) { if ( strcmp(entry->fname, leaf) == 0 ) { /* found it! stat it and return */ memset(sbuf, 0, sizeof(SMB_STRUCT_STAT)); sbuf->st_dev = 770; // ?? sbuf->st_ino = 1; // Fake inode sbuf->st_mode = 0100777; sbuf->st_uid = 0; sbuf->st_gid = 0; sbuf->st_nlink = 1; // number of hard links sbuf->st_blksize = 4096; // Physical block size sbuf->st_blocks = 1; // Number of blocks allocated sbuf->st_atime = 1027382400; sbuf->st_mtime = 1027382400; sbuf->st_ctime = 1027382400; sbuf->st_size = entry->filesize; return 1; } entry = (struct song_entry *)ubi_slNext(entry); } return 0; /* not found */}static int stat_find_dir(const char *query, const char *leaf, SMB_STRUCT_STAT *sbuf, MYSQL *sock, struct connection_struct *conn, struct vfs_handle_struct *musicdb_handle){ struct dir_entry *entry; struct cache_node *cache_entry; struct musicdb_ctx *mydata = (struct musicdb_ctx *)musicdb_handle->data; cache_entry = (struct cache_node *)ubi_cacheGet(mydata->cache, query); if ( cache_entry == NULL ) { /* couldn't find it in the cache. we have to load it. */ entry = (struct dir_entry *) cache_load(DDIR, query, sock, mydata->cache); } else { /* found it set song_entry */ entry = (struct dir_entry *) ubi_slFirst((ubi_slListPtr)cache_entry->data); } while ( entry ) { if ( strncmp(leaf, entry->template, 128) == 0 ) { generic_dir_stat(sbuf); return 1; } entry = (struct dir_entry *)ubi_slNext(entry); } return 0;}static int stat_find_sdir(const char *leaf, int subptr, SMB_STRUCT_STAT *sbuf, struct dirtbl *dtable){ int i = dirtbl_search(subptr, dtable); if ( i == -1 ) return 0; while ( i < dtable->size && dtable->rows[i].dirid == subptr ) { if ( dtable->rows[i].visible == 'F' ) { i++; continue; /* skip */ } if ( strncmp(dtable->rows[i].template, leaf, 128) == 0 ) { generic_dir_stat(sbuf); return 1; } i++; } return 0;}static int musicdb_fstat(struct vfs_handle_struct *musicdb_handle, struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf){ return module_fstat(fd, sbuf);}static BOOL musicdb_lock(struct vfs_handle_struct *musicdb_handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type){ return 0;}static int check_black_list(const char *host, MYSQL *sock){ MYSQL_RES *res; MYSQL_ROW myrow; char SQL[] = "SELECT * FROM blacklist"; if ( MYSQL_QUERY(sock, SQL) ) { DEBUG(1, ("musicdb: failed to load black list table. Blocking ALL\n")); return 1; } res = mysql_store_result(sock); while ( (myrow = mysql_fetch_row(res)) ) { if ( strcasecmp(myrow[0], host) == 0 ) { /* found host name in list */ mysql_free_result(res); return 1; } } mysql_free_result(res); return 0;}/************************************************************************** * int generic_dir_stat * * function for stat which fills in a stat structure for a directory. * returns 0 on success, non-zero otherwise, appropriate for stat * ************************************************************************/static int generic_dir_stat(SMB_STRUCT_STAT *sbuf){ memset(sbuf, 0, sizeof(SMB_STRUCT_STAT)); sbuf->st_dev = 770; // ?? sbuf->st_ino = 1; // Fake inode /* sbuf->st_mode = 042555; */ /* apparently, windows spams for desktop.ini if the directory is marked * read only. Go figure. we'll mark it read-write and deny access later */ sbuf->st_mode = 042777; sbuf->st_uid = 0; sbuf->st_gid = 0; sbuf->st_nlink = 1; // number of hard links sbuf->st_size = 4096; // Actual size in bytes sbuf->st_blksize = 4096; // Physical block size sbuf->st_blocks = 1; // Number of blocks allocated sbuf->st_atime = 1027382400; sbuf->st_mtime = 1027382400; sbuf->st_ctime = 1027382400; return 0;}static vfs_op_tuple musicdb_ops[] = { { SMB_VFS_OP(musicdb_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_closedir), SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_read), SMB_VFS_OP_READ, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_lseek), SMB_VFS_OP_LSEEK, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(musicdb_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE }, { SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP },};NTSTATUS init_module(void){ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "databasefs", musicdb_ops);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -