?? smbfs.c
字號:
filp->flags |= F_MODIFIED;
left -= rc;
p += rc;
if (filp->pos > file->statbuf.quad.size_low) file->statbuf.quad.size_low = filp->pos;
}
return size;
}
int smb_ioctl(struct file *filp, int cmd, void *data, size_t size)
{
return -ENOSYS;
}
loff_t smb_tell(struct file *filp)
{
if (filp->flags & F_DIR) return -EBADF;
return filp->pos;
}
loff_t smb_lseek(struct file *filp, loff_t offset, int origin)
{
struct smb_file *file = (struct smb_file *) filp->data;
if (filp->flags & F_DIR) return -EBADF;
switch (origin)
{
case SEEK_END:
offset += file->statbuf.quad.size_low;
break;
case SEEK_CUR:
offset += filp->pos;
}
if (offset < 0) return -EINVAL;
filp->pos = offset;
return offset;
}
int smb_chsize(struct file *filp, loff_t size)
{
struct smb_share *share = (struct smb_share *) filp->fs->data;
struct smb_file *file = (struct smb_file *) filp->data;
struct smb_set_fileinfo_request req;
struct smb_file_end_of_file_info info;
struct smb_set_fileinfo_response rsp;
int rc;
int rsplen;
memset(&req, 0, sizeof(req));
req.fid = file->fid;
req.infolevel = 0x104;
info.end_of_file = size;
rsplen = sizeof(rsp);
rc = smb_trans(share, TRANS2_SET_FILE_INFORMATION, &req, sizeof(req), &info, sizeof(info), &rsp, &rsplen, NULL, NULL);
if (rc < 0) return rc;
if (filp->pos > size) filp->pos = size;
return 0;
}
int smb_futime(struct file *filp, struct utimbuf *times)
{
struct smb_share *share = (struct smb_share *) filp->fs->data;
struct smb_file *file = (struct smb_file *) filp->data;
struct smb_set_fileinfo_request req;
struct smb_file_basic_info info;
struct smb_set_fileinfo_response rsp;
int rc;
int rsplen;
memset(&req, 0, sizeof(req));
req.fid = file->fid;
req.infolevel = 0x101;
info.creation_time = time2ft(times->ctime == -1 ? file->statbuf.ctime : times->ctime);
info.last_access_time = time2ft(times->atime == -1 ? file->statbuf.atime : times->atime);
info.last_write_time = time2ft(times->mtime == -1 ? file->statbuf.mtime : times->mtime);
info.change_time = time2ft(times->mtime == -1 ? file->statbuf.mtime : times->mtime);
info.attributes = file->attrs;
rsplen = sizeof(rsp);
rc = smb_trans(share, TRANS2_SET_FILE_INFORMATION, &req, sizeof(req), &info, sizeof(info), &rsp, &rsplen, NULL, NULL);
if (rc < 0) return rc;
if (times->ctime != -1) file->statbuf.ctime = times->ctime;
if (times->mtime != -1) file->statbuf.mtime = times->mtime;
if (times->atime != -1) file->statbuf.atime = times->atime;
return 0;
}
int smb_utime(struct fs *fs, char *name, struct utimbuf *times)
{
struct file filp;
int rc;
memset(&filp, 0, sizeof(struct file));
filp.fs = fs;
rc = smb_open(&filp, name);
if (rc < 0) return rc;
rc = smb_futime(&filp, times);
smb_close(&filp);
return rc;
}
int smb_fstat(struct file *filp, struct stat *buffer)
{
struct smb_file *file = (struct smb_file *) filp->data;
if (filp->flags & F_DIR) return -EBADF;
if (buffer) memcpy(buffer, &file->statbuf, sizeof(struct stat));
return file->statbuf.quad.size_low;
}
int smb_stat(struct fs *fs, char *name, struct stat *buffer)
{
struct smb_share *share = (struct smb_share *) fs->data;
struct smb_pathinfo_request req;
struct smb_file_basic_info rspb;
struct smb_file_standard_info rsps;
struct smb_dentry *dentry;
int rsplen;
short dummy;
int dummylen;
int rc;
rc = smb_convert_filename(name);
if (rc < 0) return rc;
// Handle root mount point
if (!*name)
{
if (buffer)
{
memset(buffer, 0, sizeof(struct stat));
buffer->atime = time(0);
buffer->ctime = share->mounttime;
buffer->mtime = share->mounttime;
buffer->mode = FS_DIRECTORY;
buffer->nlink = 1;
return 0;
}
}
// Look in cache
dentry = smb_find_in_cache(share, name);
if (dentry != NULL)
{
if (buffer) memcpy(buffer, &dentry->statbuf, sizeof(struct stat));
return dentry->statbuf.quad.size_low;
}
// Query server for file information
if (buffer)
{
req.infolevel = SMB_QUERY_FILE_BASIC_INFO;
req.reserved = 0;
strcpy(req.filename, name);
rsplen = sizeof(rspb);
dummylen = sizeof(dummy);
rc = smb_trans(share, TRANS2_QUERY_PATH_INFORMATION, &req, sizeof(req) - MAXPATH + strlen(name) + 1, NULL, 0, &dummy, &dummylen, &rspb, &rsplen);
if (rc < 0) return rc;
}
req.infolevel = SMB_QUERY_FILE_STANDARD_INFO;
req.reserved = 0;
strcpy(req.filename, name);
rsplen = sizeof(rsps);
dummylen = sizeof(dummy);
rc = smb_trans(share, TRANS2_QUERY_PATH_INFORMATION, &req, sizeof(req) - MAXPATH + strlen(name) + 1, NULL, 0, &dummy, &dummylen, &rsps, &rsplen);
if (rc < 0) return rc;
if (buffer)
{
buffer->mode = 0;
buffer->ino = 0;
buffer->nlink = rsps.number_of_links;
buffer->devno = NODEV;
buffer->atime = ft2time(rspb.last_access_time);
buffer->mtime = ft2time(rspb.last_write_time);
buffer->ctime = ft2time(rspb.creation_time);
buffer->size = rsps.end_of_file;
if (rspb.attributes & SMB_FILE_ATTR_DIRECTORY) buffer->mode |= FS_DIRECTORY;
}
return (int) rsps.end_of_file;
}
int smb_mkdir(struct fs *fs, char *name)
{
struct smb_share *share = (struct smb_share *) fs->data;
struct smb *smb;
char namebuf[MAXPATH + 1 + 1];
char *p;
int rc;
rc = smb_convert_filename(name);
if (rc < 0) return rc;
// Make directory
smb = smb_init(share, 0);
p = namebuf;
*p++ = 4;
p = addstrz(p, name);
rc = smb_request(share, smb, SMB_COM_CREATE_DIRECTORY, 0, namebuf, p - namebuf, 1);
if (rc < 0) return rc;
return 0;
}
int smb_rmdir(struct fs *fs, char *name)
{
struct smb_share *share = (struct smb_share *) fs->data;
struct smb *smb;
char namebuf[MAXPATH + 1 + 1];
char *p;
int rc;
rc = smb_convert_filename(name);
if (rc < 0) return rc;
// Delete directory
smb = smb_init(share, 0);
p = namebuf;
*p++ = 4;
p = addstrz(p, name);
rc = smb_request(share, smb, SMB_COM_DELETE_DIRECTORY, 0, namebuf, p - namebuf, 1);
if (rc < 0) return rc;
return 0;
}
int smb_rename(struct fs *fs, char *oldname, char *newname)
{
struct smb_share *share = (struct smb_share *) fs->data;
struct smb *smb;
char namebuf[(MAXPATH + 1 + 1) * 2];
char *p;
int rc;
rc = smb_convert_filename(oldname);
if (rc < 0) return rc;
rc = smb_convert_filename(newname);
if (rc < 0) return rc;
// Rename file
smb = smb_init(share, 0);
p = namebuf;
*p++ = 4;
p = addstrz(p, oldname);
*p++ = 4;
p = addstrz(p, newname);
rc = smb_request(share, smb, SMB_COM_RENAME, 1, namebuf, p - namebuf, 1);
if (rc < 0) return rc;
return 0;
}
int smb_link(struct fs *fs, char *oldname, char *newname)
{
return -ENOSYS;
}
int smb_unlink(struct fs *fs, char *name)
{
struct smb_share *share = (struct smb_share *) fs->data;
struct smb *smb;
char namebuf[MAXPATH + 1 + 1];
char *p;
int rc;
rc = smb_convert_filename(name);
if (rc < 0) return rc;
// Delete file
smb = smb_init(share, 0);
p = namebuf;
*p++ = 4;
p = addstrz(p, name);
rc = smb_request(share, smb, SMB_COM_DELETE, 1, namebuf, p - namebuf, 1);
if (rc < 0) return rc;
return 0;
}
int smb_opendir(struct file *filp, char *name)
{
struct smb_share *share = (struct smb_share *) filp->fs->data;
struct smb_findfirst_request req;
struct smb_findfirst_response rsp;
struct smb_directory *dir;
int rsplen;
int buflen;
int rc;
rc = smb_convert_filename(name);
if (rc < 0) return rc;
dir = (struct smb_directory *) kmalloc(sizeof(struct smb_directory));
if (!dir) return -ENOMEM;
memset(&req, 0, sizeof(req));
req.search_attributes = SMB_FILE_ATTR_SYSTEM | SMB_FILE_ATTR_HIDDEN | SMB_FILE_ATTR_DIRECTORY;
req.flags = SMB_CLOSE_IF_END;
req.infolevel = 0x101;
req.search_count = 512;
strcpy(req.filename, name);
if (*name) strcat(req.filename, "\\*");
rsplen = sizeof(rsp);
buflen = SMB_DIRBUF_SIZE;
rc = smb_trans(share, TRANS2_FIND_FIRST2, &req, 12 + strlen(req.filename) + 1, NULL, 0, &rsp, &rsplen, dir->buffer, &buflen);
if (rc < 0)
{
kfree(dir);
return rc;
}
dir->sid = rsp.sid;
dir->eos = rsp.end_of_search;
dir->entries_left = rsp.search_count;
dir->fi = (struct smb_file_directory_info *) dir->buffer;
strcpy(dir->path, name);
filp->data = dir;
return 0;
}
int smb_readdir(struct file *filp, struct dirent *dirp, int count)
{
struct smb_share *share = (struct smb_share *) filp->fs->data;
struct smb_directory *dir = (struct smb_directory *) filp->data;
struct stat statbuf;
if (count != 1) return -1;
again:
if (dir->entries_left == 0)
{
struct smb_findnext_request req;
struct smb_findnext_response rsp;
int rsplen;
int buflen;
int rc;
if (dir->eos) return 0;
memset(&req, 0, sizeof(req));
req.sid = dir->sid;
req.flags = SMB_CONTINUE_BIT | SMB_CLOSE_IF_END;
req.infolevel = 0x101;
req.search_count = 512;
rsplen = sizeof(rsp);
buflen = SMB_DIRBUF_SIZE;
rc = smb_trans(share, TRANS2_FIND_NEXT2, &req, sizeof(req), NULL, 0, &rsp, &rsplen, dir->buffer, &buflen);
if (rc < 0) return rc;
dir->eos = rsp.end_of_search;
dir->entries_left = rsp.search_count;
dir->fi = (struct smb_file_directory_info *) dir->buffer;
if (dir->entries_left == 0) return 0;
}
if (dir->fi->filename[0] == '.' && (dir->fi->filename[1] == 0 || (dir->fi->filename[1] == '.' && dir->fi->filename[2] == 0)))
{
dir->entries_left--;
dir->fi = (struct smb_file_directory_info *) ((char *) dir->fi + dir->fi->next_entry_offset);
goto again;
}
memset(&statbuf, 0, sizeof(struct stat));
statbuf.nlink = 1;
statbuf.ctime = ft2time(dir->fi->creation_time);
statbuf.mtime = ft2time(dir->fi->last_write_time);
statbuf.atime = ft2time(dir->fi->last_access_time);
statbuf.size = dir->fi->end_of_file;
if (dir->fi->ext_file_attributes & SMB_FILE_ATTR_DIRECTORY) statbuf.mode |= FS_DIRECTORY;
smb_add_to_cache(share, dir->path, dir->fi->filename, &statbuf);
dirp->ino = 0;
dirp->namelen = strlen(dir->fi->filename);
dirp->reclen = sizeof(struct dirent) - MAXPATH + dirp->namelen + 1;
strcpy(dirp->name, dir->fi->filename);
dir->entries_left--;
dir->fi = (struct smb_file_directory_info *) ((char *) dir->fi + dir->fi->next_entry_offset);
return 1;
}
struct fsops smbfsops =
{
0,
smb_lockfs,
smb_unlockfs,
smb_format,
smb_mount,
smb_umount,
smb_statfs,
smb_open,
smb_close,
smb_flush,
smb_read,
smb_write,
smb_ioctl,
smb_tell,
smb_lseek,
smb_chsize,
smb_futime,
smb_utime,
smb_fstat,
smb_stat,
smb_mkdir,
smb_rmdir,
smb_rename,
smb_link,
smb_unlink,
smb_opendir,
smb_readdir
};
void init_smbfs()
{
register_filesystem("smbfs", &smbfsops);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -