aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/smbfs/Kconfig56
-rw-r--r--drivers/staging/smbfs/Makefile18
-rw-r--r--drivers/staging/smbfs/TODO8
-rw-r--r--drivers/staging/smbfs/cache.c208
-rw-r--r--drivers/staging/smbfs/dir.c699
-rw-r--r--drivers/staging/smbfs/file.c456
-rw-r--r--drivers/staging/smbfs/getopt.c64
-rw-r--r--drivers/staging/smbfs/getopt.h14
-rw-r--r--drivers/staging/smbfs/inode.c854
-rw-r--r--drivers/staging/smbfs/ioctl.c68
-rw-r--r--drivers/staging/smbfs/proc.c3502
-rw-r--r--drivers/staging/smbfs/proto.h89
-rw-r--r--drivers/staging/smbfs/request.c817
-rw-r--r--drivers/staging/smbfs/request.h70
-rw-r--r--drivers/staging/smbfs/smb.h118
-rw-r--r--drivers/staging/smbfs/smb_debug.h34
-rw-r--r--drivers/staging/smbfs/smb_fs.h153
-rw-r--r--drivers/staging/smbfs/smb_fs_i.h37
-rw-r--r--drivers/staging/smbfs/smb_fs_sb.h100
-rw-r--r--drivers/staging/smbfs/smb_mount.h65
-rw-r--r--drivers/staging/smbfs/smbfs.txt8
-rw-r--r--drivers/staging/smbfs/smbiod.c343
-rw-r--r--drivers/staging/smbfs/smbno.h363
-rw-r--r--drivers/staging/smbfs/sock.c385
-rw-r--r--drivers/staging/smbfs/symlink.c67
27 files changed, 0 insertions, 8599 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 8bcc153310c..b80755da539 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -149,8 +149,6 @@ source "drivers/staging/msm/Kconfig"
149 149
150source "drivers/staging/lirc/Kconfig" 150source "drivers/staging/lirc/Kconfig"
151 151
152source "drivers/staging/smbfs/Kconfig"
153
154source "drivers/staging/easycap/Kconfig" 152source "drivers/staging/easycap/Kconfig"
155 153
156source "drivers/staging/solo6x10/Kconfig" 154source "drivers/staging/solo6x10/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 0919a423398..fd26509e5ef 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_POHMELFS) += pohmelfs/
34obj-$(CONFIG_IDE_PHISON) += phison/ 34obj-$(CONFIG_IDE_PHISON) += phison/
35obj-$(CONFIG_LINE6_USB) += line6/ 35obj-$(CONFIG_LINE6_USB) += line6/
36obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/ 36obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
37obj-$(CONFIG_SMB_FS) += smbfs/
38obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ 37obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
39obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ 38obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
40obj-$(CONFIG_VT6655) += vt6655/ 39obj-$(CONFIG_VT6655) += vt6655/
diff --git a/drivers/staging/smbfs/Kconfig b/drivers/staging/smbfs/Kconfig
deleted file mode 100644
index 2bc24a8c403..00000000000
--- a/drivers/staging/smbfs/Kconfig
+++ /dev/null
@@ -1,56 +0,0 @@
1config SMB_FS
2 tristate "SMB file system support (OBSOLETE, please use CIFS)"
3 depends on BKL # probably unfixable
4 depends on INET
5 select NLS
6 help
7 SMB (Server Message Block) is the protocol Windows for Workgroups
8 (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
9 files and printers over local networks. Saying Y here allows you to
10 mount their file systems (often called "shares" in this context) and
11 access them just like any other Unix directory. Currently, this
12 works only if the Windows machines use TCP/IP as the underlying
13 transport protocol, and not NetBEUI. For details, read
14 <file:Documentation/filesystems/smbfs.txt> and the SMB-HOWTO,
15 available from <http://www.tldp.org/docs.html#howto>.
16
17 Note: if you just want your box to act as an SMB *server* and make
18 files and printing services available to Windows clients (which need
19 to have a TCP/IP stack), you don't need to say Y here; you can use
20 the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
21 for that.
22
23 General information about how to connect Linux, Windows machines and
24 Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
25
26 To compile the SMB support as a module, choose M here:
27 the module will be called smbfs. Most people say N, however.
28
29config SMB_NLS_DEFAULT
30 bool "Use a default NLS"
31 depends on SMB_FS
32 help
33 Enabling this will make smbfs use nls translations by default. You
34 need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls
35 settings and you need to give the default nls for the SMB server as
36 CONFIG_SMB_NLS_REMOTE.
37
38 The nls settings can be changed at mount time, if your smbmount
39 supports that, using the codepage and iocharset parameters.
40
41 smbmount from samba 2.2.0 or later supports this.
42
43config SMB_NLS_REMOTE
44 string "Default Remote NLS Option"
45 depends on SMB_NLS_DEFAULT
46 default "cp437"
47 help
48 This setting allows you to specify a default value for which
49 codepage the server uses. If this field is left blank no
50 translations will be done by default. The local codepage/charset
51 default to CONFIG_NLS_DEFAULT.
52
53 The nls settings can be changed at mount time, if your smbmount
54 supports that, using the codepage and iocharset parameters.
55
56 smbmount from samba 2.2.0 or later supports this.
diff --git a/drivers/staging/smbfs/Makefile b/drivers/staging/smbfs/Makefile
deleted file mode 100644
index d2a92c5cb11..00000000000
--- a/drivers/staging/smbfs/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
1#
2# Makefile for the linux smb-filesystem routines.
3#
4
5obj-$(CONFIG_SMB_FS) += smbfs.o
6
7smbfs-y := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \
8 symlink.o smbiod.o request.o
9
10# If you want debugging output, you may add these flags to the EXTRA_CFLAGS
11# SMBFS_PARANOIA should normally be enabled.
12
13ccflags-y := -DSMBFS_PARANOIA
14#ccflags-y += -DSMBFS_DEBUG
15#ccflags-y += -DSMBFS_DEBUG_VERBOSE
16#ccflags-y += -DDEBUG_SMB_TIMESTAMP
17#ccflags-y += -Werror
18
diff --git a/drivers/staging/smbfs/TODO b/drivers/staging/smbfs/TODO
deleted file mode 100644
index 24f4d29d53a..00000000000
--- a/drivers/staging/smbfs/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
1smbfs is on its way out of the kernel, it has been replaced
2by cifs several years ago.
3
4The smbfs code uses the big kernel lock which
5is getting deprecated.
6
7Users that find smbfs to work but not cifs should contact
8the CIFS developers on linux-cifs@vger.kernel.org.
diff --git a/drivers/staging/smbfs/cache.c b/drivers/staging/smbfs/cache.c
deleted file mode 100644
index f2a1323ca82..00000000000
--- a/drivers/staging/smbfs/cache.c
+++ /dev/null
@@ -1,208 +0,0 @@
1/*
2 * cache.c
3 *
4 * Copyright (C) 1997 by Bill Hawes
5 *
6 * Routines to support directory cacheing using the page cache.
7 * This cache code is almost directly taken from ncpfs.
8 *
9 * Please add a note about your changes to smbfs in the ChangeLog file.
10 */
11
12#include <linux/time.h>
13#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/pagemap.h>
17#include <linux/net.h>
18
19#include <asm/page.h>
20
21#include "smb_fs.h"
22#include "smb_debug.h"
23#include "proto.h"
24
25/*
26 * Force the next attempt to use the cache to be a timeout.
27 * If we can't find the page that's fine, it will cause a refresh.
28 */
29void
30smb_invalid_dir_cache(struct inode * dir)
31{
32 struct smb_sb_info *server = server_from_inode(dir);
33 union smb_dir_cache *cache = NULL;
34 struct page *page = NULL;
35
36 page = grab_cache_page(&dir->i_data, 0);
37 if (!page)
38 goto out;
39
40 if (!PageUptodate(page))
41 goto out_unlock;
42
43 cache = kmap(page);
44 cache->head.time = jiffies - SMB_MAX_AGE(server);
45
46 kunmap(page);
47 SetPageUptodate(page);
48out_unlock:
49 unlock_page(page);
50 page_cache_release(page);
51out:
52 return;
53}
54
55/*
56 * Mark all dentries for 'parent' as invalid, forcing them to be re-read
57 */
58void
59smb_invalidate_dircache_entries(struct dentry *parent)
60{
61 struct smb_sb_info *server = server_from_dentry(parent);
62 struct list_head *next;
63 struct dentry *dentry;
64
65 spin_lock(&parent->d_lock);
66 next = parent->d_subdirs.next;
67 while (next != &parent->d_subdirs) {
68 dentry = list_entry(next, struct dentry, d_u.d_child);
69 dentry->d_fsdata = NULL;
70 smb_age_dentry(server, dentry);
71 next = next->next;
72 }
73 spin_unlock(&parent->d_lock);
74}
75
76/*
77 * dget, but require that fpos and parent matches what the dentry contains.
78 * dentry is not known to be a valid pointer at entry.
79 */
80struct dentry *
81smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
82{
83 struct dentry *dent = dentry;
84 struct list_head *next;
85
86 if (d_validate(dent, parent)) {
87 if (dent->d_name.len <= SMB_MAXNAMELEN &&
88 (unsigned long)dent->d_fsdata == fpos) {
89 if (!dent->d_inode) {
90 dput(dent);
91 dent = NULL;
92 }
93 return dent;
94 }
95 dput(dent);
96 }
97
98 /* If a pointer is invalid, we search the dentry. */
99 spin_lock(&parent->d_lock);
100 next = parent->d_subdirs.next;
101 while (next != &parent->d_subdirs) {
102 dent = list_entry(next, struct dentry, d_u.d_child);
103 if ((unsigned long)dent->d_fsdata == fpos) {
104 if (dent->d_inode)
105 dget(dent);
106 else
107 dent = NULL;
108 goto out_unlock;
109 }
110 next = next->next;
111 }
112 dent = NULL;
113out_unlock:
114 spin_unlock(&parent->d_lock);
115 return dent;
116}
117
118
119/*
120 * Create dentry/inode for this file and add it to the dircache.
121 */
122int
123smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
124 struct smb_cache_control *ctrl, struct qstr *qname,
125 struct smb_fattr *entry)
126{
127 struct dentry *newdent, *dentry = filp->f_path.dentry;
128 struct inode *newino, *inode = dentry->d_inode;
129 struct smb_cache_control ctl = *ctrl;
130 int valid = 0;
131 int hashed = 0;
132 ino_t ino = 0;
133
134 qname->hash = full_name_hash(qname->name, qname->len);
135
136 if (dentry->d_op && dentry->d_op->d_hash)
137 if (dentry->d_op->d_hash(dentry, inode, qname) != 0)
138 goto end_advance;
139
140 newdent = d_lookup(dentry, qname);
141
142 if (!newdent) {
143 newdent = d_alloc(dentry, qname);
144 if (!newdent)
145 goto end_advance;
146 } else {
147 hashed = 1;
148 /* dir i_mutex is locked because we're in readdir */
149 dentry_update_name_case(newdent, qname);
150 }
151
152 if (!newdent->d_inode) {
153 smb_renew_times(newdent);
154 entry->f_ino = iunique(inode->i_sb, 2);
155 newino = smb_iget(inode->i_sb, entry);
156 if (newino) {
157 smb_new_dentry(newdent);
158 d_instantiate(newdent, newino);
159 if (!hashed)
160 d_rehash(newdent);
161 }
162 } else
163 smb_set_inode_attr(newdent->d_inode, entry);
164
165 if (newdent->d_inode) {
166 ino = newdent->d_inode->i_ino;
167 newdent->d_fsdata = (void *) ctl.fpos;
168 smb_new_dentry(newdent);
169 }
170
171 if (ctl.idx >= SMB_DIRCACHE_SIZE) {
172 if (ctl.page) {
173 kunmap(ctl.page);
174 SetPageUptodate(ctl.page);
175 unlock_page(ctl.page);
176 page_cache_release(ctl.page);
177 }
178 ctl.cache = NULL;
179 ctl.idx -= SMB_DIRCACHE_SIZE;
180 ctl.ofs += 1;
181 ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
182 if (ctl.page)
183 ctl.cache = kmap(ctl.page);
184 }
185 if (ctl.cache) {
186 ctl.cache->dentry[ctl.idx] = newdent;
187 valid = 1;
188 }
189 dput(newdent);
190
191end_advance:
192 if (!valid)
193 ctl.valid = 0;
194 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
195 if (!ino)
196 ino = find_inode_number(dentry, qname);
197 if (!ino)
198 ino = iunique(inode->i_sb, 2);
199 ctl.filled = filldir(dirent, qname->name, qname->len,
200 filp->f_pos, ino, DT_UNKNOWN);
201 if (!ctl.filled)
202 filp->f_pos += 1;
203 }
204 ctl.fpos += 1;
205 ctl.idx += 1;
206 *ctrl = ctl;
207 return (ctl.valid || !ctl.filled);
208}
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c
deleted file mode 100644
index f204d33910e..00000000000
--- a/drivers/staging/smbfs/dir.c
+++ /dev/null
@@ -1,699 +0,0 @@
1/*
2 * dir.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/time.h>
11#include <linux/errno.h>
12#include <linux/kernel.h>
13#include <linux/smp_lock.h>
14#include <linux/ctype.h>
15#include <linux/net.h>
16#include <linux/sched.h>
17#include <linux/namei.h>
18
19#include "smb_fs.h"
20#include "smb_mount.h"
21#include "smbno.h"
22
23#include "smb_debug.h"
24#include "proto.h"
25
26static int smb_readdir(struct file *, void *, filldir_t);
27static int smb_dir_open(struct inode *, struct file *);
28
29static struct dentry *smb_lookup(struct inode *, struct dentry *, struct nameidata *);
30static int smb_create(struct inode *, struct dentry *, int, struct nameidata *);
31static int smb_mkdir(struct inode *, struct dentry *, int);
32static int smb_rmdir(struct inode *, struct dentry *);
33static int smb_unlink(struct inode *, struct dentry *);
34static int smb_rename(struct inode *, struct dentry *,
35 struct inode *, struct dentry *);
36static int smb_make_node(struct inode *,struct dentry *,int,dev_t);
37static int smb_link(struct dentry *, struct inode *, struct dentry *);
38
39const struct file_operations smb_dir_operations =
40{
41 .llseek = generic_file_llseek,
42 .read = generic_read_dir,
43 .readdir = smb_readdir,
44 .unlocked_ioctl = smb_ioctl,
45 .open = smb_dir_open,
46};
47
48const struct inode_operations smb_dir_inode_operations =
49{
50 .create = smb_create,
51 .lookup = smb_lookup,
52 .unlink = smb_unlink,
53 .mkdir = smb_mkdir,
54 .rmdir = smb_rmdir,
55 .rename = smb_rename,
56 .getattr = smb_getattr,
57 .setattr = smb_notify_change,
58};
59
60const struct inode_operations smb_dir_inode_operations_unix =
61{
62 .create = smb_create,
63 .lookup = smb_lookup,
64 .unlink = smb_unlink,
65 .mkdir = smb_mkdir,
66 .rmdir = smb_rmdir,
67 .rename = smb_rename,
68 .getattr = smb_getattr,
69 .setattr = smb_notify_change,
70 .symlink = smb_symlink,
71 .mknod = smb_make_node,
72 .link = smb_link,
73};
74
75/*
76 * Read a directory, using filldir to fill the dirent memory.
77 * smb_proc_readdir does the actual reading from the smb server.
78 *
79 * The cache code is almost directly taken from ncpfs
80 */
81static int
82smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
83{
84 struct dentry *dentry = filp->f_path.dentry;
85 struct inode *dir = dentry->d_inode;
86 struct smb_sb_info *server = server_from_dentry(dentry);
87 union smb_dir_cache *cache = NULL;
88 struct smb_cache_control ctl;
89 struct page *page = NULL;
90 int result;
91
92 ctl.page = NULL;
93 ctl.cache = NULL;
94
95 VERBOSE("reading %s/%s, f_pos=%d\n",
96 DENTRY_PATH(dentry), (int) filp->f_pos);
97
98 result = 0;
99
100 lock_kernel();
101
102 switch ((unsigned int) filp->f_pos) {
103 case 0:
104 if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
105 goto out;
106 filp->f_pos = 1;
107 /* fallthrough */
108 case 1:
109 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR) < 0)
110 goto out;
111 filp->f_pos = 2;
112 }
113
114 /*
115 * Make sure our inode is up-to-date.
116 */
117 result = smb_revalidate_inode(dentry);
118 if (result)
119 goto out;
120
121
122 page = grab_cache_page(&dir->i_data, 0);
123 if (!page)
124 goto read_really;
125
126 ctl.cache = cache = kmap(page);
127 ctl.head = cache->head;
128
129 if (!PageUptodate(page) || !ctl.head.eof) {
130 VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
131 DENTRY_PATH(dentry), PageUptodate(page),ctl.head.eof);
132 goto init_cache;
133 }
134
135 if (filp->f_pos == 2) {
136 if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
137 goto init_cache;
138
139 /*
140 * N.B. ncpfs checks mtime of dentry too here, we don't.
141 * 1. common smb servers do not update mtime on dir changes
142 * 2. it requires an extra smb request
143 * (revalidate has the same timeout as ctl.head.time)
144 *
145 * Instead smbfs invalidates its own cache on local changes
146 * and remote changes are not seen until timeout.
147 */
148 }
149
150 if (filp->f_pos > ctl.head.end)
151 goto finished;
152
153 ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
154 ctl.ofs = ctl.fpos / SMB_DIRCACHE_SIZE;
155 ctl.idx = ctl.fpos % SMB_DIRCACHE_SIZE;
156
157 for (;;) {
158 if (ctl.ofs != 0) {
159 ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
160 if (!ctl.page)
161 goto invalid_cache;
162 ctl.cache = kmap(ctl.page);
163 if (!PageUptodate(ctl.page))
164 goto invalid_cache;
165 }
166 while (ctl.idx < SMB_DIRCACHE_SIZE) {
167 struct dentry *dent;
168 int res;
169
170 dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
171 dentry, filp->f_pos);
172 if (!dent)
173 goto invalid_cache;
174
175 res = filldir(dirent, dent->d_name.name,
176 dent->d_name.len, filp->f_pos,
177 dent->d_inode->i_ino, DT_UNKNOWN);
178 dput(dent);
179 if (res)
180 goto finished;
181 filp->f_pos += 1;
182 ctl.idx += 1;
183 if (filp->f_pos > ctl.head.end)
184 goto finished;
185 }
186 if (ctl.page) {
187 kunmap(ctl.page);
188 SetPageUptodate(ctl.page);
189 unlock_page(ctl.page);
190 page_cache_release(ctl.page);
191 ctl.page = NULL;
192 }
193 ctl.idx = 0;
194 ctl.ofs += 1;
195 }
196invalid_cache:
197 if (ctl.page) {
198 kunmap(ctl.page);
199 unlock_page(ctl.page);
200 page_cache_release(ctl.page);
201 ctl.page = NULL;
202 }
203 ctl.cache = cache;
204init_cache:
205 smb_invalidate_dircache_entries(dentry);
206 ctl.head.time = jiffies;
207 ctl.head.eof = 0;
208 ctl.fpos = 2;
209 ctl.ofs = 0;
210 ctl.idx = SMB_DIRCACHE_START;
211 ctl.filled = 0;
212 ctl.valid = 1;
213read_really:
214 result = server->ops->readdir(filp, dirent, filldir, &ctl);
215 if (result == -ERESTARTSYS && page)
216 ClearPageUptodate(page);
217 if (ctl.idx == -1)
218 goto invalid_cache; /* retry */
219 ctl.head.end = ctl.fpos - 1;
220 ctl.head.eof = ctl.valid;
221finished:
222 if (page) {
223 cache->head = ctl.head;
224 kunmap(page);
225 if (result != -ERESTARTSYS)
226 SetPageUptodate(page);
227 unlock_page(page);
228 page_cache_release(page);
229 }
230 if (ctl.page) {
231 kunmap(ctl.page);
232 SetPageUptodate(ctl.page);
233 unlock_page(ctl.page);
234 page_cache_release(ctl.page);
235 }
236out:
237 unlock_kernel();
238 return result;
239}
240
241static int
242smb_dir_open(struct inode *dir, struct file *file)
243{
244 struct dentry *dentry = file->f_path.dentry;
245 struct smb_sb_info *server;
246 int error = 0;
247
248 VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
249 file->f_path.dentry->d_name.name);
250
251 /*
252 * Directory timestamps in the core protocol aren't updated
253 * when a file is added, so we give them a very short TTL.
254 */
255 lock_kernel();
256 server = server_from_dentry(dentry);
257 if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
258 unsigned long age = jiffies - SMB_I(dir)->oldmtime;
259 if (age > 2*HZ)
260 smb_invalid_dir_cache(dir);
261 }
262
263 /*
264 * Note: in order to allow the smbmount process to open the
265 * mount point, we only revalidate if the connection is valid or
266 * if the process is trying to access something other than the root.
267 */
268 if (server->state == CONN_VALID || !IS_ROOT(dentry))
269 error = smb_revalidate_inode(dentry);
270 unlock_kernel();
271 return error;
272}
273
274/*
275 * Dentry operations routines
276 */
277static int smb_lookup_validate(struct dentry *, struct nameidata *);
278static int smb_hash_dentry(const struct dentry *, const struct inode *,
279 struct qstr *);
280static int smb_compare_dentry(const struct dentry *,
281 const struct inode *,
282 const struct dentry *, const struct inode *,
283 unsigned int, const char *, const struct qstr *);
284static int smb_delete_dentry(const struct dentry *);
285
286const struct dentry_operations smbfs_dentry_operations =
287{
288 .d_revalidate = smb_lookup_validate,
289 .d_hash = smb_hash_dentry,
290 .d_compare = smb_compare_dentry,
291 .d_delete = smb_delete_dentry,
292};
293
294const struct dentry_operations smbfs_dentry_operations_case =
295{
296 .d_revalidate = smb_lookup_validate,
297 .d_delete = smb_delete_dentry,
298};
299
300
301/*
302 * This is the callback when the dcache has a lookup hit.
303 */
304static int
305smb_lookup_validate(struct dentry *dentry, struct nameidata *nd)
306{
307 struct smb_sb_info *server;
308 struct inode *inode;
309 unsigned long age;
310 int valid;
311
312 if (nd->flags & LOOKUP_RCU)
313 return -ECHILD;
314
315 server = server_from_dentry(dentry);
316 inode = dentry->d_inode;
317 age = jiffies - dentry->d_time;
318
319 /*
320 * The default validation is based on dentry age:
321 * we believe in dentries for a few seconds. (But each
322 * successful server lookup renews the timestamp.)
323 */
324 valid = (age <= SMB_MAX_AGE(server));
325#ifdef SMBFS_DEBUG_VERBOSE
326 if (!valid)
327 VERBOSE("%s/%s not valid, age=%lu\n",
328 DENTRY_PATH(dentry), age);
329#endif
330
331 if (inode) {
332 lock_kernel();
333 if (is_bad_inode(inode)) {
334 PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
335 valid = 0;
336 } else if (!valid)
337 valid = (smb_revalidate_inode(dentry) == 0);
338 unlock_kernel();
339 } else {
340 /*
341 * What should we do for negative dentries?
342 */
343 }
344 return valid;
345}
346
347static int
348smb_hash_dentry(const struct dentry *dir, const struct inode *inode,
349 struct qstr *this)
350{
351 unsigned long hash;
352 int i;
353
354 hash = init_name_hash();
355 for (i=0; i < this->len ; i++)
356 hash = partial_name_hash(tolower(this->name[i]), hash);
357 this->hash = end_name_hash(hash);
358
359 return 0;
360}
361
362static int
363smb_compare_dentry(const struct dentry *parent,
364 const struct inode *pinode,
365 const struct dentry *dentry, const struct inode *inode,
366 unsigned int len, const char *str, const struct qstr *name)
367{
368 int i, result = 1;
369
370 if (len != name->len)
371 goto out;
372 for (i=0; i < len; i++) {
373 if (tolower(str[i]) != tolower(name->name[i]))
374 goto out;
375 }
376 result = 0;
377out:
378 return result;
379}
380
381/*
382 * This is the callback from dput() when d_count is going to 0.
383 * We use this to unhash dentries with bad inodes.
384 */
385static int
386smb_delete_dentry(const struct dentry *dentry)
387{
388 if (dentry->d_inode) {
389 if (is_bad_inode(dentry->d_inode)) {
390 PARANOIA("bad inode, unhashing %s/%s\n",
391 DENTRY_PATH(dentry));
392 return 1;
393 }
394 } else {
395 /* N.B. Unhash negative dentries? */
396 }
397 return 0;
398}
399
400/*
401 * Initialize a new dentry
402 */
403void
404smb_new_dentry(struct dentry *dentry)
405{
406 dentry->d_time = jiffies;
407}
408
409
410/*
411 * Whenever a lookup succeeds, we know the parent directories
412 * are all valid, so we want to update the dentry timestamps.
413 * N.B. Move this to dcache?
414 */
415void
416smb_renew_times(struct dentry * dentry)
417{
418 dget(dentry);
419 dentry->d_time = jiffies;
420
421 while (!IS_ROOT(dentry)) {
422 struct dentry *parent = dget_parent(dentry);
423 dput(dentry);
424 dentry = parent;
425
426 dentry->d_time = jiffies;
427 }
428 dput(dentry);
429}
430
431static struct dentry *
432smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
433{
434 struct smb_fattr finfo;
435 struct inode *inode;
436 int error;
437
438 error = -ENAMETOOLONG;
439 if (dentry->d_name.len > SMB_MAXNAMELEN)
440 goto out;
441
442 /* Do not allow lookup of names with backslashes in */
443 error = -EINVAL;
444 if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
445 goto out;
446
447 lock_kernel();
448 error = smb_proc_getattr(dentry, &finfo);
449#ifdef SMBFS_PARANOIA
450 if (error && error != -ENOENT)
451 PARANOIA("find %s/%s failed, error=%d\n",
452 DENTRY_PATH(dentry), error);
453#endif
454
455 inode = NULL;
456 if (error == -ENOENT)
457 goto add_entry;
458 if (!error) {
459 error = -EACCES;
460 finfo.f_ino = iunique(dentry->d_sb, 2);
461 inode = smb_iget(dir->i_sb, &finfo);
462 if (inode) {
463 add_entry:
464 d_add(dentry, inode);
465 smb_renew_times(dentry);
466 error = 0;
467 }
468 }
469 unlock_kernel();
470out:
471 return ERR_PTR(error);
472}
473
474/*
475 * This code is common to all routines creating a new inode.
476 */
477static int
478smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
479{
480 struct smb_sb_info *server = server_from_dentry(dentry);
481 struct inode *inode;
482 int error;
483 struct smb_fattr fattr;
484
485 VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
486
487 error = smb_proc_getattr(dentry, &fattr);
488 if (error)
489 goto out_close;
490
491 smb_renew_times(dentry);
492 fattr.f_ino = iunique(dentry->d_sb, 2);
493 inode = smb_iget(dentry->d_sb, &fattr);
494 if (!inode)
495 goto out_no_inode;
496
497 if (have_id) {
498 struct smb_inode_info *ei = SMB_I(inode);
499 ei->fileid = fileid;
500 ei->access = SMB_O_RDWR;
501 ei->open = server->generation;
502 }
503 d_instantiate(dentry, inode);
504out:
505 return error;
506
507out_no_inode:
508 error = -EACCES;
509out_close:
510 if (have_id) {
511 PARANOIA("%s/%s failed, error=%d, closing %u\n",
512 DENTRY_PATH(dentry), error, fileid);
513 smb_close_fileid(dentry, fileid);
514 }
515 goto out;
516}
517
518/* N.B. How should the mode argument be used? */
519static int
520smb_create(struct inode *dir, struct dentry *dentry, int mode,
521 struct nameidata *nd)
522{
523 struct smb_sb_info *server = server_from_dentry(dentry);
524 __u16 fileid;
525 int error;
526 struct iattr attr;
527
528 VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
529
530 lock_kernel();
531 smb_invalid_dir_cache(dir);
532 error = smb_proc_create(dentry, 0, get_seconds(), &fileid);
533 if (!error) {
534 if (server->opt.capabilities & SMB_CAP_UNIX) {
535 /* Set attributes for new file */
536 attr.ia_valid = ATTR_MODE;
537 attr.ia_mode = mode;
538 error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
539 }
540 error = smb_instantiate(dentry, fileid, 1);
541 } else {
542 PARANOIA("%s/%s failed, error=%d\n",
543 DENTRY_PATH(dentry), error);
544 }
545 unlock_kernel();
546 return error;
547}
548
549/* N.B. How should the mode argument be used? */
550static int
551smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
552{
553 struct smb_sb_info *server = server_from_dentry(dentry);
554 int error;
555 struct iattr attr;
556
557 lock_kernel();
558 smb_invalid_dir_cache(dir);
559 error = smb_proc_mkdir(dentry);
560 if (!error) {
561 if (server->opt.capabilities & SMB_CAP_UNIX) {
562 /* Set attributes for new directory */
563 attr.ia_valid = ATTR_MODE;
564 attr.ia_mode = mode;
565 error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
566 }
567 error = smb_instantiate(dentry, 0, 0);
568 }
569 unlock_kernel();
570 return error;
571}
572
573static int
574smb_rmdir(struct inode *dir, struct dentry *dentry)
575{
576 struct inode *inode = dentry->d_inode;
577 int error;
578
579 /*
580 * Close the directory if it's open.
581 */
582 lock_kernel();
583 smb_close(inode);
584
585 /*
586 * Check that nobody else is using the directory..
587 */
588 error = -EBUSY;
589 if (!d_unhashed(dentry))
590 goto out;
591
592 smb_invalid_dir_cache(dir);
593 error = smb_proc_rmdir(dentry);
594
595out:
596 unlock_kernel();
597 return error;
598}
599
600static int
601smb_unlink(struct inode *dir, struct dentry *dentry)
602{
603 int error;
604
605 /*
606 * Close the file if it's open.
607 */
608 lock_kernel();
609 smb_close(dentry->d_inode);
610
611 smb_invalid_dir_cache(dir);
612 error = smb_proc_unlink(dentry);
613 if (!error)
614 smb_renew_times(dentry);
615 unlock_kernel();
616 return error;
617}
618
619static int
620smb_rename(struct inode *old_dir, struct dentry *old_dentry,
621 struct inode *new_dir, struct dentry *new_dentry)
622{
623 int error;
624
625 /*
626 * Close any open files, and check whether to delete the
627 * target before attempting the rename.
628 */
629 lock_kernel();
630 if (old_dentry->d_inode)
631 smb_close(old_dentry->d_inode);
632 if (new_dentry->d_inode) {
633 smb_close(new_dentry->d_inode);
634 error = smb_proc_unlink(new_dentry);
635 if (error) {
636 VERBOSE("unlink %s/%s, error=%d\n",
637 DENTRY_PATH(new_dentry), error);
638 goto out;
639 }
640 /* FIXME */
641 d_delete(new_dentry);
642 }
643
644 smb_invalid_dir_cache(old_dir);
645 smb_invalid_dir_cache(new_dir);
646 error = smb_proc_mv(old_dentry, new_dentry);
647 if (!error) {
648 smb_renew_times(old_dentry);
649 smb_renew_times(new_dentry);
650 }
651out:
652 unlock_kernel();
653 return error;
654}
655
656/*
657 * FIXME: samba servers won't let you create device nodes unless uid/gid
658 * matches the connection credentials (and we don't know which those are ...)
659 */
660static int
661smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
662{
663 int error;
664 struct iattr attr;
665
666 attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID;
667 attr.ia_mode = mode;
668 current_euid_egid(&attr.ia_uid, &attr.ia_gid);
669
670 if (!new_valid_dev(dev))
671 return -EINVAL;
672
673 smb_invalid_dir_cache(dir);
674 error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev));
675 if (!error) {
676 error = smb_instantiate(dentry, 0, 0);
677 }
678 return error;
679}
680
681/*
682 * dentry = existing file
683 * new_dentry = new file
684 */
685static int
686smb_link(struct dentry *dentry, struct inode *dir, struct dentry *new_dentry)
687{
688 int error;
689
690 DEBUG1("smb_link old=%s/%s new=%s/%s\n",
691 DENTRY_PATH(dentry), DENTRY_PATH(new_dentry));
692 smb_invalid_dir_cache(dir);
693 error = smb_proc_link(server_from_dentry(dentry), dentry, new_dentry);
694 if (!error) {
695 smb_renew_times(dentry);
696 error = smb_instantiate(new_dentry, 0, 0);
697 }
698 return error;
699}
diff --git a/drivers/staging/smbfs/file.c b/drivers/staging/smbfs/file.c
deleted file mode 100644
index 31372e7b12d..00000000000
--- a/drivers/staging/smbfs/file.c
+++ /dev/null
@@ -1,456 +0,0 @@
1/*
2 * file.c
3 *
4 * Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/time.h>
11#include <linux/kernel.h>
12#include <linux/errno.h>
13#include <linux/fcntl.h>
14#include <linux/stat.h>
15#include <linux/mm.h>
16#include <linux/pagemap.h>
17#include <linux/smp_lock.h>
18#include <linux/net.h>
19#include <linux/aio.h>
20
21#include <asm/uaccess.h>
22#include <asm/system.h>
23
24#include "smbno.h"
25#include "smb_fs.h"
26#include "smb_debug.h"
27#include "proto.h"
28
29static int
30smb_fsync(struct file *file, int datasync)
31{
32 struct dentry *dentry = file->f_path.dentry;
33 struct smb_sb_info *server = server_from_dentry(dentry);
34 int result;
35
36 VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
37
38 /*
39 * The VFS will writepage() all dirty pages for us, but we
40 * should send a SMBflush to the server, letting it know that
41 * we want things synchronized with actual storage.
42 *
43 * Note: this function requires all pages to have been written already
44 * (should be ok with writepage_sync)
45 */
46 result = smb_proc_flush(server, SMB_I(dentry->d_inode)->fileid);
47 return result;
48}
49
50/*
51 * Read a page synchronously.
52 */
53static int
54smb_readpage_sync(struct dentry *dentry, struct page *page)
55{
56 char *buffer = kmap(page);
57 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
58 struct smb_sb_info *server = server_from_dentry(dentry);
59 unsigned int rsize = smb_get_rsize(server);
60 int count = PAGE_SIZE;
61 int result;
62
63 VERBOSE("file %s/%s, count=%d@%Ld, rsize=%d\n",
64 DENTRY_PATH(dentry), count, offset, rsize);
65
66 result = smb_open(dentry, SMB_O_RDONLY);
67 if (result < 0)
68 goto io_error;
69
70 do {
71 if (count < rsize)
72 rsize = count;
73
74 result = server->ops->read(dentry->d_inode,offset,rsize,buffer);
75 if (result < 0)
76 goto io_error;
77
78 count -= result;
79 offset += result;
80 buffer += result;
81 dentry->d_inode->i_atime =
82 current_fs_time(dentry->d_inode->i_sb);
83 if (result < rsize)
84 break;
85 } while (count);
86
87 memset(buffer, 0, count);
88 flush_dcache_page(page);
89 SetPageUptodate(page);
90 result = 0;
91
92io_error:
93 kunmap(page);
94 unlock_page(page);
95 return result;
96}
97
98/*
99 * We are called with the page locked and we unlock it when done.
100 */
101static int
102smb_readpage(struct file *file, struct page *page)
103{
104 int error;
105 struct dentry *dentry = file->f_path.dentry;
106
107 page_cache_get(page);
108 error = smb_readpage_sync(dentry, page);
109 page_cache_release(page);
110 return error;
111}
112
113/*
114 * Write a page synchronously.
115 * Offset is the data offset within the page.
116 */
117static int
118smb_writepage_sync(struct inode *inode, struct page *page,
119 unsigned long pageoffset, unsigned int count)
120{
121 loff_t offset;
122 char *buffer = kmap(page) + pageoffset;
123 struct smb_sb_info *server = server_from_inode(inode);
124 unsigned int wsize = smb_get_wsize(server);
125 int ret = 0;
126
127 offset = ((loff_t)page->index << PAGE_CACHE_SHIFT) + pageoffset;
128 VERBOSE("file ino=%ld, fileid=%d, count=%d@%Ld, wsize=%d\n",
129 inode->i_ino, SMB_I(inode)->fileid, count, offset, wsize);
130
131 do {
132 int write_ret;
133
134 if (count < wsize)
135 wsize = count;
136
137 write_ret = server->ops->write(inode, offset, wsize, buffer);
138 if (write_ret < 0) {
139 PARANOIA("failed write, wsize=%d, write_ret=%d\n",
140 wsize, write_ret);
141 ret = write_ret;
142 break;
143 }
144 /* N.B. what if result < wsize?? */
145#ifdef SMBFS_PARANOIA
146 if (write_ret < wsize)
147 PARANOIA("short write, wsize=%d, write_ret=%d\n",
148 wsize, write_ret);
149#endif
150 buffer += wsize;
151 offset += wsize;
152 count -= wsize;
153 /*
154 * Update the inode now rather than waiting for a refresh.
155 */
156 inode->i_mtime = inode->i_atime = current_fs_time(inode->i_sb);
157 SMB_I(inode)->flags |= SMB_F_LOCALWRITE;
158 if (offset > inode->i_size)
159 inode->i_size = offset;
160 } while (count);
161
162 kunmap(page);
163 return ret;
164}
165
166/*
167 * Write a page to the server. This will be used for NFS swapping only
168 * (for now), and we currently do this synchronously only.
169 *
170 * We are called with the page locked and we unlock it when done.
171 */
172static int
173smb_writepage(struct page *page, struct writeback_control *wbc)
174{
175 struct address_space *mapping = page->mapping;
176 struct inode *inode;
177 unsigned long end_index;
178 unsigned offset = PAGE_CACHE_SIZE;
179 int err;
180
181 BUG_ON(!mapping);
182 inode = mapping->host;
183 BUG_ON(!inode);
184
185 end_index = inode->i_size >> PAGE_CACHE_SHIFT;
186
187 /* easy case */
188 if (page->index < end_index)
189 goto do_it;
190 /* things got complicated... */
191 offset = inode->i_size & (PAGE_CACHE_SIZE-1);
192 /* OK, are we completely out? */
193 if (page->index >= end_index+1 || !offset)
194 return 0; /* truncated - don't care */
195do_it:
196 page_cache_get(page);
197 err = smb_writepage_sync(inode, page, 0, offset);
198 SetPageUptodate(page);
199 unlock_page(page);
200 page_cache_release(page);
201 return err;
202}
203
204static int
205smb_updatepage(struct file *file, struct page *page, unsigned long offset,
206 unsigned int count)
207{
208 struct dentry *dentry = file->f_path.dentry;
209
210 DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
211 ((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
212
213 return smb_writepage_sync(dentry->d_inode, page, offset, count);
214}
215
216static ssize_t
217smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
218 unsigned long nr_segs, loff_t pos)
219{
220 struct file * file = iocb->ki_filp;
221 struct dentry * dentry = file->f_path.dentry;
222 ssize_t status;
223
224 VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
225 (unsigned long) iocb->ki_left, (unsigned long) pos);
226
227 status = smb_revalidate_inode(dentry);
228 if (status) {
229 PARANOIA("%s/%s validation failed, error=%Zd\n",
230 DENTRY_PATH(dentry), status);
231 goto out;
232 }
233
234 VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
235 (long)dentry->d_inode->i_size,
236 dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec);
237
238 status = generic_file_aio_read(iocb, iov, nr_segs, pos);
239out:
240 return status;
241}
242
243static int
244smb_file_mmap(struct file * file, struct vm_area_struct * vma)
245{
246 struct dentry * dentry = file->f_path.dentry;
247 int status;
248
249 VERBOSE("file %s/%s, address %lu - %lu\n",
250 DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
251
252 status = smb_revalidate_inode(dentry);
253 if (status) {
254 PARANOIA("%s/%s validation failed, error=%d\n",
255 DENTRY_PATH(dentry), status);
256 goto out;
257 }
258 status = generic_file_mmap(file, vma);
259out:
260 return status;
261}
262
263static ssize_t
264smb_file_splice_read(struct file *file, loff_t *ppos,
265 struct pipe_inode_info *pipe, size_t count,
266 unsigned int flags)
267{
268 struct dentry *dentry = file->f_path.dentry;
269 ssize_t status;
270
271 VERBOSE("file %s/%s, pos=%Ld, count=%lu\n",
272 DENTRY_PATH(dentry), *ppos, count);
273
274 status = smb_revalidate_inode(dentry);
275 if (status) {
276 PARANOIA("%s/%s validation failed, error=%Zd\n",
277 DENTRY_PATH(dentry), status);
278 goto out;
279 }
280 status = generic_file_splice_read(file, ppos, pipe, count, flags);
281out:
282 return status;
283}
284
285/*
286 * This does the "real" work of the write. The generic routine has
287 * allocated the page, locked it, done all the page alignment stuff
288 * calculations etc. Now we should just copy the data from user
289 * space and write it back to the real medium..
290 *
291 * If the writer ends up delaying the write, the writer needs to
292 * increment the page use counts until he is done with the page.
293 */
294static int smb_write_begin(struct file *file, struct address_space *mapping,
295 loff_t pos, unsigned len, unsigned flags,
296 struct page **pagep, void **fsdata)
297{
298 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
299 *pagep = grab_cache_page_write_begin(mapping, index, flags);
300 if (!*pagep)
301 return -ENOMEM;
302 return 0;
303}
304
305static int smb_write_end(struct file *file, struct address_space *mapping,
306 loff_t pos, unsigned len, unsigned copied,
307 struct page *page, void *fsdata)
308{
309 int status;
310 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
311
312 lock_kernel();
313 status = smb_updatepage(file, page, offset, copied);
314 unlock_kernel();
315
316 if (!status) {
317 if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
318 SetPageUptodate(page);
319 status = copied;
320 }
321
322 unlock_page(page);
323 page_cache_release(page);
324
325 return status;
326}
327
328const struct address_space_operations smb_file_aops = {
329 .readpage = smb_readpage,
330 .writepage = smb_writepage,
331 .write_begin = smb_write_begin,
332 .write_end = smb_write_end,
333};
334
335/*
336 * Write to a file (through the page cache).
337 */
338static ssize_t
339smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
340 unsigned long nr_segs, loff_t pos)
341{
342 struct file * file = iocb->ki_filp;
343 struct dentry * dentry = file->f_path.dentry;
344 ssize_t result;
345
346 VERBOSE("file %s/%s, count=%lu@%lu\n",
347 DENTRY_PATH(dentry),
348 (unsigned long) iocb->ki_left, (unsigned long) pos);
349
350 result = smb_revalidate_inode(dentry);
351 if (result) {
352 PARANOIA("%s/%s validation failed, error=%Zd\n",
353 DENTRY_PATH(dentry), result);
354 goto out;
355 }
356
357 result = smb_open(dentry, SMB_O_WRONLY);
358 if (result)
359 goto out;
360
361 if (iocb->ki_left > 0) {
362 result = generic_file_aio_write(iocb, iov, nr_segs, pos);
363 VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
364 (long) file->f_pos, (long) dentry->d_inode->i_size,
365 dentry->d_inode->i_mtime.tv_sec,
366 dentry->d_inode->i_atime.tv_sec);
367 }
368out:
369 return result;
370}
371
372static int
373smb_file_open(struct inode *inode, struct file * file)
374{
375 int result;
376 struct dentry *dentry = file->f_path.dentry;
377 int smb_mode = (file->f_mode & O_ACCMODE) - 1;
378
379 lock_kernel();
380 result = smb_open(dentry, smb_mode);
381 if (result)
382 goto out;
383 SMB_I(inode)->openers++;
384out:
385 unlock_kernel();
386 return result;
387}
388
389static int
390smb_file_release(struct inode *inode, struct file * file)
391{
392 lock_kernel();
393 if (!--SMB_I(inode)->openers) {
394 /* We must flush any dirty pages now as we won't be able to
395 write anything after close. mmap can trigger this.
396 "openers" should perhaps include mmap'ers ... */
397 filemap_write_and_wait(inode->i_mapping);
398 smb_close(inode);
399 }
400 unlock_kernel();
401 return 0;
402}
403
404/*
405 * Check whether the required access is compatible with
406 * an inode's permission. SMB doesn't recognize superuser
407 * privileges, so we need our own check for this.
408 */
409static int
410smb_file_permission(struct inode *inode, int mask, unsigned int flags)
411{
412 int mode = inode->i_mode;
413 int error = 0;
414
415 if (flags & IPERM_FLAG_RCU)
416 return -ECHILD;
417
418 VERBOSE("mode=%x, mask=%x\n", mode, mask);
419
420 /* Look at user permissions */
421 mode >>= 6;
422 if (mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC))
423 error = -EACCES;
424 return error;
425}
426
427static loff_t smb_remote_llseek(struct file *file, loff_t offset, int origin)
428{
429 loff_t ret;
430 lock_kernel();
431 ret = generic_file_llseek_unlocked(file, offset, origin);
432 unlock_kernel();
433 return ret;
434}
435
436const struct file_operations smb_file_operations =
437{
438 .llseek = smb_remote_llseek,
439 .read = do_sync_read,
440 .aio_read = smb_file_aio_read,
441 .write = do_sync_write,
442 .aio_write = smb_file_aio_write,
443 .unlocked_ioctl = smb_ioctl,
444 .mmap = smb_file_mmap,
445 .open = smb_file_open,
446 .release = smb_file_release,
447 .fsync = smb_fsync,
448 .splice_read = smb_file_splice_read,
449};
450
451const struct inode_operations smb_file_inode_operations =
452{
453 .permission = smb_file_permission,
454 .getattr = smb_getattr,
455 .setattr = smb_notify_change,
456};
diff --git a/drivers/staging/smbfs/getopt.c b/drivers/staging/smbfs/getopt.c
deleted file mode 100644
index 7ae0f5273ab..00000000000
--- a/drivers/staging/smbfs/getopt.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * getopt.c
3 */
4
5#include <linux/kernel.h>
6#include <linux/string.h>
7#include <linux/net.h>
8
9#include "getopt.h"
10
11/**
12 * smb_getopt - option parser
13 * @caller: name of the caller, for error messages
14 * @options: the options string
15 * @opts: an array of &struct option entries controlling parser operations
16 * @optopt: output; will contain the current option
17 * @optarg: output; will contain the value (if one exists)
18 * @flag: output; may be NULL; should point to a long for or'ing flags
19 * @value: output; may be NULL; will be overwritten with the integer value
20 * of the current argument.
21 *
22 * Helper to parse options on the format used by mount ("a=b,c=d,e,f").
23 * Returns opts->val if a matching entry in the 'opts' array is found,
24 * 0 when no more tokens are found, -1 if an error is encountered.
25 */
26int smb_getopt(char *caller, char **options, struct option *opts,
27 char **optopt, char **optarg, unsigned long *flag,
28 unsigned long *value)
29{
30 char *token;
31 char *val;
32 int i;
33
34 do {
35 if ((token = strsep(options, ",")) == NULL)
36 return 0;
37 } while (*token == '\0');
38 *optopt = token;
39
40 *optarg = NULL;
41 if ((val = strchr (token, '=')) != NULL) {
42 *val++ = 0;
43 if (value)
44 *value = simple_strtoul(val, NULL, 0);
45 *optarg = val;
46 }
47
48 for (i = 0; opts[i].name != NULL; i++) {
49 if (!strcmp(opts[i].name, token)) {
50 if (!opts[i].flag && (!val || !*val)) {
51 printk("%s: the %s option requires an argument\n",
52 caller, token);
53 return -1;
54 }
55
56 if (flag && opts[i].flag)
57 *flag |= opts[i].flag;
58
59 return opts[i].val;
60 }
61 }
62 printk("%s: Unrecognized mount option %s\n", caller, token);
63 return -1;
64}
diff --git a/drivers/staging/smbfs/getopt.h b/drivers/staging/smbfs/getopt.h
deleted file mode 100644
index 146219ac7c4..00000000000
--- a/drivers/staging/smbfs/getopt.h
+++ /dev/null
@@ -1,14 +0,0 @@
1#ifndef _LINUX_GETOPT_H
2#define _LINUX_GETOPT_H
3
4struct option {
5 const char *name;
6 unsigned long flag;
7 int val;
8};
9
10extern int smb_getopt(char *caller, char **options, struct option *opts,
11 char **optopt, char **optarg, unsigned long *flag,
12 unsigned long *value);
13
14#endif /* _LINUX_GETOPT_H */
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c
deleted file mode 100644
index 0778589d9e9..00000000000
--- a/drivers/staging/smbfs/inode.c
+++ /dev/null
@@ -1,854 +0,0 @@
1/*
2 * inode.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/module.h>
11#include <linux/time.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/string.h>
15#include <linux/stat.h>
16#include <linux/errno.h>
17#include <linux/slab.h>
18#include <linux/init.h>
19#include <linux/file.h>
20#include <linux/dcache.h>
21#include <linux/smp_lock.h>
22#include <linux/nls.h>
23#include <linux/seq_file.h>
24#include <linux/mount.h>
25#include <linux/net.h>
26#include <linux/vfs.h>
27#include <linux/highuid.h>
28#include <linux/sched.h>
29
30#include <asm/system.h>
31#include <asm/uaccess.h>
32
33#include "smb_fs.h"
34#include "smbno.h"
35#include "smb_mount.h"
36#include "smb_debug.h"
37#include "getopt.h"
38#include "proto.h"
39
40/* Always pick a default string */
41#ifdef CONFIG_SMB_NLS_REMOTE
42#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE
43#else
44#define SMB_NLS_REMOTE ""
45#endif
46
47#define SMB_TTL_DEFAULT 1000
48
49static void smb_evict_inode(struct inode *);
50static void smb_put_super(struct super_block *);
51static int smb_statfs(struct dentry *, struct kstatfs *);
52static int smb_show_options(struct seq_file *, struct vfsmount *);
53
54static struct kmem_cache *smb_inode_cachep;
55
56static struct inode *smb_alloc_inode(struct super_block *sb)
57{
58 struct smb_inode_info *ei;
59 ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, GFP_KERNEL);
60 if (!ei)
61 return NULL;
62 return &ei->vfs_inode;
63}
64
65static void smb_i_callback(struct rcu_head *head)
66{
67 struct inode *inode = container_of(head, struct inode, i_rcu);
68 INIT_LIST_HEAD(&inode->i_dentry);
69 kmem_cache_free(smb_inode_cachep, SMB_I(inode));
70}
71
72static void smb_destroy_inode(struct inode *inode)
73{
74 call_rcu(&inode->i_rcu, smb_i_callback);
75}
76
77static void init_once(void *foo)
78{
79 struct smb_inode_info *ei = (struct smb_inode_info *) foo;
80
81 inode_init_once(&ei->vfs_inode);
82}
83
84static int init_inodecache(void)
85{
86 smb_inode_cachep = kmem_cache_create("smb_inode_cache",
87 sizeof(struct smb_inode_info),
88 0, (SLAB_RECLAIM_ACCOUNT|
89 SLAB_MEM_SPREAD),
90 init_once);
91 if (smb_inode_cachep == NULL)
92 return -ENOMEM;
93 return 0;
94}
95
96static void destroy_inodecache(void)
97{
98 kmem_cache_destroy(smb_inode_cachep);
99}
100
101static int smb_remount(struct super_block *sb, int *flags, char *data)
102{
103 *flags |= MS_NODIRATIME;
104 return 0;
105}
106
107static const struct super_operations smb_sops =
108{
109 .alloc_inode = smb_alloc_inode,
110 .destroy_inode = smb_destroy_inode,
111 .drop_inode = generic_delete_inode,
112 .evict_inode = smb_evict_inode,
113 .put_super = smb_put_super,
114 .statfs = smb_statfs,
115 .show_options = smb_show_options,
116 .remount_fs = smb_remount,
117};
118
119
120/* We are always generating a new inode here */
121struct inode *
122smb_iget(struct super_block *sb, struct smb_fattr *fattr)
123{
124 struct smb_sb_info *server = SMB_SB(sb);
125 struct inode *result;
126
127 DEBUG1("smb_iget: %p\n", fattr);
128
129 result = new_inode(sb);
130 if (!result)
131 return result;
132 result->i_ino = fattr->f_ino;
133 SMB_I(result)->open = 0;
134 SMB_I(result)->fileid = 0;
135 SMB_I(result)->access = 0;
136 SMB_I(result)->flags = 0;
137 SMB_I(result)->closed = 0;
138 SMB_I(result)->openers = 0;
139 smb_set_inode_attr(result, fattr);
140 if (S_ISREG(result->i_mode)) {
141 result->i_op = &smb_file_inode_operations;
142 result->i_fop = &smb_file_operations;
143 result->i_data.a_ops = &smb_file_aops;
144 } else if (S_ISDIR(result->i_mode)) {
145 if (server->opt.capabilities & SMB_CAP_UNIX)
146 result->i_op = &smb_dir_inode_operations_unix;
147 else
148 result->i_op = &smb_dir_inode_operations;
149 result->i_fop = &smb_dir_operations;
150 } else if (S_ISLNK(result->i_mode)) {
151 result->i_op = &smb_link_inode_operations;
152 } else {
153 init_special_inode(result, result->i_mode, fattr->f_rdev);
154 }
155 insert_inode_hash(result);
156 return result;
157}
158
159/*
160 * Copy the inode data to a smb_fattr structure.
161 */
162void
163smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
164{
165 memset(fattr, 0, sizeof(struct smb_fattr));
166 fattr->f_mode = inode->i_mode;
167 fattr->f_nlink = inode->i_nlink;
168 fattr->f_ino = inode->i_ino;
169 fattr->f_uid = inode->i_uid;
170 fattr->f_gid = inode->i_gid;
171 fattr->f_size = inode->i_size;
172 fattr->f_mtime = inode->i_mtime;
173 fattr->f_ctime = inode->i_ctime;
174 fattr->f_atime = inode->i_atime;
175 fattr->f_blocks = inode->i_blocks;
176
177 fattr->attr = SMB_I(inode)->attr;
178 /*
179 * Keep the attributes in sync with the inode permissions.
180 */
181 if (fattr->f_mode & S_IWUSR)
182 fattr->attr &= ~aRONLY;
183 else
184 fattr->attr |= aRONLY;
185}
186
187/*
188 * Update the inode, possibly causing it to invalidate its pages if mtime/size
189 * is different from last time.
190 */
191void
192smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
193{
194 struct smb_inode_info *ei = SMB_I(inode);
195
196 /*
197 * A size change should have a different mtime, or same mtime
198 * but different size.
199 */
200 time_t last_time = inode->i_mtime.tv_sec;
201 loff_t last_sz = inode->i_size;
202
203 inode->i_mode = fattr->f_mode;
204 inode->i_nlink = fattr->f_nlink;
205 inode->i_uid = fattr->f_uid;
206 inode->i_gid = fattr->f_gid;
207 inode->i_ctime = fattr->f_ctime;
208 inode->i_blocks = fattr->f_blocks;
209 inode->i_size = fattr->f_size;
210 inode->i_mtime = fattr->f_mtime;
211 inode->i_atime = fattr->f_atime;
212 ei->attr = fattr->attr;
213
214 /*
215 * Update the "last time refreshed" field for revalidation.
216 */
217 ei->oldmtime = jiffies;
218
219 if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {
220 VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
221 inode->i_ino,
222 (long) last_time, (long) inode->i_mtime.tv_sec,
223 (long) last_sz, (long) inode->i_size);
224
225 if (!S_ISDIR(inode->i_mode))
226 invalidate_remote_inode(inode);
227 }
228}
229
230/*
231 * This is called if the connection has gone bad ...
232 * try to kill off all the current inodes.
233 */
234void
235smb_invalidate_inodes(struct smb_sb_info *server)
236{
237 VERBOSE("\n");
238 shrink_dcache_sb(SB_of(server));
239}
240
241/*
242 * This is called to update the inode attributes after
243 * we've made changes to a file or directory.
244 */
245static int
246smb_refresh_inode(struct dentry *dentry)
247{
248 struct inode *inode = dentry->d_inode;
249 int error;
250 struct smb_fattr fattr;
251
252 error = smb_proc_getattr(dentry, &fattr);
253 if (!error) {
254 smb_renew_times(dentry);
255 /*
256 * Check whether the type part of the mode changed,
257 * and don't update the attributes if it did.
258 *
259 * And don't dick with the root inode
260 */
261 if (inode->i_ino == 2)
262 return error;
263 if (S_ISLNK(inode->i_mode))
264 return error; /* VFS will deal with it */
265
266 if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {
267 smb_set_inode_attr(inode, &fattr);
268 } else {
269 /*
270 * Big trouble! The inode has become a new object,
271 * so any operations attempted on it are invalid.
272 *
273 * To limit damage, mark the inode as bad so that
274 * subsequent lookup validations will fail.
275 */
276 PARANOIA("%s/%s changed mode, %07o to %07o\n",
277 DENTRY_PATH(dentry),
278 inode->i_mode, fattr.f_mode);
279
280 fattr.f_mode = inode->i_mode; /* save mode */
281 make_bad_inode(inode);
282 inode->i_mode = fattr.f_mode; /* restore mode */
283 /*
284 * No need to worry about unhashing the dentry: the
285 * lookup validation will see that the inode is bad.
286 * But we do want to invalidate the caches ...
287 */
288 if (!S_ISDIR(inode->i_mode))
289 invalidate_remote_inode(inode);
290 else
291 smb_invalid_dir_cache(inode);
292 error = -EIO;
293 }
294 }
295 return error;
296}
297
298/*
299 * This is called when we want to check whether the inode
300 * has changed on the server. If it has changed, we must
301 * invalidate our local caches.
302 */
303int
304smb_revalidate_inode(struct dentry *dentry)
305{
306 struct smb_sb_info *s = server_from_dentry(dentry);
307 struct inode *inode = dentry->d_inode;
308 int error = 0;
309
310 DEBUG1("smb_revalidate_inode\n");
311 lock_kernel();
312
313 /*
314 * Check whether we've recently refreshed the inode.
315 */
316 if (time_before(jiffies, SMB_I(inode)->oldmtime + SMB_MAX_AGE(s))) {
317 VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
318 inode->i_ino, jiffies, SMB_I(inode)->oldmtime);
319 goto out;
320 }
321
322 error = smb_refresh_inode(dentry);
323out:
324 unlock_kernel();
325 return error;
326}
327
328/*
329 * This routine is called when i_nlink == 0 and i_count goes to 0.
330 * All blocking cleanup operations need to go here to avoid races.
331 */
332static void
333smb_evict_inode(struct inode *ino)
334{
335 DEBUG1("ino=%ld\n", ino->i_ino);
336 truncate_inode_pages(&ino->i_data, 0);
337 end_writeback(ino);
338 lock_kernel();
339 if (smb_close(ino))
340 PARANOIA("could not close inode %ld\n", ino->i_ino);
341 unlock_kernel();
342}
343
344static struct option opts[] = {
345 { "version", 0, 'v' },
346 { "win95", SMB_MOUNT_WIN95, 1 },
347 { "oldattr", SMB_MOUNT_OLDATTR, 1 },
348 { "dirattr", SMB_MOUNT_DIRATTR, 1 },
349 { "case", SMB_MOUNT_CASE, 1 },
350 { "uid", 0, 'u' },
351 { "gid", 0, 'g' },
352 { "file_mode", 0, 'f' },
353 { "dir_mode", 0, 'd' },
354 { "iocharset", 0, 'i' },
355 { "codepage", 0, 'c' },
356 { "ttl", 0, 't' },
357 { NULL, 0, 0}
358};
359
360static int
361parse_options(struct smb_mount_data_kernel *mnt, char *options)
362{
363 int c;
364 unsigned long flags;
365 unsigned long value;
366 char *optarg;
367 char *optopt;
368
369 flags = 0;
370 while ( (c = smb_getopt("smbfs", &options, opts,
371 &optopt, &optarg, &flags, &value)) > 0) {
372
373 VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
374 switch (c) {
375 case 1:
376 /* got a "flag" option */
377 break;
378 case 'v':
379 if (value != SMB_MOUNT_VERSION) {
380 printk ("smbfs: Bad mount version %ld, expected %d\n",
381 value, SMB_MOUNT_VERSION);
382 return 0;
383 }
384 mnt->version = value;
385 break;
386 case 'u':
387 mnt->uid = value;
388 flags |= SMB_MOUNT_UID;
389 break;
390 case 'g':
391 mnt->gid = value;
392 flags |= SMB_MOUNT_GID;
393 break;
394 case 'f':
395 mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
396 flags |= SMB_MOUNT_FMODE;
397 break;
398 case 'd':
399 mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
400 flags |= SMB_MOUNT_DMODE;
401 break;
402 case 'i':
403 strlcpy(mnt->codepage.local_name, optarg,
404 SMB_NLS_MAXNAMELEN);
405 break;
406 case 'c':
407 strlcpy(mnt->codepage.remote_name, optarg,
408 SMB_NLS_MAXNAMELEN);
409 break;
410 case 't':
411 mnt->ttl = value;
412 break;
413 default:
414 printk ("smbfs: Unrecognized mount option %s\n",
415 optopt);
416 return -1;
417 }
418 }
419 mnt->flags = flags;
420 return c;
421}
422
423/*
424 * smb_show_options() is for displaying mount options in /proc/mounts.
425 * It tries to avoid showing settings that were not changed from their
426 * defaults.
427 */
428static int
429smb_show_options(struct seq_file *s, struct vfsmount *m)
430{
431 struct smb_mount_data_kernel *mnt = SMB_SB(m->mnt_sb)->mnt;
432 int i;
433
434 for (i = 0; opts[i].name != NULL; i++)
435 if (mnt->flags & opts[i].flag)
436 seq_printf(s, ",%s", opts[i].name);
437
438 if (mnt->flags & SMB_MOUNT_UID)
439 seq_printf(s, ",uid=%d", mnt->uid);
440 if (mnt->flags & SMB_MOUNT_GID)
441 seq_printf(s, ",gid=%d", mnt->gid);
442 if (mnt->mounted_uid != 0)
443 seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
444
445 /*
446 * Defaults for file_mode and dir_mode are unknown to us; they
447 * depend on the current umask of the user doing the mount.
448 */
449 if (mnt->flags & SMB_MOUNT_FMODE)
450 seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
451 if (mnt->flags & SMB_MOUNT_DMODE)
452 seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
453
454 if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
455 seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
456 if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
457 seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
458
459 if (mnt->ttl != SMB_TTL_DEFAULT)
460 seq_printf(s, ",ttl=%d", mnt->ttl);
461
462 return 0;
463}
464
465static void
466smb_unload_nls(struct smb_sb_info *server)
467{
468 unload_nls(server->remote_nls);
469 unload_nls(server->local_nls);
470}
471
472static void
473smb_put_super(struct super_block *sb)
474{
475 struct smb_sb_info *server = SMB_SB(sb);
476
477 lock_kernel();
478
479 smb_lock_server(server);
480 server->state = CONN_INVALID;
481 smbiod_unregister_server(server);
482
483 smb_close_socket(server);
484
485 if (server->conn_pid)
486 kill_pid(server->conn_pid, SIGTERM, 1);
487
488 bdi_destroy(&server->bdi);
489 kfree(server->ops);
490 smb_unload_nls(server);
491 sb->s_fs_info = NULL;
492 smb_unlock_server(server);
493 put_pid(server->conn_pid);
494 kfree(server);
495
496 unlock_kernel();
497}
498
499static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
500{
501 struct smb_sb_info *server;
502 struct smb_mount_data_kernel *mnt;
503 struct smb_mount_data *oldmnt;
504 struct inode *root_inode;
505 struct smb_fattr root;
506 int ver;
507 void *mem;
508 static int warn_count;
509
510 lock_kernel();
511
512 if (warn_count < 5) {
513 warn_count++;
514 printk(KERN_EMERG "smbfs is deprecated and will be removed"
515 " from the 2.6.37 kernel. Please migrate to cifs\n");
516 }
517
518 if (!raw_data)
519 goto out_no_data;
520
521 oldmnt = (struct smb_mount_data *) raw_data;
522 ver = oldmnt->version;
523 if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
524 goto out_wrong_data;
525
526 sb->s_flags |= MS_NODIRATIME;
527 sb->s_blocksize = 1024; /* Eh... Is this correct? */
528 sb->s_blocksize_bits = 10;
529 sb->s_magic = SMB_SUPER_MAGIC;
530 sb->s_op = &smb_sops;
531 sb->s_time_gran = 100;
532
533 server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
534 if (!server)
535 goto out_no_server;
536 sb->s_fs_info = server;
537
538 if (bdi_setup_and_register(&server->bdi, "smbfs", BDI_CAP_MAP_COPY))
539 goto out_bdi;
540
541 sb->s_bdi = &server->bdi;
542
543 server->super_block = sb;
544 server->mnt = NULL;
545 server->sock_file = NULL;
546 init_waitqueue_head(&server->conn_wq);
547 sema_init(&server->sem, 1);
548 INIT_LIST_HEAD(&server->entry);
549 INIT_LIST_HEAD(&server->xmitq);
550 INIT_LIST_HEAD(&server->recvq);
551 server->conn_error = 0;
552 server->conn_pid = NULL;
553 server->state = CONN_INVALID; /* no connection yet */
554 server->generation = 0;
555
556 /* Allocate the global temp buffer and some superblock helper structs */
557 /* FIXME: move these to the smb_sb_info struct */
558 VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) +
559 sizeof(struct smb_mount_data_kernel));
560 mem = kmalloc(sizeof(struct smb_ops) +
561 sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
562 if (!mem)
563 goto out_no_mem;
564
565 server->ops = mem;
566 smb_install_null_ops(server->ops);
567 server->mnt = mem + sizeof(struct smb_ops);
568
569 /* Setup NLS stuff */
570 server->remote_nls = NULL;
571 server->local_nls = NULL;
572
573 mnt = server->mnt;
574
575 memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
576 strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
577 SMB_NLS_MAXNAMELEN);
578 strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
579 SMB_NLS_MAXNAMELEN);
580
581 mnt->ttl = SMB_TTL_DEFAULT;
582 if (ver == SMB_MOUNT_OLDVERSION) {
583 mnt->version = oldmnt->version;
584
585 SET_UID(mnt->uid, oldmnt->uid);
586 SET_GID(mnt->gid, oldmnt->gid);
587
588 mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
589 mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
590
591 mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
592 SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
593 } else {
594 mnt->file_mode = S_IRWXU | S_IRGRP | S_IXGRP |
595 S_IROTH | S_IXOTH | S_IFREG;
596 mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
597 S_IROTH | S_IXOTH | S_IFDIR;
598 if (parse_options(mnt, raw_data))
599 goto out_bad_option;
600 }
601 mnt->mounted_uid = current_uid();
602 smb_setcodepage(server, &mnt->codepage);
603
604 /*
605 * Display the enabled options
606 * Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
607 */
608 if (mnt->flags & SMB_MOUNT_OLDATTR)
609 printk("SMBFS: Using core getattr (Win 95 speedup)\n");
610 else if (mnt->flags & SMB_MOUNT_DIRATTR)
611 printk("SMBFS: Using dir ff getattr\n");
612
613 if (smbiod_register_server(server) < 0) {
614 printk(KERN_ERR "smbfs: failed to start smbiod\n");
615 goto out_no_smbiod;
616 }
617 if (server->mnt->flags & SMB_MOUNT_CASE)
618 sb->s_d_op = &smbfs_dentry_operations_case;
619 else
620 sb->s_d_op = &smbfs_dentry_operations;
621
622 /*
623 * Keep the super block locked while we get the root inode.
624 */
625 smb_init_root_dirent(server, &root, sb);
626 root_inode = smb_iget(sb, &root);
627 if (!root_inode)
628 goto out_no_root;
629
630 sb->s_root = d_alloc_root(root_inode);
631 if (!sb->s_root)
632 goto out_no_root;
633
634 smb_new_dentry(sb->s_root);
635
636 unlock_kernel();
637 return 0;
638
639out_no_root:
640 iput(root_inode);
641out_no_smbiod:
642 smb_unload_nls(server);
643out_bad_option:
644 kfree(mem);
645out_no_mem:
646 bdi_destroy(&server->bdi);
647out_bdi:
648 if (!server->mnt)
649 printk(KERN_ERR "smb_fill_super: allocation failure\n");
650 sb->s_fs_info = NULL;
651 kfree(server);
652 goto out_fail;
653out_wrong_data:
654 printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
655 goto out_fail;
656out_no_data:
657 printk(KERN_ERR "smb_fill_super: missing data argument\n");
658out_fail:
659 unlock_kernel();
660 return -EINVAL;
661out_no_server:
662 printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n");
663 unlock_kernel();
664 return -ENOMEM;
665}
666
667static int
668smb_statfs(struct dentry *dentry, struct kstatfs *buf)
669{
670 int result;
671
672 lock_kernel();
673
674 result = smb_proc_dskattr(dentry, buf);
675
676 unlock_kernel();
677
678 buf->f_type = SMB_SUPER_MAGIC;
679 buf->f_namelen = SMB_MAXPATHLEN;
680 return result;
681}
682
683int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
684{
685 int err = smb_revalidate_inode(dentry);
686 if (!err)
687 generic_fillattr(dentry->d_inode, stat);
688 return err;
689}
690
691int
692smb_notify_change(struct dentry *dentry, struct iattr *attr)
693{
694 struct inode *inode = dentry->d_inode;
695 struct smb_sb_info *server = server_from_dentry(dentry);
696 unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
697 int error, changed, refresh = 0;
698 struct smb_fattr fattr;
699
700 lock_kernel();
701
702 error = smb_revalidate_inode(dentry);
703 if (error)
704 goto out;
705
706 if ((error = inode_change_ok(inode, attr)) < 0)
707 goto out;
708
709 error = -EPERM;
710 if ((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->mnt->uid))
711 goto out;
712
713 if ((attr->ia_valid & ATTR_GID) && (attr->ia_uid != server->mnt->gid))
714 goto out;
715
716 if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
717 goto out;
718
719 if ((attr->ia_valid & ATTR_SIZE) != 0) {
720 VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
721 DENTRY_PATH(dentry),
722 (long) inode->i_size, (long) attr->ia_size);
723
724 filemap_write_and_wait(inode->i_mapping);
725
726 error = smb_open(dentry, O_WRONLY);
727 if (error)
728 goto out;
729 error = server->ops->truncate(inode, attr->ia_size);
730 if (error)
731 goto out;
732 truncate_setsize(inode, attr->ia_size);
733 refresh = 1;
734 }
735
736 if (server->opt.capabilities & SMB_CAP_UNIX) {
737 /* For now we don't want to set the size with setattr_unix */
738 attr->ia_valid &= ~ATTR_SIZE;
739 /* FIXME: only call if we actually want to set something? */
740 error = smb_proc_setattr_unix(dentry, attr, 0, 0);
741 if (!error)
742 refresh = 1;
743
744 goto out;
745 }
746
747 /*
748 * Initialize the fattr and check for changed fields.
749 * Note: CTIME under SMB is creation time rather than
750 * change time, so we don't attempt to change it.
751 */
752 smb_get_inode_attr(inode, &fattr);
753
754 changed = 0;
755 if ((attr->ia_valid & ATTR_MTIME) != 0) {
756 fattr.f_mtime = attr->ia_mtime;
757 changed = 1;
758 }
759 if ((attr->ia_valid & ATTR_ATIME) != 0) {
760 fattr.f_atime = attr->ia_atime;
761 /* Earlier protocols don't have an access time */
762 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
763 changed = 1;
764 }
765 if (changed) {
766 error = smb_proc_settime(dentry, &fattr);
767 if (error)
768 goto out;
769 refresh = 1;
770 }
771
772 /*
773 * Check for mode changes ... we're extremely limited in
774 * what can be set for SMB servers: just the read-only bit.
775 */
776 if ((attr->ia_valid & ATTR_MODE) != 0) {
777 VERBOSE("%s/%s mode change, old=%x, new=%x\n",
778 DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
779 changed = 0;
780 if (attr->ia_mode & S_IWUSR) {
781 if (fattr.attr & aRONLY) {
782 fattr.attr &= ~aRONLY;
783 changed = 1;
784 }
785 } else {
786 if (!(fattr.attr & aRONLY)) {
787 fattr.attr |= aRONLY;
788 changed = 1;
789 }
790 }
791 if (changed) {
792 error = smb_proc_setattr(dentry, &fattr);
793 if (error)
794 goto out;
795 refresh = 1;
796 }
797 }
798 error = 0;
799
800out:
801 if (refresh)
802 smb_refresh_inode(dentry);
803 unlock_kernel();
804 return error;
805}
806
807static struct dentry *smb_mount(struct file_system_type *fs_type,
808 int flags, const char *dev_name, void *data)
809{
810 return mount_nodev(fs_type, flags, data, smb_fill_super);
811}
812
813static struct file_system_type smb_fs_type = {
814 .owner = THIS_MODULE,
815 .name = "smbfs",
816 .mount = smb_mount,
817 .kill_sb = kill_anon_super,
818 .fs_flags = FS_BINARY_MOUNTDATA,
819};
820
821static int __init init_smb_fs(void)
822{
823 int err;
824 DEBUG1("registering ...\n");
825
826 err = init_inodecache();
827 if (err)
828 goto out_inode;
829 err = smb_init_request_cache();
830 if (err)
831 goto out_request;
832 err = register_filesystem(&smb_fs_type);
833 if (err)
834 goto out;
835 return 0;
836out:
837 smb_destroy_request_cache();
838out_request:
839 destroy_inodecache();
840out_inode:
841 return err;
842}
843
844static void __exit exit_smb_fs(void)
845{
846 DEBUG1("unregistering ...\n");
847 unregister_filesystem(&smb_fs_type);
848 smb_destroy_request_cache();
849 destroy_inodecache();
850}
851
852module_init(init_smb_fs)
853module_exit(exit_smb_fs)
854MODULE_LICENSE("GPL");
diff --git a/drivers/staging/smbfs/ioctl.c b/drivers/staging/smbfs/ioctl.c
deleted file mode 100644
index 2da16926747..00000000000
--- a/drivers/staging/smbfs/ioctl.c
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * ioctl.c
3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/errno.h>
11#include <linux/fs.h>
12#include <linux/ioctl.h>
13#include <linux/time.h>
14#include <linux/mm.h>
15#include <linux/highuid.h>
16#include <linux/smp_lock.h>
17#include <linux/net.h>
18
19#include <asm/uaccess.h>
20
21#include "smb_fs.h"
22#include "smb_mount.h"
23#include "proto.h"
24
25long
26smb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
27{
28 struct smb_sb_info *server = server_from_inode(filp->f_path.dentry->d_inode);
29 struct smb_conn_opt opt;
30 int result = -EINVAL;
31
32 lock_kernel();
33 switch (cmd) {
34 uid16_t uid16;
35 uid_t uid32;
36 case SMB_IOC_GETMOUNTUID:
37 SET_UID(uid16, server->mnt->mounted_uid);
38 result = put_user(uid16, (uid16_t __user *) arg);
39 break;
40 case SMB_IOC_GETMOUNTUID32:
41 SET_UID(uid32, server->mnt->mounted_uid);
42 result = put_user(uid32, (uid_t __user *) arg);
43 break;
44
45 case SMB_IOC_NEWCONN:
46 /* arg is smb_conn_opt, or NULL if no connection was made */
47 if (!arg) {
48 result = 0;
49 smb_lock_server(server);
50 server->state = CONN_RETRIED;
51 printk(KERN_ERR "Connection attempt failed! [%d]\n",
52 server->conn_error);
53 smbiod_flush(server);
54 smb_unlock_server(server);
55 break;
56 }
57
58 result = -EFAULT;
59 if (!copy_from_user(&opt, (void __user *)arg, sizeof(opt)))
60 result = smb_newconn(server, &opt);
61 break;
62 default:
63 break;
64 }
65 unlock_kernel();
66
67 return result;
68}
diff --git a/drivers/staging/smbfs/proc.c b/drivers/staging/smbfs/proc.c
deleted file mode 100644
index ba37b1fae18..00000000000
--- a/drivers/staging/smbfs/proc.c
+++ /dev/null
@@ -1,3502 +0,0 @@
1/*
2 * proc.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/types.h>
11#include <linux/capability.h>
12#include <linux/errno.h>
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/file.h>
16#include <linux/stat.h>
17#include <linux/fcntl.h>
18#include <linux/dcache.h>
19#include <linux/nls.h>
20#include <linux/smp_lock.h>
21#include <linux/net.h>
22#include <linux/vfs.h>
23#include <net/sock.h>
24
25#include <asm/string.h>
26#include <asm/div64.h>
27
28#include "smb_fs.h"
29#include "smbno.h"
30#include "smb_mount.h"
31#include "smb_debug.h"
32#include "proto.h"
33#include "request.h"
34
35
36/* Features. Undefine if they cause problems, this should perhaps be a
37 config option. */
38#define SMBFS_POSIX_UNLINK 1
39
40/* Allow smb_retry to be interrupted. */
41#define SMB_RETRY_INTR
42
43#define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
44#define SMB_CMD(packet) (*(packet+8))
45#define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1))
46
47#define SMB_DIRINFO_SIZE 43
48#define SMB_STATUS_SIZE 21
49
50#define SMB_ST_BLKSIZE (PAGE_SIZE)
51#define SMB_ST_BLKSHIFT (PAGE_SHIFT)
52
53static struct smb_ops smb_ops_core;
54static struct smb_ops smb_ops_os2;
55static struct smb_ops smb_ops_win95;
56static struct smb_ops smb_ops_winNT;
57static struct smb_ops smb_ops_unix;
58static struct smb_ops smb_ops_null;
59
60static void
61smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
62static void
63smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
64static int
65smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
66 struct smb_fattr *fattr);
67static int
68smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
69 struct smb_fattr *fattr);
70static int
71smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
72 u16 attr);
73static int
74smb_proc_setattr_ext(struct smb_sb_info *server,
75 struct inode *inode, struct smb_fattr *fattr);
76static int
77smb_proc_query_cifsunix(struct smb_sb_info *server);
78static void
79install_ops(struct smb_ops *dst, struct smb_ops *src);
80
81
82static void
83str_upper(char *name, int len)
84{
85 while (len--)
86 {
87 if (*name >= 'a' && *name <= 'z')
88 *name -= ('a' - 'A');
89 name++;
90 }
91}
92
93#if 0
94static void
95str_lower(char *name, int len)
96{
97 while (len--)
98 {
99 if (*name >= 'A' && *name <= 'Z')
100 *name += ('a' - 'A');
101 name++;
102 }
103}
104#endif
105
106/* reverse a string inline. This is used by the dircache walking routines */
107static void reverse_string(char *buf, int len)
108{
109 char c;
110 char *end = buf+len-1;
111
112 while(buf < end) {
113 c = *buf;
114 *(buf++) = *end;
115 *(end--) = c;
116 }
117}
118
119/* no conversion, just a wrapper for memcpy. */
120static int convert_memcpy(unsigned char *output, int olen,
121 const unsigned char *input, int ilen,
122 struct nls_table *nls_from,
123 struct nls_table *nls_to)
124{
125 if (olen < ilen)
126 return -ENAMETOOLONG;
127 memcpy(output, input, ilen);
128 return ilen;
129}
130
131static inline int write_char(unsigned char ch, char *output, int olen)
132{
133 if (olen < 4)
134 return -ENAMETOOLONG;
135 sprintf(output, ":x%02x", ch);
136 return 4;
137}
138
139static inline int write_unichar(wchar_t ch, char *output, int olen)
140{
141 if (olen < 5)
142 return -ENAMETOOLONG;
143 sprintf(output, ":%04x", ch);
144 return 5;
145}
146
147/* convert from one "codepage" to another (possibly being utf8). */
148static int convert_cp(unsigned char *output, int olen,
149 const unsigned char *input, int ilen,
150 struct nls_table *nls_from,
151 struct nls_table *nls_to)
152{
153 int len = 0;
154 int n;
155 wchar_t ch;
156
157 while (ilen > 0) {
158 /* convert by changing to unicode and back to the new cp */
159 n = nls_from->char2uni(input, ilen, &ch);
160 if (n == -EINVAL) {
161 ilen--;
162 n = write_char(*input++, output, olen);
163 if (n < 0)
164 goto fail;
165 output += n;
166 olen -= n;
167 len += n;
168 continue;
169 } else if (n < 0)
170 goto fail;
171 input += n;
172 ilen -= n;
173
174 n = nls_to->uni2char(ch, output, olen);
175 if (n == -EINVAL)
176 n = write_unichar(ch, output, olen);
177 if (n < 0)
178 goto fail;
179 output += n;
180 olen -= n;
181
182 len += n;
183 }
184 return len;
185fail:
186 return n;
187}
188
189/* ----------------------------------------------------------- */
190
191/*
192 * nls_unicode
193 *
194 * This encodes/decodes little endian unicode format
195 */
196
197static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
198{
199 if (boundlen < 2)
200 return -EINVAL;
201 *out++ = uni & 0xff;
202 *out++ = uni >> 8;
203 return 2;
204}
205
206static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
207{
208 if (boundlen < 2)
209 return -EINVAL;
210 *uni = (rawstring[1] << 8) | rawstring[0];
211 return 2;
212}
213
214static struct nls_table unicode_table = {
215 .charset = "unicode",
216 .uni2char = uni2char,
217 .char2uni = char2uni,
218};
219
220/* ----------------------------------------------------------- */
221
222static int setcodepage(struct nls_table **p, char *name)
223{
224 struct nls_table *nls;
225
226 if (!name || !*name) {
227 nls = NULL;
228 } else if ( (nls = load_nls(name)) == NULL) {
229 printk (KERN_ERR "smbfs: failed to load nls '%s'\n", name);
230 return -EINVAL;
231 }
232
233 /* if already set, unload the previous one. */
234 if (*p && *p != &unicode_table)
235 unload_nls(*p);
236 *p = nls;
237
238 return 0;
239}
240
241/* Handles all changes to codepage settings. */
242int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
243{
244 int n = 0;
245
246 smb_lock_server(server);
247
248 /* Don't load any nls_* at all, if no remote is requested */
249 if (!*cp->remote_name)
250 goto out;
251
252 /* local */
253 n = setcodepage(&server->local_nls, cp->local_name);
254 if (n != 0)
255 goto out;
256
257 /* remote */
258 if (!strcmp(cp->remote_name, "unicode")) {
259 server->remote_nls = &unicode_table;
260 } else {
261 n = setcodepage(&server->remote_nls, cp->remote_name);
262 if (n != 0)
263 setcodepage(&server->local_nls, NULL);
264 }
265
266out:
267 if (server->local_nls != NULL && server->remote_nls != NULL)
268 server->ops->convert = convert_cp;
269 else
270 server->ops->convert = convert_memcpy;
271
272 smb_unlock_server(server);
273 return n;
274}
275
276
277/*****************************************************************************/
278/* */
279/* Encoding/Decoding section */
280/* */
281/*****************************************************************************/
282
283static __u8 *
284smb_encode_smb_length(__u8 * p, __u32 len)
285{
286 *p = 0;
287 *(p+1) = 0;
288 *(p+2) = (len & 0xFF00) >> 8;
289 *(p+3) = (len & 0xFF);
290 if (len > 0xFFFF)
291 {
292 *(p+1) = 1;
293 }
294 return p + 4;
295}
296
297/*
298 * smb_build_path: build the path to entry and name storing it in buf.
299 * The path returned will have the trailing '\0'.
300 */
301static int smb_build_path(struct smb_sb_info *server, unsigned char *buf,
302 int maxlen,
303 struct dentry *entry, struct qstr *name)
304{
305 unsigned char *path = buf;
306 int len;
307 int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE) != 0;
308
309 if (maxlen < (2<<unicode))
310 return -ENAMETOOLONG;
311
312 if (maxlen > SMB_MAXPATHLEN + 1)
313 maxlen = SMB_MAXPATHLEN + 1;
314
315 if (entry == NULL)
316 goto test_name_and_out;
317
318 /*
319 * If IS_ROOT, we have to do no walking at all.
320 */
321 if (IS_ROOT(entry) && !name) {
322 *path++ = '\\';
323 if (unicode) *path++ = '\0';
324 *path++ = '\0';
325 if (unicode) *path++ = '\0';
326 return path-buf;
327 }
328
329 /*
330 * Build the path string walking the tree backward from end to ROOT
331 * and store it in reversed order [see reverse_string()]
332 */
333 dget(entry);
334 while (!IS_ROOT(entry)) {
335 struct dentry *parent;
336
337 if (maxlen < (3<<unicode)) {
338 dput(entry);
339 return -ENAMETOOLONG;
340 }
341
342 spin_lock(&entry->d_lock);
343 len = server->ops->convert(path, maxlen-2,
344 entry->d_name.name, entry->d_name.len,
345 server->local_nls, server->remote_nls);
346 if (len < 0) {
347 spin_unlock(&entry->d_lock);
348 dput(entry);
349 return len;
350 }
351 reverse_string(path, len);
352 path += len;
353 if (unicode) {
354 /* Note: reverse order */
355 *path++ = '\0';
356 maxlen--;
357 }
358 *path++ = '\\';
359 maxlen -= len+1;
360 spin_unlock(&entry->d_lock);
361
362 parent = dget_parent(entry);
363 dput(entry);
364 entry = parent;
365 }
366 dput(entry);
367 reverse_string(buf, path-buf);
368
369 /* maxlen has space for at least one char */
370test_name_and_out:
371 if (name) {
372 if (maxlen < (3<<unicode))
373 return -ENAMETOOLONG;
374 *path++ = '\\';
375 if (unicode) {
376 *path++ = '\0';
377 maxlen--;
378 }
379 len = server->ops->convert(path, maxlen-2,
380 name->name, name->len,
381 server->local_nls, server->remote_nls);
382 if (len < 0)
383 return len;
384 path += len;
385 maxlen -= len+1;
386 }
387 /* maxlen has space for at least one char */
388 *path++ = '\0';
389 if (unicode) *path++ = '\0';
390 return path-buf;
391}
392
393static int smb_encode_path(struct smb_sb_info *server, char *buf, int maxlen,
394 struct dentry *dir, struct qstr *name)
395{
396 int result;
397
398 result = smb_build_path(server, buf, maxlen, dir, name);
399 if (result < 0)
400 goto out;
401 if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
402 str_upper(buf, result);
403out:
404 return result;
405}
406
407/* encode_path for non-trans2 request SMBs */
408static int smb_simple_encode_path(struct smb_request *req, char **p,
409 struct dentry * entry, struct qstr * name)
410{
411 struct smb_sb_info *server = req->rq_server;
412 char *s = *p;
413 int res;
414 int maxlen = ((char *)req->rq_buffer + req->rq_bufsize) - s;
415 int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE);
416
417 if (!maxlen)
418 return -ENAMETOOLONG;
419 *s++ = 4; /* ASCII data format */
420
421 /*
422 * SMB Unicode strings must be 16bit aligned relative the start of the
423 * packet. If they are not they must be padded with 0.
424 */
425 if (unicode) {
426 int align = s - (char *)req->rq_buffer;
427 if (!(align & 1)) {
428 *s++ = '\0';
429 maxlen--;
430 }
431 }
432
433 res = smb_encode_path(server, s, maxlen-1, entry, name);
434 if (res < 0)
435 return res;
436 *p = s + res;
437 return 0;
438}
439
440/* The following are taken directly from msdos-fs */
441
442/* Linear day numbers of the respective 1sts in non-leap years. */
443
444static int day_n[] =
445{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
446 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
447
448
449static time_t
450utc2local(struct smb_sb_info *server, time_t time)
451{
452 return time - server->opt.serverzone*60;
453}
454
455static time_t
456local2utc(struct smb_sb_info *server, time_t time)
457{
458 return time + server->opt.serverzone*60;
459}
460
461/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
462
463static time_t
464date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
465{
466 int month, year;
467 time_t secs;
468
469 /* first subtract and mask after that... Otherwise, if
470 date == 0, bad things happen */
471 month = ((date >> 5) - 1) & 15;
472 year = date >> 9;
473 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
474 ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
475 month < 2 ? 1 : 0) + 3653);
476 /* days since 1.1.70 plus 80's leap day */
477 return local2utc(server, secs);
478}
479
480
481/* Convert linear UNIX date to a MS-DOS time/date pair. */
482
483static void
484date_unix2dos(struct smb_sb_info *server,
485 int unix_date, __u16 *date, __u16 *time)
486{
487 int day, year, nl_day, month;
488
489 unix_date = utc2local(server, unix_date);
490 if (unix_date < 315532800)
491 unix_date = 315532800;
492
493 *time = (unix_date % 60) / 2 +
494 (((unix_date / 60) % 60) << 5) +
495 (((unix_date / 3600) % 24) << 11);
496
497 day = unix_date / 86400 - 3652;
498 year = day / 365;
499 if ((year + 3) / 4 + 365 * year > day)
500 year--;
501 day -= (year + 3) / 4 + 365 * year;
502 if (day == 59 && !(year & 3)) {
503 nl_day = day;
504 month = 2;
505 } else {
506 nl_day = (year & 3) || day <= 59 ? day : day - 1;
507 for (month = 1; month < 12; month++)
508 if (day_n[month] > nl_day)
509 break;
510 }
511 *date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
512}
513
514/* The following are taken from fs/ntfs/util.c */
515
516#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
517
518/*
519 * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
520 * into Unix UTC (based 1970-01-01, in seconds).
521 */
522static struct timespec
523smb_ntutc2unixutc(u64 ntutc)
524{
525 struct timespec ts;
526 /* FIXME: what about the timezone difference? */
527 /* Subtract the NTFS time offset, then convert to 1s intervals. */
528 u64 t = ntutc - NTFS_TIME_OFFSET;
529 ts.tv_nsec = do_div(t, 10000000) * 100;
530 ts.tv_sec = t;
531 return ts;
532}
533
534/* Convert the Unix UTC into NT time */
535static u64
536smb_unixutc2ntutc(struct timespec ts)
537{
538 /* Note: timezone conversion is probably wrong. */
539 /* return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET; */
540 return ((u64)ts.tv_sec) * 10000000 + ts.tv_nsec/100 + NTFS_TIME_OFFSET;
541}
542
543#define MAX_FILE_MODE 6
544static mode_t file_mode[] = {
545 S_IFREG, S_IFDIR, S_IFLNK, S_IFCHR, S_IFBLK, S_IFIFO, S_IFSOCK
546};
547
548static int smb_filetype_to_mode(u32 filetype)
549{
550 if (filetype > MAX_FILE_MODE) {
551 PARANOIA("Filetype out of range: %d\n", filetype);
552 return S_IFREG;
553 }
554 return file_mode[filetype];
555}
556
557static u32 smb_filetype_from_mode(int mode)
558{
559 if (S_ISREG(mode))
560 return UNIX_TYPE_FILE;
561 if (S_ISDIR(mode))
562 return UNIX_TYPE_DIR;
563 if (S_ISLNK(mode))
564 return UNIX_TYPE_SYMLINK;
565 if (S_ISCHR(mode))
566 return UNIX_TYPE_CHARDEV;
567 if (S_ISBLK(mode))
568 return UNIX_TYPE_BLKDEV;
569 if (S_ISFIFO(mode))
570 return UNIX_TYPE_FIFO;
571 if (S_ISSOCK(mode))
572 return UNIX_TYPE_SOCKET;
573 return UNIX_TYPE_UNKNOWN;
574}
575
576
577/*****************************************************************************/
578/* */
579/* Support section. */
580/* */
581/*****************************************************************************/
582
583__u32
584smb_len(__u8 * p)
585{
586 return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3);
587}
588
589static __u16
590smb_bcc(__u8 * packet)
591{
592 int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16);
593 return WVAL(packet, pos);
594}
595
596/* smb_valid_packet: We check if packet fulfills the basic
597 requirements of a smb packet */
598
599static int
600smb_valid_packet(__u8 * packet)
601{
602 return (packet[4] == 0xff
603 && packet[5] == 'S'
604 && packet[6] == 'M'
605 && packet[7] == 'B'
606 && (smb_len(packet) + 4 == SMB_HEADER_LEN
607 + SMB_WCT(packet) * 2 + smb_bcc(packet)));
608}
609
610/* smb_verify: We check if we got the answer we expected, and if we
611 got enough data. If bcc == -1, we don't care. */
612
613static int
614smb_verify(__u8 * packet, int command, int wct, int bcc)
615{
616 if (SMB_CMD(packet) != command)
617 goto bad_command;
618 if (SMB_WCT(packet) < wct)
619 goto bad_wct;
620 if (bcc != -1 && smb_bcc(packet) < bcc)
621 goto bad_bcc;
622 return 0;
623
624bad_command:
625 printk(KERN_ERR "smb_verify: command=%x, SMB_CMD=%x??\n",
626 command, SMB_CMD(packet));
627 goto fail;
628bad_wct:
629 printk(KERN_ERR "smb_verify: command=%x, wct=%d, SMB_WCT=%d??\n",
630 command, wct, SMB_WCT(packet));
631 goto fail;
632bad_bcc:
633 printk(KERN_ERR "smb_verify: command=%x, bcc=%d, SMB_BCC=%d??\n",
634 command, bcc, smb_bcc(packet));
635fail:
636 return -EIO;
637}
638
639/*
640 * Returns the maximum read or write size for the "payload". Making all of the
641 * packet fit within the negotiated max_xmit size.
642 *
643 * N.B. Since this value is usually computed before locking the server,
644 * the server's packet size must never be decreased!
645 */
646static inline int
647smb_get_xmitsize(struct smb_sb_info *server, int overhead)
648{
649 return server->opt.max_xmit - overhead;
650}
651
652/*
653 * Calculate the maximum read size
654 */
655int
656smb_get_rsize(struct smb_sb_info *server)
657{
658 /* readX has 12 parameters, read has 5 */
659 int overhead = SMB_HEADER_LEN + 12 * sizeof(__u16) + 2 + 1 + 2;
660 int size = smb_get_xmitsize(server, overhead);
661
662 VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);
663
664 return size;
665}
666
667/*
668 * Calculate the maximum write size
669 */
670int
671smb_get_wsize(struct smb_sb_info *server)
672{
673 /* writeX has 14 parameters, write has 5 */
674 int overhead = SMB_HEADER_LEN + 14 * sizeof(__u16) + 2 + 1 + 2;
675 int size = smb_get_xmitsize(server, overhead);
676
677 VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);
678
679 return size;
680}
681
682/*
683 * Convert SMB error codes to -E... errno values.
684 */
685int
686smb_errno(struct smb_request *req)
687{
688 int errcls = req->rq_rcls;
689 int error = req->rq_err;
690 char *class = "Unknown";
691
692 VERBOSE("errcls %d code %d from command 0x%x\n",
693 errcls, error, SMB_CMD(req->rq_header));
694
695 if (errcls == ERRDOS) {
696 switch (error) {
697 case ERRbadfunc:
698 return -EINVAL;
699 case ERRbadfile:
700 case ERRbadpath:
701 return -ENOENT;
702 case ERRnofids:
703 return -EMFILE;
704 case ERRnoaccess:
705 return -EACCES;
706 case ERRbadfid:
707 return -EBADF;
708 case ERRbadmcb:
709 return -EREMOTEIO;
710 case ERRnomem:
711 return -ENOMEM;
712 case ERRbadmem:
713 return -EFAULT;
714 case ERRbadenv:
715 case ERRbadformat:
716 return -EREMOTEIO;
717 case ERRbadaccess:
718 return -EACCES;
719 case ERRbaddata:
720 return -E2BIG;
721 case ERRbaddrive:
722 return -ENXIO;
723 case ERRremcd:
724 return -EREMOTEIO;
725 case ERRdiffdevice:
726 return -EXDEV;
727 case ERRnofiles:
728 return -ENOENT;
729 case ERRbadshare:
730 return -ETXTBSY;
731 case ERRlock:
732 return -EDEADLK;
733 case ERRfilexists:
734 return -EEXIST;
735 case ERROR_INVALID_PARAMETER:
736 return -EINVAL;
737 case ERROR_DISK_FULL:
738 return -ENOSPC;
739 case ERROR_INVALID_NAME:
740 return -ENOENT;
741 case ERROR_DIR_NOT_EMPTY:
742 return -ENOTEMPTY;
743 case ERROR_NOT_LOCKED:
744 return -ENOLCK;
745 case ERROR_ALREADY_EXISTS:
746 return -EEXIST;
747 default:
748 class = "ERRDOS";
749 goto err_unknown;
750 }
751 } else if (errcls == ERRSRV) {
752 switch (error) {
753 /* N.B. This is wrong ... EIO ? */
754 case ERRerror:
755 return -ENFILE;
756 case ERRbadpw:
757 return -EINVAL;
758 case ERRbadtype:
759 case ERRtimeout:
760 return -EIO;
761 case ERRaccess:
762 return -EACCES;
763 /*
764 * This is a fatal error, as it means the "tree ID"
765 * for this connection is no longer valid. We map
766 * to a special error code and get a new connection.
767 */
768 case ERRinvnid:
769 return -EBADSLT;
770 default:
771 class = "ERRSRV";
772 goto err_unknown;
773 }
774 } else if (errcls == ERRHRD) {
775 switch (error) {
776 case ERRnowrite:
777 return -EROFS;
778 case ERRbadunit:
779 return -ENODEV;
780 case ERRnotready:
781 return -EUCLEAN;
782 case ERRbadcmd:
783 case ERRdata:
784 return -EIO;
785 case ERRbadreq:
786 return -ERANGE;
787 case ERRbadshare:
788 return -ETXTBSY;
789 case ERRlock:
790 return -EDEADLK;
791 case ERRdiskfull:
792 return -ENOSPC;
793 default:
794 class = "ERRHRD";
795 goto err_unknown;
796 }
797 } else if (errcls == ERRCMD) {
798 class = "ERRCMD";
799 } else if (errcls == SUCCESS) {
800 return 0; /* This is the only valid 0 return */
801 }
802
803err_unknown:
804 printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",
805 class, error, SMB_CMD(req->rq_header));
806 return -EIO;
807}
808
809/* smb_request_ok: We expect the server to be locked. Then we do the
810 request and check the answer completely. When smb_request_ok
811 returns 0, you can be quite sure that everything went well. When
812 the answer is <=0, the returned number is a valid unix errno. */
813
814static int
815smb_request_ok(struct smb_request *req, int command, int wct, int bcc)
816{
817 int result;
818
819 req->rq_resp_wct = wct;
820 req->rq_resp_bcc = bcc;
821
822 result = smb_add_request(req);
823 if (result != 0) {
824 DEBUG1("smb_request failed\n");
825 goto out;
826 }
827
828 if (smb_valid_packet(req->rq_header) != 0) {
829 PARANOIA("invalid packet!\n");
830 goto out;
831 }
832
833 result = smb_verify(req->rq_header, command, wct, bcc);
834
835out:
836 return result;
837}
838
839/*
840 * This implements the NEWCONN ioctl. It installs the server pid,
841 * sets server->state to CONN_VALID, and wakes up the waiting process.
842 */
843int
844smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
845{
846 struct file *filp;
847 struct sock *sk;
848 int error;
849
850 VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
851
852 smb_lock_server(server);
853
854 /*
855 * Make sure we don't already have a valid connection ...
856 */
857 error = -EINVAL;
858 if (server->state == CONN_VALID)
859 goto out;
860
861 error = -EACCES;
862 if (current_uid() != server->mnt->mounted_uid &&
863 !capable(CAP_SYS_ADMIN))
864 goto out;
865
866 error = -EBADF;
867 filp = fget(opt->fd);
868 if (!filp)
869 goto out;
870 if (!smb_valid_socket(filp->f_path.dentry->d_inode))
871 goto out_putf;
872
873 server->sock_file = filp;
874 server->conn_pid = get_pid(task_pid(current));
875 server->opt = *opt;
876 server->generation += 1;
877 server->state = CONN_VALID;
878 error = 0;
879
880 if (server->conn_error) {
881 /*
882 * conn_error is the returncode we originally decided to
883 * drop the old connection on. This message should be positive
884 * and not make people ask questions on why smbfs is printing
885 * error messages ...
886 */
887 printk(KERN_INFO "SMB connection re-established (%d)\n",
888 server->conn_error);
889 server->conn_error = 0;
890 }
891
892 /*
893 * Store the server in sock user_data (Only used by sunrpc)
894 */
895 sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;
896 sk->sk_user_data = server;
897
898 /* chain into the data_ready callback */
899 server->data_ready = xchg(&sk->sk_data_ready, smb_data_ready);
900
901 /* check if we have an old smbmount that uses seconds for the
902 serverzone */
903 if (server->opt.serverzone > 12*60 || server->opt.serverzone < -12*60)
904 server->opt.serverzone /= 60;
905
906 /* now that we have an established connection we can detect the server
907 type and enable bug workarounds */
908 if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
909 install_ops(server->ops, &smb_ops_core);
910 else if (server->opt.protocol == SMB_PROTOCOL_LANMAN2)
911 install_ops(server->ops, &smb_ops_os2);
912 else if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
913 (server->opt.max_xmit < 0x1000) &&
914 !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
915 /* FIXME: can we kill the WIN95 flag now? */
916 server->mnt->flags |= SMB_MOUNT_WIN95;
917 VERBOSE("detected WIN95 server\n");
918 install_ops(server->ops, &smb_ops_win95);
919 } else {
920 /*
921 * Samba has max_xmit 65535
922 * NT4spX has max_xmit 4536 (or something like that)
923 * win2k has ...
924 */
925 VERBOSE("detected NT1 (Samba, NT4/5) server\n");
926 install_ops(server->ops, &smb_ops_winNT);
927 }
928
929 /* FIXME: the win9x code wants to modify these ... (seek/trunc bug) */
930 if (server->mnt->flags & SMB_MOUNT_OLDATTR) {
931 server->ops->getattr = smb_proc_getattr_core;
932 } else if (server->mnt->flags & SMB_MOUNT_DIRATTR) {
933 server->ops->getattr = smb_proc_getattr_ff;
934 }
935
936 /* Decode server capabilities */
937 if (server->opt.capabilities & SMB_CAP_LARGE_FILES) {
938 /* Should be ok to set this now, as no one can access the
939 mount until the connection has been established. */
940 SB_of(server)->s_maxbytes = ~0ULL >> 1;
941 VERBOSE("LFS enabled\n");
942 }
943 if (server->opt.capabilities & SMB_CAP_UNICODE) {
944 server->mnt->flags |= SMB_MOUNT_UNICODE;
945 VERBOSE("Unicode enabled\n");
946 } else {
947 server->mnt->flags &= ~SMB_MOUNT_UNICODE;
948 }
949#if 0
950 /* flags we may test for other patches ... */
951 if (server->opt.capabilities & SMB_CAP_LARGE_READX) {
952 VERBOSE("Large reads enabled\n");
953 }
954 if (server->opt.capabilities & SMB_CAP_LARGE_WRITEX) {
955 VERBOSE("Large writes enabled\n");
956 }
957#endif
958 if (server->opt.capabilities & SMB_CAP_UNIX) {
959 struct inode *inode;
960 VERBOSE("Using UNIX CIFS extensions\n");
961 install_ops(server->ops, &smb_ops_unix);
962 inode = SB_of(server)->s_root->d_inode;
963 if (inode)
964 inode->i_op = &smb_dir_inode_operations_unix;
965 }
966
967 VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
968 server->opt.protocol, server->opt.max_xmit,
969 pid_nr(server->conn_pid), server->opt.capabilities);
970
971 /* FIXME: this really should be done by smbmount. */
972 if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {
973 server->opt.max_xmit = SMB_MAX_PACKET_SIZE;
974 }
975
976 smb_unlock_server(server);
977 smbiod_wake_up();
978 if (server->opt.capabilities & SMB_CAP_UNIX)
979 smb_proc_query_cifsunix(server);
980
981 server->conn_complete++;
982 wake_up_interruptible_all(&server->conn_wq);
983 return error;
984
985out:
986 smb_unlock_server(server);
987 smbiod_wake_up();
988 return error;
989
990out_putf:
991 fput(filp);
992 goto out;
993}
994
995/* smb_setup_header: We completely set up the packet. You only have to
996 insert the command-specific fields */
997
998__u8 *
999smb_setup_header(struct smb_request *req, __u8 command, __u16 wct, __u16 bcc)
1000{
1001 __u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2;
1002 __u8 *p = req->rq_header;
1003 struct smb_sb_info *server = req->rq_server;
1004
1005 p = smb_encode_smb_length(p, xmit_len - 4);
1006
1007 *p++ = 0xff;
1008 *p++ = 'S';
1009 *p++ = 'M';
1010 *p++ = 'B';
1011 *p++ = command;
1012
1013 memset(p, '\0', 19);
1014 p += 19;
1015 p += 8;
1016
1017 if (server->opt.protocol > SMB_PROTOCOL_CORE) {
1018 int flags = SMB_FLAGS_CASELESS_PATHNAMES;
1019 int flags2 = SMB_FLAGS2_LONG_PATH_COMPONENTS |
1020 SMB_FLAGS2_EXTENDED_ATTRIBUTES; /* EA? not really ... */
1021
1022 *(req->rq_header + smb_flg) = flags;
1023 if (server->mnt->flags & SMB_MOUNT_UNICODE)
1024 flags2 |= SMB_FLAGS2_UNICODE_STRINGS;
1025 WSET(req->rq_header, smb_flg2, flags2);
1026 }
1027 *p++ = wct; /* wct */
1028 p += 2 * wct;
1029 WSET(p, 0, bcc);
1030
1031 /* Include the header in the data to send */
1032 req->rq_iovlen = 1;
1033 req->rq_iov[0].iov_base = req->rq_header;
1034 req->rq_iov[0].iov_len = xmit_len - bcc;
1035
1036 return req->rq_buffer;
1037}
1038
1039static void
1040smb_setup_bcc(struct smb_request *req, __u8 *p)
1041{
1042 u16 bcc = p - req->rq_buffer;
1043 u8 *pbcc = req->rq_header + SMB_HEADER_LEN + 2*SMB_WCT(req->rq_header);
1044
1045 WSET(pbcc, 0, bcc);
1046
1047 smb_encode_smb_length(req->rq_header, SMB_HEADER_LEN +
1048 2*SMB_WCT(req->rq_header) - 2 + bcc);
1049
1050 /* Include the "bytes" in the data to send */
1051 req->rq_iovlen = 2;
1052 req->rq_iov[1].iov_base = req->rq_buffer;
1053 req->rq_iov[1].iov_len = bcc;
1054}
1055
1056static int
1057smb_proc_seek(struct smb_sb_info *server, __u16 fileid,
1058 __u16 mode, off_t offset)
1059{
1060 int result;
1061 struct smb_request *req;
1062
1063 result = -ENOMEM;
1064 if (! (req = smb_alloc_request(server, 0)))
1065 goto out;
1066
1067 smb_setup_header(req, SMBlseek, 4, 0);
1068 WSET(req->rq_header, smb_vwv0, fileid);
1069 WSET(req->rq_header, smb_vwv1, mode);
1070 DSET(req->rq_header, smb_vwv2, offset);
1071 req->rq_flags |= SMB_REQ_NORETRY;
1072
1073 result = smb_request_ok(req, SMBlseek, 2, 0);
1074 if (result < 0) {
1075 result = 0;
1076 goto out_free;
1077 }
1078
1079 result = DVAL(req->rq_header, smb_vwv0);
1080out_free:
1081 smb_rput(req);
1082out:
1083 return result;
1084}
1085
1086static int
1087smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
1088{
1089 struct inode *ino = dentry->d_inode;
1090 struct smb_inode_info *ei = SMB_I(ino);
1091 int mode, read_write = 0x42, read_only = 0x40;
1092 int res;
1093 char *p;
1094 struct smb_request *req;
1095
1096 /*
1097 * Attempt to open r/w, unless there are no write privileges.
1098 */
1099 mode = read_write;
1100 if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1101 mode = read_only;
1102#if 0
1103 /* FIXME: why is this code not in? below we fix it so that a caller
1104 wanting RO doesn't get RW. smb_revalidate_inode does some
1105 optimization based on access mode. tail -f needs it to be correct.
1106
1107 We must open rw since we don't do the open if called a second time
1108 with different 'wish'. Is that not supported by smb servers? */
1109 if (!(wish & (O_WRONLY | O_RDWR)))
1110 mode = read_only;
1111#endif
1112
1113 res = -ENOMEM;
1114 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
1115 goto out;
1116
1117 retry:
1118 p = smb_setup_header(req, SMBopen, 2, 0);
1119 WSET(req->rq_header, smb_vwv0, mode);
1120 WSET(req->rq_header, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
1121 res = smb_simple_encode_path(req, &p, dentry, NULL);
1122 if (res < 0)
1123 goto out_free;
1124 smb_setup_bcc(req, p);
1125
1126 res = smb_request_ok(req, SMBopen, 7, 0);
1127 if (res != 0) {
1128 if (mode == read_write &&
1129 (res == -EACCES || res == -ETXTBSY || res == -EROFS))
1130 {
1131 VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
1132 DENTRY_PATH(dentry), res);
1133 mode = read_only;
1134 req->rq_flags = 0;
1135 goto retry;
1136 }
1137 goto out_free;
1138 }
1139 /* We should now have data in vwv[0..6]. */
1140
1141 ei->fileid = WVAL(req->rq_header, smb_vwv0);
1142 ei->attr = WVAL(req->rq_header, smb_vwv1);
1143 /* smb_vwv2 has mtime */
1144 /* smb_vwv4 has size */
1145 ei->access = (WVAL(req->rq_header, smb_vwv6) & SMB_ACCMASK);
1146 ei->open = server->generation;
1147
1148out_free:
1149 smb_rput(req);
1150out:
1151 return res;
1152}
1153
1154/*
1155 * Make sure the file is open, and check that the access
1156 * is compatible with the desired access.
1157 */
1158int
1159smb_open(struct dentry *dentry, int wish)
1160{
1161 struct inode *inode = dentry->d_inode;
1162 int result;
1163 __u16 access;
1164
1165 result = -ENOENT;
1166 if (!inode) {
1167 printk(KERN_ERR "smb_open: no inode for dentry %s/%s\n",
1168 DENTRY_PATH(dentry));
1169 goto out;
1170 }
1171
1172 if (!smb_is_open(inode)) {
1173 struct smb_sb_info *server = server_from_inode(inode);
1174 result = 0;
1175 if (!smb_is_open(inode))
1176 result = smb_proc_open(server, dentry, wish);
1177 if (result)
1178 goto out;
1179 /*
1180 * A successful open means the path is still valid ...
1181 */
1182 smb_renew_times(dentry);
1183 }
1184
1185 /*
1186 * Check whether the access is compatible with the desired mode.
1187 */
1188 result = 0;
1189 access = SMB_I(inode)->access;
1190 if (access != wish && access != SMB_O_RDWR) {
1191 PARANOIA("%s/%s access denied, access=%x, wish=%x\n",
1192 DENTRY_PATH(dentry), access, wish);
1193 result = -EACCES;
1194 }
1195out:
1196 return result;
1197}
1198
1199static int
1200smb_proc_close(struct smb_sb_info *server, __u16 fileid, __u32 mtime)
1201{
1202 struct smb_request *req;
1203 int result = -ENOMEM;
1204
1205 if (! (req = smb_alloc_request(server, 0)))
1206 goto out;
1207
1208 smb_setup_header(req, SMBclose, 3, 0);
1209 WSET(req->rq_header, smb_vwv0, fileid);
1210 DSET(req->rq_header, smb_vwv1, utc2local(server, mtime));
1211 req->rq_flags |= SMB_REQ_NORETRY;
1212 result = smb_request_ok(req, SMBclose, 0, 0);
1213
1214 smb_rput(req);
1215out:
1216 return result;
1217}
1218
1219/*
1220 * Win NT 4.0 has an apparent bug in that it fails to update the
1221 * modify time when writing to a file. As a workaround, we update
1222 * both modify and access time locally, and post the times to the
1223 * server when closing the file.
1224 */
1225static int
1226smb_proc_close_inode(struct smb_sb_info *server, struct inode * ino)
1227{
1228 struct smb_inode_info *ei = SMB_I(ino);
1229 int result = 0;
1230 if (smb_is_open(ino))
1231 {
1232 /*
1233 * We clear the open flag in advance, in case another
1234 * process observes the value while we block below.
1235 */
1236 ei->open = 0;
1237
1238 /*
1239 * Kludge alert: SMB timestamps are accurate only to
1240 * two seconds ... round the times to avoid needless
1241 * cache invalidations!
1242 */
1243 if (ino->i_mtime.tv_sec & 1) {
1244 ino->i_mtime.tv_sec--;
1245 ino->i_mtime.tv_nsec = 0;
1246 }
1247 if (ino->i_atime.tv_sec & 1) {
1248 ino->i_atime.tv_sec--;
1249 ino->i_atime.tv_nsec = 0;
1250 }
1251 /*
1252 * If the file is open with write permissions,
1253 * update the time stamps to sync mtime and atime.
1254 */
1255 if ((server->opt.capabilities & SMB_CAP_UNIX) == 0 &&
1256 (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) &&
1257 !(ei->access == SMB_O_RDONLY))
1258 {
1259 struct smb_fattr fattr;
1260 smb_get_inode_attr(ino, &fattr);
1261 smb_proc_setattr_ext(server, ino, &fattr);
1262 }
1263
1264 result = smb_proc_close(server, ei->fileid, ino->i_mtime.tv_sec);
1265 /*
1266 * Force a revalidation after closing ... some servers
1267 * don't post the size until the file has been closed.
1268 */
1269 if (server->opt.protocol < SMB_PROTOCOL_NT1)
1270 ei->oldmtime = 0;
1271 ei->closed = jiffies;
1272 }
1273 return result;
1274}
1275
1276int
1277smb_close(struct inode *ino)
1278{
1279 int result = 0;
1280
1281 if (smb_is_open(ino)) {
1282 struct smb_sb_info *server = server_from_inode(ino);
1283 result = smb_proc_close_inode(server, ino);
1284 }
1285 return result;
1286}
1287
1288/*
1289 * This is used to close a file following a failed instantiate.
1290 * Since we don't have an inode, we can't use any of the above.
1291 */
1292int
1293smb_close_fileid(struct dentry *dentry, __u16 fileid)
1294{
1295 struct smb_sb_info *server = server_from_dentry(dentry);
1296 int result;
1297
1298 result = smb_proc_close(server, fileid, get_seconds());
1299 return result;
1300}
1301
1302/* In smb_proc_read and smb_proc_write we do not retry, because the
1303 file-id would not be valid after a reconnection. */
1304
1305static void
1306smb_proc_read_data(struct smb_request *req)
1307{
1308 req->rq_iov[0].iov_base = req->rq_buffer;
1309 req->rq_iov[0].iov_len = 3;
1310
1311 req->rq_iov[1].iov_base = req->rq_page;
1312 req->rq_iov[1].iov_len = req->rq_rsize;
1313 req->rq_iovlen = 2;
1314
1315 req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
1316}
1317
1318static int
1319smb_proc_read(struct inode *inode, loff_t offset, int count, char *data)
1320{
1321 struct smb_sb_info *server = server_from_inode(inode);
1322 __u16 returned_count, data_len;
1323 unsigned char *buf;
1324 int result;
1325 struct smb_request *req;
1326 u8 rbuf[4];
1327
1328 result = -ENOMEM;
1329 if (! (req = smb_alloc_request(server, 0)))
1330 goto out;
1331
1332 smb_setup_header(req, SMBread, 5, 0);
1333 buf = req->rq_header;
1334 WSET(buf, smb_vwv0, SMB_I(inode)->fileid);
1335 WSET(buf, smb_vwv1, count);
1336 DSET(buf, smb_vwv2, offset);
1337 WSET(buf, smb_vwv4, 0);
1338
1339 req->rq_page = data;
1340 req->rq_rsize = count;
1341 req->rq_callback = smb_proc_read_data;
1342 req->rq_buffer = rbuf;
1343 req->rq_flags |= SMB_REQ_NORETRY | SMB_REQ_STATIC;
1344
1345 result = smb_request_ok(req, SMBread, 5, -1);
1346 if (result < 0)
1347 goto out_free;
1348 returned_count = WVAL(req->rq_header, smb_vwv0);
1349
1350 data_len = WVAL(rbuf, 1);
1351
1352 if (returned_count != data_len) {
1353 printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
1354 printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
1355 returned_count, data_len);
1356 }
1357 result = data_len;
1358
1359out_free:
1360 smb_rput(req);
1361out:
1362 VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
1363 inode->i_ino, SMB_I(inode)->fileid, count, result);
1364 return result;
1365}
1366
1367static int
1368smb_proc_write(struct inode *inode, loff_t offset, int count, const char *data)
1369{
1370 struct smb_sb_info *server = server_from_inode(inode);
1371 int result;
1372 u16 fileid = SMB_I(inode)->fileid;
1373 u8 buf[4];
1374 struct smb_request *req;
1375
1376 result = -ENOMEM;
1377 if (! (req = smb_alloc_request(server, 0)))
1378 goto out;
1379
1380 VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld\n",
1381 inode->i_ino, fileid, count, offset);
1382
1383 smb_setup_header(req, SMBwrite, 5, count + 3);
1384 WSET(req->rq_header, smb_vwv0, fileid);
1385 WSET(req->rq_header, smb_vwv1, count);
1386 DSET(req->rq_header, smb_vwv2, offset);
1387 WSET(req->rq_header, smb_vwv4, 0);
1388
1389 buf[0] = 1;
1390 WSET(buf, 1, count); /* yes, again ... */
1391 req->rq_iov[1].iov_base = buf;
1392 req->rq_iov[1].iov_len = 3;
1393 req->rq_iov[2].iov_base = (char *) data;
1394 req->rq_iov[2].iov_len = count;
1395 req->rq_iovlen = 3;
1396 req->rq_flags |= SMB_REQ_NORETRY;
1397
1398 result = smb_request_ok(req, SMBwrite, 1, 0);
1399 if (result >= 0)
1400 result = WVAL(req->rq_header, smb_vwv0);
1401
1402 smb_rput(req);
1403out:
1404 return result;
1405}
1406
1407/*
1408 * In smb_proc_readX and smb_proc_writeX we do not retry, because the
1409 * file-id would not be valid after a reconnection.
1410 */
1411
1412#define SMB_READX_MAX_PAD 64
1413static void
1414smb_proc_readX_data(struct smb_request *req)
1415{
1416 /* header length, excluding the netbios length (-4) */
1417 int hdrlen = SMB_HEADER_LEN + req->rq_resp_wct*2 - 2;
1418 int data_off = WVAL(req->rq_header, smb_vwv6);
1419
1420 /*
1421 * Some genius made the padding to the data bytes arbitrary.
1422 * So we must first calculate the amount of padding used by the server.
1423 */
1424 data_off -= hdrlen;
1425 if (data_off > SMB_READX_MAX_PAD || data_off < 0) {
1426 PARANOIA("offset is larger than SMB_READX_MAX_PAD or negative!\n");
1427 PARANOIA("%d > %d || %d < 0\n", data_off, SMB_READX_MAX_PAD, data_off);
1428 req->rq_rlen = req->rq_bufsize + 1;
1429 return;
1430 }
1431 req->rq_iov[0].iov_base = req->rq_buffer;
1432 req->rq_iov[0].iov_len = data_off;
1433
1434 req->rq_iov[1].iov_base = req->rq_page;
1435 req->rq_iov[1].iov_len = req->rq_rsize;
1436 req->rq_iovlen = 2;
1437
1438 req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
1439}
1440
1441static int
1442smb_proc_readX(struct inode *inode, loff_t offset, int count, char *data)
1443{
1444 struct smb_sb_info *server = server_from_inode(inode);
1445 unsigned char *buf;
1446 int result;
1447 struct smb_request *req;
1448 static char pad[SMB_READX_MAX_PAD];
1449
1450 result = -ENOMEM;
1451 if (! (req = smb_alloc_request(server, 0)))
1452 goto out;
1453
1454 smb_setup_header(req, SMBreadX, 12, 0);
1455 buf = req->rq_header;
1456 WSET(buf, smb_vwv0, 0x00ff);
1457 WSET(buf, smb_vwv1, 0);
1458 WSET(buf, smb_vwv2, SMB_I(inode)->fileid);
1459 DSET(buf, smb_vwv3, (u32)offset); /* low 32 bits */
1460 WSET(buf, smb_vwv5, count);
1461 WSET(buf, smb_vwv6, 0);
1462 DSET(buf, smb_vwv7, 0);
1463 WSET(buf, smb_vwv9, 0);
1464 DSET(buf, smb_vwv10, (u32)(offset >> 32)); /* high 32 bits */
1465 WSET(buf, smb_vwv11, 0);
1466
1467 req->rq_page = data;
1468 req->rq_rsize = count;
1469 req->rq_callback = smb_proc_readX_data;
1470 req->rq_buffer = pad;
1471 req->rq_bufsize = SMB_READX_MAX_PAD;
1472 req->rq_flags |= SMB_REQ_STATIC | SMB_REQ_NORETRY;
1473
1474 result = smb_request_ok(req, SMBreadX, 12, -1);
1475 if (result < 0)
1476 goto out_free;
1477 result = WVAL(req->rq_header, smb_vwv5);
1478
1479out_free:
1480 smb_rput(req);
1481out:
1482 VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
1483 inode->i_ino, SMB_I(inode)->fileid, count, result);
1484 return result;
1485}
1486
1487static int
1488smb_proc_writeX(struct inode *inode, loff_t offset, int count, const char *data)
1489{
1490 struct smb_sb_info *server = server_from_inode(inode);
1491 int result;
1492 u8 *p;
1493 static u8 pad[4];
1494 struct smb_request *req;
1495
1496 result = -ENOMEM;
1497 if (! (req = smb_alloc_request(server, 0)))
1498 goto out;
1499
1500 VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld\n",
1501 inode->i_ino, SMB_I(inode)->fileid, count, offset);
1502
1503 p = smb_setup_header(req, SMBwriteX, 14, count + 1);
1504 WSET(req->rq_header, smb_vwv0, 0x00ff);
1505 WSET(req->rq_header, smb_vwv1, 0);
1506 WSET(req->rq_header, smb_vwv2, SMB_I(inode)->fileid);
1507 DSET(req->rq_header, smb_vwv3, (u32)offset); /* low 32 bits */
1508 DSET(req->rq_header, smb_vwv5, 0);
1509 WSET(req->rq_header, smb_vwv7, 0); /* write mode */
1510 WSET(req->rq_header, smb_vwv8, 0);
1511 WSET(req->rq_header, smb_vwv9, 0);
1512 WSET(req->rq_header, smb_vwv10, count); /* data length */
1513 WSET(req->rq_header, smb_vwv11, smb_vwv12 + 2 + 1);
1514 DSET(req->rq_header, smb_vwv12, (u32)(offset >> 32));
1515
1516 req->rq_iov[1].iov_base = pad;
1517 req->rq_iov[1].iov_len = 1;
1518 req->rq_iov[2].iov_base = (char *) data;
1519 req->rq_iov[2].iov_len = count;
1520 req->rq_iovlen = 3;
1521 req->rq_flags |= SMB_REQ_NORETRY;
1522
1523 result = smb_request_ok(req, SMBwriteX, 6, 0);
1524 if (result >= 0)
1525 result = WVAL(req->rq_header, smb_vwv2);
1526
1527 smb_rput(req);
1528out:
1529 return result;
1530}
1531
1532int
1533smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
1534{
1535 struct smb_sb_info *server = server_from_dentry(dentry);
1536 char *p;
1537 int result;
1538 struct smb_request *req;
1539
1540 result = -ENOMEM;
1541 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
1542 goto out;
1543
1544 p = smb_setup_header(req, SMBcreate, 3, 0);
1545 WSET(req->rq_header, smb_vwv0, attr);
1546 DSET(req->rq_header, smb_vwv1, utc2local(server, ctime));
1547 result = smb_simple_encode_path(req, &p, dentry, NULL);
1548 if (result < 0)
1549 goto out_free;
1550 smb_setup_bcc(req, p);
1551
1552 result = smb_request_ok(req, SMBcreate, 1, 0);
1553 if (result < 0)
1554 goto out_free;
1555
1556 *fileid = WVAL(req->rq_header, smb_vwv0);
1557 result = 0;
1558
1559out_free:
1560 smb_rput(req);
1561out:
1562 return result;
1563}
1564
1565int
1566smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
1567{
1568 struct smb_sb_info *server = server_from_dentry(old_dentry);
1569 char *p;
1570 int result;
1571 struct smb_request *req;
1572
1573 result = -ENOMEM;
1574 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
1575 goto out;
1576
1577 p = smb_setup_header(req, SMBmv, 1, 0);
1578 WSET(req->rq_header, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
1579 result = smb_simple_encode_path(req, &p, old_dentry, NULL);
1580 if (result < 0)
1581 goto out_free;
1582 result = smb_simple_encode_path(req, &p, new_dentry, NULL);
1583 if (result < 0)
1584 goto out_free;
1585 smb_setup_bcc(req, p);
1586
1587 if ((result = smb_request_ok(req, SMBmv, 0, 0)) < 0)
1588 goto out_free;
1589 result = 0;
1590
1591out_free:
1592 smb_rput(req);
1593out:
1594 return result;
1595}
1596
1597/*
1598 * Code common to mkdir and rmdir.
1599 */
1600static int
1601smb_proc_generic_command(struct dentry *dentry, __u8 command)
1602{
1603 struct smb_sb_info *server = server_from_dentry(dentry);
1604 char *p;
1605 int result;
1606 struct smb_request *req;
1607
1608 result = -ENOMEM;
1609 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
1610 goto out;
1611
1612 p = smb_setup_header(req, command, 0, 0);
1613 result = smb_simple_encode_path(req, &p, dentry, NULL);
1614 if (result < 0)
1615 goto out_free;
1616 smb_setup_bcc(req, p);
1617
1618 result = smb_request_ok(req, command, 0, 0);
1619 if (result < 0)
1620 goto out_free;
1621 result = 0;
1622
1623out_free:
1624 smb_rput(req);
1625out:
1626 return result;
1627}
1628
1629int
1630smb_proc_mkdir(struct dentry *dentry)
1631{
1632 return smb_proc_generic_command(dentry, SMBmkdir);
1633}
1634
1635int
1636smb_proc_rmdir(struct dentry *dentry)
1637{
1638 return smb_proc_generic_command(dentry, SMBrmdir);
1639}
1640
1641#if SMBFS_POSIX_UNLINK
1642/*
1643 * Removes readonly attribute from a file. Used by unlink to give posix
1644 * semantics.
1645 */
1646static int
1647smb_set_rw(struct dentry *dentry,struct smb_sb_info *server)
1648{
1649 int result;
1650 struct smb_fattr fattr;
1651
1652 /* FIXME: cifsUE should allow removing a readonly file. */
1653
1654 /* first get current attribute */
1655 smb_init_dirent(server, &fattr);
1656 result = server->ops->getattr(server, dentry, &fattr);
1657 smb_finish_dirent(server, &fattr);
1658 if (result < 0)
1659 return result;
1660
1661 /* if RONLY attribute is set, remove it */
1662 if (fattr.attr & aRONLY) { /* read only attribute is set */
1663 fattr.attr &= ~aRONLY;
1664 result = smb_proc_setattr_core(server, dentry, fattr.attr);
1665 }
1666 return result;
1667}
1668#endif
1669
1670int
1671smb_proc_unlink(struct dentry *dentry)
1672{
1673 struct smb_sb_info *server = server_from_dentry(dentry);
1674 int flag = 0;
1675 char *p;
1676 int result;
1677 struct smb_request *req;
1678
1679 result = -ENOMEM;
1680 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
1681 goto out;
1682
1683 retry:
1684 p = smb_setup_header(req, SMBunlink, 1, 0);
1685 WSET(req->rq_header, smb_vwv0, aSYSTEM | aHIDDEN);
1686 result = smb_simple_encode_path(req, &p, dentry, NULL);
1687 if (result < 0)
1688 goto out_free;
1689 smb_setup_bcc(req, p);
1690
1691 if ((result = smb_request_ok(req, SMBunlink, 0, 0)) < 0) {
1692#if SMBFS_POSIX_UNLINK
1693 if (result == -EACCES && !flag) {
1694 /* Posix semantics is for the read-only state
1695 of a file to be ignored in unlink(). In the
1696 SMB world a unlink() is refused on a
1697 read-only file. To make things easier for
1698 unix users we try to override the files
1699 permission if the unlink fails with the
1700 right error.
1701 This introduces a race condition that could
1702 lead to a file being written by someone who
1703 shouldn't have access, but as far as I can
1704 tell that is unavoidable */
1705
1706 /* remove RONLY attribute and try again */
1707 result = smb_set_rw(dentry,server);
1708 if (result == 0) {
1709 flag = 1;
1710 req->rq_flags = 0;
1711 goto retry;
1712 }
1713 }
1714#endif
1715 goto out_free;
1716 }
1717 result = 0;
1718
1719out_free:
1720 smb_rput(req);
1721out:
1722 return result;
1723}
1724
1725int
1726smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
1727{
1728 int result;
1729 struct smb_request *req;
1730
1731 result = -ENOMEM;
1732 if (! (req = smb_alloc_request(server, 0)))
1733 goto out;
1734
1735 smb_setup_header(req, SMBflush, 1, 0);
1736 WSET(req->rq_header, smb_vwv0, fileid);
1737 req->rq_flags |= SMB_REQ_NORETRY;
1738 result = smb_request_ok(req, SMBflush, 0, 0);
1739
1740 smb_rput(req);
1741out:
1742 return result;
1743}
1744
1745static int
1746smb_proc_trunc32(struct inode *inode, loff_t length)
1747{
1748 /*
1749 * Writing 0bytes is old-SMB magic for truncating files.
1750 * MAX_NON_LFS should prevent this from being called with a too
1751 * large offset.
1752 */
1753 return smb_proc_write(inode, length, 0, NULL);
1754}
1755
1756static int
1757smb_proc_trunc64(struct inode *inode, loff_t length)
1758{
1759 struct smb_sb_info *server = server_from_inode(inode);
1760 int result;
1761 char *param;
1762 char *data;
1763 struct smb_request *req;
1764
1765 result = -ENOMEM;
1766 if (! (req = smb_alloc_request(server, 14)))
1767 goto out;
1768
1769 param = req->rq_buffer;
1770 data = req->rq_buffer + 6;
1771
1772 /* FIXME: must we also set allocation size? winNT seems to do that */
1773 WSET(param, 0, SMB_I(inode)->fileid);
1774 WSET(param, 2, SMB_SET_FILE_END_OF_FILE_INFO);
1775 WSET(param, 4, 0);
1776 LSET(data, 0, length);
1777
1778 req->rq_trans2_command = TRANSACT2_SETFILEINFO;
1779 req->rq_ldata = 8;
1780 req->rq_data = data;
1781 req->rq_lparm = 6;
1782 req->rq_parm = param;
1783 req->rq_flags |= SMB_REQ_NORETRY;
1784 result = smb_add_request(req);
1785 if (result < 0)
1786 goto out_free;
1787
1788 result = 0;
1789 if (req->rq_rcls != 0)
1790 result = smb_errno(req);
1791
1792out_free:
1793 smb_rput(req);
1794out:
1795 return result;
1796}
1797
1798static int
1799smb_proc_trunc95(struct inode *inode, loff_t length)
1800{
1801 struct smb_sb_info *server = server_from_inode(inode);
1802 int result = smb_proc_trunc32(inode, length);
1803
1804 /*
1805 * win9x doesn't appear to update the size immediately.
1806 * It will return the old file size after the truncate,
1807 * confusing smbfs. So we force an update.
1808 *
1809 * FIXME: is this still necessary?
1810 */
1811 smb_proc_flush(server, SMB_I(inode)->fileid);
1812 return result;
1813}
1814
1815static void
1816smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
1817{
1818 memset(fattr, 0, sizeof(*fattr));
1819
1820 fattr->f_nlink = 1;
1821 fattr->f_uid = server->mnt->uid;
1822 fattr->f_gid = server->mnt->gid;
1823 fattr->f_unix = 0;
1824}
1825
1826static void
1827smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
1828{
1829 if (fattr->f_unix)
1830 return;
1831
1832 fattr->f_mode = server->mnt->file_mode;
1833 if (fattr->attr & aDIR) {
1834 fattr->f_mode = server->mnt->dir_mode;
1835 fattr->f_size = SMB_ST_BLKSIZE;
1836 }
1837 /* Check the read-only flag */
1838 if (fattr->attr & aRONLY)
1839 fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
1840
1841 /* How many 512 byte blocks do we need for this file? */
1842 fattr->f_blocks = 0;
1843 if (fattr->f_size != 0)
1844 fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);
1845 return;
1846}
1847
1848void
1849smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr,
1850 struct super_block *sb)
1851{
1852 smb_init_dirent(server, fattr);
1853 fattr->attr = aDIR;
1854 fattr->f_ino = 2; /* traditional root inode number */
1855 fattr->f_mtime = current_fs_time(sb);
1856 smb_finish_dirent(server, fattr);
1857}
1858
1859/*
1860 * Decode a dirent for old protocols
1861 *
1862 * qname is filled with the decoded, and possibly translated, name.
1863 * fattr receives decoded attributes
1864 *
1865 * Bugs Noted:
1866 * (1) Pathworks servers may pad the name with extra spaces.
1867 */
1868static char *
1869smb_decode_short_dirent(struct smb_sb_info *server, char *p,
1870 struct qstr *qname, struct smb_fattr *fattr,
1871 unsigned char *name_buf)
1872{
1873 int len;
1874
1875 /*
1876 * SMB doesn't have a concept of inode numbers ...
1877 */
1878 smb_init_dirent(server, fattr);
1879 fattr->f_ino = 0; /* FIXME: do we need this? */
1880
1881 p += SMB_STATUS_SIZE; /* reserved (search_status) */
1882 fattr->attr = *p;
1883 fattr->f_mtime.tv_sec = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
1884 fattr->f_mtime.tv_nsec = 0;
1885 fattr->f_size = DVAL(p, 5);
1886 fattr->f_ctime = fattr->f_mtime;
1887 fattr->f_atime = fattr->f_mtime;
1888 qname->name = p + 9;
1889 len = strnlen(qname->name, 12);
1890
1891 /*
1892 * Trim trailing blanks for Pathworks servers
1893 */
1894 while (len > 2 && qname->name[len-1] == ' ')
1895 len--;
1896
1897 smb_finish_dirent(server, fattr);
1898
1899#if 0
1900 /* FIXME: These only work for ascii chars, and recent smbmount doesn't
1901 allow the flag to be set anyway. It kills const. Remove? */
1902 switch (server->opt.case_handling) {
1903 case SMB_CASE_UPPER:
1904 str_upper(entry->name, len);
1905 break;
1906 case SMB_CASE_LOWER:
1907 str_lower(entry->name, len);
1908 break;
1909 default:
1910 break;
1911 }
1912#endif
1913
1914 qname->len = 0;
1915 len = server->ops->convert(name_buf, SMB_MAXNAMELEN,
1916 qname->name, len,
1917 server->remote_nls, server->local_nls);
1918 if (len > 0) {
1919 qname->len = len;
1920 qname->name = name_buf;
1921 DEBUG1("len=%d, name=%.*s\n",qname->len,qname->len,qname->name);
1922 }
1923
1924 return p + 22;
1925}
1926
1927/*
1928 * This routine is used to read in directory entries from the network.
1929 * Note that it is for short directory name seeks, i.e.: protocol <
1930 * SMB_PROTOCOL_LANMAN2
1931 */
1932static int
1933smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
1934 struct smb_cache_control *ctl)
1935{
1936 struct dentry *dir = filp->f_path.dentry;
1937 struct smb_sb_info *server = server_from_dentry(dir);
1938 struct qstr qname;
1939 struct smb_fattr fattr;
1940 char *p;
1941 int result;
1942 int i, first, entries_seen, entries;
1943 int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE;
1944 __u16 bcc;
1945 __u16 count;
1946 char status[SMB_STATUS_SIZE];
1947 static struct qstr mask = {
1948 .name = "*.*",
1949 .len = 3,
1950 };
1951 unsigned char *last_status;
1952 struct smb_request *req;
1953 unsigned char *name_buf;
1954
1955 VERBOSE("%s/%s\n", DENTRY_PATH(dir));
1956
1957 lock_kernel();
1958
1959 result = -ENOMEM;
1960 if (! (name_buf = kmalloc(SMB_MAXNAMELEN, GFP_KERNEL)))
1961 goto out;
1962
1963 first = 1;
1964 entries = 0;
1965 entries_seen = 2; /* implicit . and .. */
1966
1967 result = -ENOMEM;
1968 if (! (req = smb_alloc_request(server, server->opt.max_xmit)))
1969 goto out_name;
1970
1971 while (1) {
1972 p = smb_setup_header(req, SMBsearch, 2, 0);
1973 WSET(req->rq_header, smb_vwv0, entries_asked);
1974 WSET(req->rq_header, smb_vwv1, aDIR);
1975 if (first == 1) {
1976 result = smb_simple_encode_path(req, &p, dir, &mask);
1977 if (result < 0)
1978 goto out_free;
1979 if (p + 3 > (char *)req->rq_buffer + req->rq_bufsize) {
1980 result = -ENAMETOOLONG;
1981 goto out_free;
1982 }
1983 *p++ = 5;
1984 WSET(p, 0, 0);
1985 p += 2;
1986 first = 0;
1987 } else {
1988 if (p + 5 + SMB_STATUS_SIZE >
1989 (char *)req->rq_buffer + req->rq_bufsize) {
1990 result = -ENAMETOOLONG;
1991 goto out_free;
1992 }
1993
1994 *p++ = 4;
1995 *p++ = 0;
1996 *p++ = 5;
1997 WSET(p, 0, SMB_STATUS_SIZE);
1998 p += 2;
1999 memcpy(p, status, SMB_STATUS_SIZE);
2000 p += SMB_STATUS_SIZE;
2001 }
2002
2003 smb_setup_bcc(req, p);
2004
2005 result = smb_request_ok(req, SMBsearch, 1, -1);
2006 if (result < 0) {
2007 if ((req->rq_rcls == ERRDOS) &&
2008 (req->rq_err == ERRnofiles))
2009 break;
2010 goto out_free;
2011 }
2012 count = WVAL(req->rq_header, smb_vwv0);
2013 if (count <= 0)
2014 break;
2015
2016 result = -EIO;
2017 bcc = smb_bcc(req->rq_header);
2018 if (bcc != count * SMB_DIRINFO_SIZE + 3)
2019 goto out_free;
2020 p = req->rq_buffer + 3;
2021
2022
2023 /* Make sure the response fits in the buffer. Fixed sized
2024 entries means we don't have to check in the decode loop. */
2025
2026 last_status = req->rq_buffer + 3 + (count-1) * SMB_DIRINFO_SIZE;
2027
2028 if (last_status + SMB_DIRINFO_SIZE >=
2029 req->rq_buffer + req->rq_bufsize) {
2030 printk(KERN_ERR "smb_proc_readdir_short: "
2031 "last dir entry outside buffer! "
2032 "%d@%p %d@%p\n", SMB_DIRINFO_SIZE, last_status,
2033 req->rq_bufsize, req->rq_buffer);
2034 goto out_free;
2035 }
2036
2037 /* Read the last entry into the status field. */
2038 memcpy(status, last_status, SMB_STATUS_SIZE);
2039
2040
2041 /* Now we are ready to parse smb directory entries. */
2042
2043 for (i = 0; i < count; i++) {
2044 p = smb_decode_short_dirent(server, p,
2045 &qname, &fattr, name_buf);
2046 if (qname.len == 0)
2047 continue;
2048
2049 if (entries_seen == 2 && qname.name[0] == '.') {
2050 if (qname.len == 1)
2051 continue;
2052 if (qname.name[1] == '.' && qname.len == 2)
2053 continue;
2054 }
2055 if (!smb_fill_cache(filp, dirent, filldir, ctl,
2056 &qname, &fattr))
2057 ; /* stop reading? */
2058 entries_seen++;
2059 }
2060 }
2061 result = entries;
2062
2063out_free:
2064 smb_rput(req);
2065out_name:
2066 kfree(name_buf);
2067out:
2068 unlock_kernel();
2069 return result;
2070}
2071
2072static void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p)
2073{
2074 u64 size, disk_bytes;
2075
2076 /* FIXME: verify nls support. all is sent as utf8? */
2077
2078 fattr->f_unix = 1;
2079 fattr->f_mode = 0;
2080
2081 /* FIXME: use the uniqueID from the remote instead? */
2082 /* 0 L file size in bytes */
2083 /* 8 L file size on disk in bytes (block count) */
2084 /* 40 L uid */
2085 /* 48 L gid */
2086 /* 56 W file type */
2087 /* 60 L devmajor */
2088 /* 68 L devminor */
2089 /* 76 L unique ID (inode) */
2090 /* 84 L permissions */
2091 /* 92 L link count */
2092
2093 size = LVAL(p, 0);
2094 disk_bytes = LVAL(p, 8);
2095
2096 /*
2097 * Some samba versions round up on-disk byte usage
2098 * to 1MB boundaries, making it useless. When seeing
2099 * that, use the size instead.
2100 */
2101 if (!(disk_bytes & 0xfffff))
2102 disk_bytes = size+511;
2103
2104 fattr->f_size = size;
2105 fattr->f_blocks = disk_bytes >> 9;
2106 fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 16));
2107 fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 24));
2108 fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 32));
2109
2110 if (server->mnt->flags & SMB_MOUNT_UID)
2111 fattr->f_uid = server->mnt->uid;
2112 else
2113 fattr->f_uid = LVAL(p, 40);
2114
2115 if (server->mnt->flags & SMB_MOUNT_GID)
2116 fattr->f_gid = server->mnt->gid;
2117 else
2118 fattr->f_gid = LVAL(p, 48);
2119
2120 fattr->f_mode |= smb_filetype_to_mode(WVAL(p, 56));
2121
2122 if (S_ISBLK(fattr->f_mode) || S_ISCHR(fattr->f_mode)) {
2123 __u64 major = LVAL(p, 60);
2124 __u64 minor = LVAL(p, 68);
2125
2126 fattr->f_rdev = MKDEV(major & 0xffffffff, minor & 0xffffffff);
2127 if (MAJOR(fattr->f_rdev) != (major & 0xffffffff) ||
2128 MINOR(fattr->f_rdev) != (minor & 0xffffffff))
2129 fattr->f_rdev = 0;
2130 }
2131
2132 fattr->f_mode |= LVAL(p, 84);
2133
2134 if ( (server->mnt->flags & SMB_MOUNT_DMODE) &&
2135 (S_ISDIR(fattr->f_mode)) )
2136 fattr->f_mode = (server->mnt->dir_mode & S_IRWXUGO) | S_IFDIR;
2137 else if ( (server->mnt->flags & SMB_MOUNT_FMODE) &&
2138 !(S_ISDIR(fattr->f_mode)) )
2139 fattr->f_mode = (server->mnt->file_mode & S_IRWXUGO) |
2140 (fattr->f_mode & S_IFMT);
2141
2142}
2143
2144/*
2145 * Interpret a long filename structure using the specified info level:
2146 * level 1 for anything below NT1 protocol
2147 * level 260 for NT1 protocol
2148 *
2149 * qname is filled with the decoded, and possibly translated, name
2150 * fattr receives decoded attributes.
2151 *
2152 * Bugs Noted:
2153 * (1) Win NT 4.0 appends a null byte to names and counts it in the length!
2154 */
2155static char *
2156smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
2157 struct qstr *qname, struct smb_fattr *fattr,
2158 unsigned char *name_buf)
2159{
2160 char *result;
2161 unsigned int len = 0;
2162 int n;
2163 __u16 date, time;
2164 int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE);
2165
2166 /*
2167 * SMB doesn't have a concept of inode numbers ...
2168 */
2169 smb_init_dirent(server, fattr);
2170 fattr->f_ino = 0; /* FIXME: do we need this? */
2171
2172 switch (level) {
2173 case 1:
2174 len = *((unsigned char *) p + 22);
2175 qname->name = p + 23;
2176 result = p + 24 + len;
2177
2178 date = WVAL(p, 0);
2179 time = WVAL(p, 2);
2180 fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
2181 fattr->f_ctime.tv_nsec = 0;
2182
2183 date = WVAL(p, 4);
2184 time = WVAL(p, 6);
2185 fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
2186 fattr->f_atime.tv_nsec = 0;
2187
2188 date = WVAL(p, 8);
2189 time = WVAL(p, 10);
2190 fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
2191 fattr->f_mtime.tv_nsec = 0;
2192 fattr->f_size = DVAL(p, 12);
2193 /* ULONG allocation size */
2194 fattr->attr = WVAL(p, 20);
2195
2196 VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
2197 p, len, len, qname->name);
2198 break;
2199 case 260:
2200 result = p + WVAL(p, 0);
2201 len = DVAL(p, 60);
2202 if (len > 255) len = 255;
2203 /* NT4 null terminates, unless we are using unicode ... */
2204 qname->name = p + 94;
2205 if (!unicode && len && qname->name[len-1] == '\0')
2206 len--;
2207
2208 fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 8));
2209 fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 16));
2210 fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 24));
2211 /* change time (32) */
2212 fattr->f_size = LVAL(p, 40);
2213 /* alloc size (48) */
2214 fattr->attr = DVAL(p, 56);
2215
2216 VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
2217 p, len, len, qname->name);
2218 break;
2219 case SMB_FIND_FILE_UNIX:
2220 result = p + WVAL(p, 0);
2221 qname->name = p + 108;
2222
2223 len = strlen(qname->name);
2224 /* FIXME: should we check the length?? */
2225
2226 p += 8;
2227 smb_decode_unix_basic(fattr, server, p);
2228 VERBOSE("info SMB_FIND_FILE_UNIX at %p, len=%d, name=%.*s\n",
2229 p, len, len, qname->name);
2230 break;
2231 default:
2232 PARANOIA("Unknown info level %d\n", level);
2233 result = p + WVAL(p, 0);
2234 goto out;
2235 }
2236
2237 smb_finish_dirent(server, fattr);
2238
2239#if 0
2240 /* FIXME: These only work for ascii chars, and recent smbmount doesn't
2241 allow the flag to be set anyway. Remove? */
2242 switch (server->opt.case_handling) {
2243 case SMB_CASE_UPPER:
2244 str_upper(qname->name, len);
2245 break;
2246 case SMB_CASE_LOWER:
2247 str_lower(qname->name, len);
2248 break;
2249 default:
2250 break;
2251 }
2252#endif
2253
2254 qname->len = 0;
2255 n = server->ops->convert(name_buf, SMB_MAXNAMELEN,
2256 qname->name, len,
2257 server->remote_nls, server->local_nls);
2258 if (n > 0) {
2259 qname->len = n;
2260 qname->name = name_buf;
2261 }
2262
2263out:
2264 return result;
2265}
2266
2267/* findfirst/findnext flags */
2268#define SMB_CLOSE_AFTER_FIRST (1<<0)
2269#define SMB_CLOSE_IF_END (1<<1)
2270#define SMB_REQUIRE_RESUME_KEY (1<<2)
2271#define SMB_CONTINUE_BIT (1<<3)
2272
2273/*
2274 * Note: samba-2.0.7 (at least) has a very similar routine, cli_list, in
2275 * source/libsmb/clilist.c. When looking for smb bugs in the readdir code,
2276 * go there for advise.
2277 *
2278 * Bugs Noted:
2279 * (1) When using Info Level 1 Win NT 4.0 truncates directory listings
2280 * for certain patterns of names and/or lengths. The breakage pattern
2281 * is completely reproducible and can be toggled by the creation of a
2282 * single file. (E.g. echo hi >foo breaks, rm -f foo works.)
2283 */
2284static int
2285smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
2286 struct smb_cache_control *ctl)
2287{
2288 struct dentry *dir = filp->f_path.dentry;
2289 struct smb_sb_info *server = server_from_dentry(dir);
2290 struct qstr qname;
2291 struct smb_fattr fattr;
2292
2293 unsigned char *p, *lastname;
2294 char *mask, *param;
2295 __u16 command;
2296 int first, entries_seen;
2297
2298 /* Both NT and OS/2 accept info level 1 (but see note below). */
2299 int info_level = 260;
2300 const int max_matches = 512;
2301
2302 unsigned int ff_searchcount = 0;
2303 unsigned int ff_eos = 0;
2304 unsigned int ff_lastname = 0;
2305 unsigned int ff_dir_handle = 0;
2306 unsigned int loop_count = 0;
2307 unsigned int mask_len, i;
2308 int result;
2309 struct smb_request *req;
2310 unsigned char *name_buf;
2311 static struct qstr star = {
2312 .name = "*",
2313 .len = 1,
2314 };
2315
2316 lock_kernel();
2317
2318 /*
2319 * We always prefer unix style. Use info level 1 for older
2320 * servers that don't do 260.
2321 */
2322 if (server->opt.capabilities & SMB_CAP_UNIX)
2323 info_level = SMB_FIND_FILE_UNIX;
2324 else if (server->opt.protocol < SMB_PROTOCOL_NT1)
2325 info_level = 1;
2326
2327 result = -ENOMEM;
2328 if (! (name_buf = kmalloc(SMB_MAXNAMELEN+2, GFP_KERNEL)))
2329 goto out;
2330 if (! (req = smb_alloc_request(server, server->opt.max_xmit)))
2331 goto out_name;
2332 param = req->rq_buffer;
2333
2334 /*
2335 * Encode the initial path
2336 */
2337 mask = param + 12;
2338
2339 result = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dir, &star);
2340 if (result <= 0)
2341 goto out_free;
2342 mask_len = result - 1; /* mask_len is strlen, not #bytes */
2343 result = 0;
2344 first = 1;
2345 VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask);
2346
2347 entries_seen = 2;
2348 ff_eos = 0;
2349
2350 while (ff_eos == 0) {
2351 loop_count += 1;
2352 if (loop_count > 10) {
2353 printk(KERN_WARNING "smb_proc_readdir_long: "
2354 "Looping in FIND_NEXT??\n");
2355 result = -EIO;
2356 break;
2357 }
2358
2359 if (first != 0) {
2360 command = TRANSACT2_FINDFIRST;
2361 WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
2362 WSET(param, 2, max_matches); /* max count */
2363 WSET(param, 4, SMB_CLOSE_IF_END);
2364 WSET(param, 6, info_level);
2365 DSET(param, 8, 0);
2366 } else {
2367 command = TRANSACT2_FINDNEXT;
2368
2369 VERBOSE("handle=0x%X, lastname=%d, mask=%.*s\n",
2370 ff_dir_handle, ff_lastname, mask_len, mask);
2371
2372 WSET(param, 0, ff_dir_handle); /* search handle */
2373 WSET(param, 2, max_matches); /* max count */
2374 WSET(param, 4, info_level);
2375 DSET(param, 6, 0);
2376 WSET(param, 10, SMB_CONTINUE_BIT|SMB_CLOSE_IF_END);
2377 }
2378
2379 req->rq_trans2_command = command;
2380 req->rq_ldata = 0;
2381 req->rq_data = NULL;
2382 req->rq_lparm = 12 + mask_len + 1;
2383 req->rq_parm = param;
2384 req->rq_flags = 0;
2385 result = smb_add_request(req);
2386 if (result < 0) {
2387 PARANOIA("error=%d, breaking\n", result);
2388 break;
2389 }
2390
2391 if (req->rq_rcls == ERRSRV && req->rq_err == ERRerror) {
2392 /* a damn Win95 bug - sometimes it clags if you
2393 ask it too fast */
2394 schedule_timeout_interruptible(msecs_to_jiffies(200));
2395 continue;
2396 }
2397
2398 if (req->rq_rcls != 0) {
2399 result = smb_errno(req);
2400 PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
2401 mask, result, req->rq_rcls, req->rq_err);
2402 break;
2403 }
2404
2405 /* parse out some important return info */
2406 if (first != 0) {
2407 ff_dir_handle = WVAL(req->rq_parm, 0);
2408 ff_searchcount = WVAL(req->rq_parm, 2);
2409 ff_eos = WVAL(req->rq_parm, 4);
2410 ff_lastname = WVAL(req->rq_parm, 8);
2411 } else {
2412 ff_searchcount = WVAL(req->rq_parm, 0);
2413 ff_eos = WVAL(req->rq_parm, 2);
2414 ff_lastname = WVAL(req->rq_parm, 6);
2415 }
2416
2417 if (ff_searchcount == 0)
2418 break;
2419
2420 /* Now we are ready to parse smb directory entries. */
2421
2422 /* point to the data bytes */
2423 p = req->rq_data;
2424 for (i = 0; i < ff_searchcount; i++) {
2425 /* make sure we stay within the buffer */
2426 if (p >= req->rq_data + req->rq_ldata) {
2427 printk(KERN_ERR "smb_proc_readdir_long: "
2428 "dirent pointer outside buffer! "
2429 "%p %d@%p\n",
2430 p, req->rq_ldata, req->rq_data);
2431 result = -EIO; /* always a comm. error? */
2432 goto out_free;
2433 }
2434
2435 p = smb_decode_long_dirent(server, p, info_level,
2436 &qname, &fattr, name_buf);
2437
2438 /* ignore . and .. from the server */
2439 if (entries_seen == 2 && qname.name[0] == '.') {
2440 if (qname.len == 1)
2441 continue;
2442 if (qname.name[1] == '.' && qname.len == 2)
2443 continue;
2444 }
2445
2446 if (!smb_fill_cache(filp, dirent, filldir, ctl,
2447 &qname, &fattr))
2448 ; /* stop reading? */
2449 entries_seen++;
2450 }
2451
2452 VERBOSE("received %d entries, eos=%d\n", ff_searchcount,ff_eos);
2453
2454 /*
2455 * We might need the lastname for continuations.
2456 *
2457 * Note that some servers (win95?) point to the filename and
2458 * others (NT4, Samba using NT1) to the dir entry. We assume
2459 * here that those who do not point to a filename do not need
2460 * this info to continue the listing.
2461 *
2462 * OS/2 needs this and talks infolevel 1.
2463 * NetApps want lastname with infolevel 260.
2464 * win2k want lastname with infolevel 260, and points to
2465 * the record not to the name.
2466 * Samba+CifsUnixExt doesn't need lastname.
2467 *
2468 * Both are happy if we return the data they point to. So we do.
2469 * (FIXME: above is not true with win2k)
2470 */
2471 mask_len = 0;
2472 if (info_level != SMB_FIND_FILE_UNIX &&
2473 ff_lastname > 0 && ff_lastname < req->rq_ldata) {
2474 lastname = req->rq_data + ff_lastname;
2475
2476 switch (info_level) {
2477 case 260:
2478 mask_len = req->rq_ldata - ff_lastname;
2479 break;
2480 case 1:
2481 /* lastname points to a length byte */
2482 mask_len = *lastname++;
2483 if (ff_lastname + 1 + mask_len > req->rq_ldata)
2484 mask_len = req->rq_ldata - ff_lastname - 1;
2485 break;
2486 }
2487
2488 /*
2489 * Update the mask string for the next message.
2490 */
2491 if (mask_len > 255)
2492 mask_len = 255;
2493 if (mask_len)
2494 strncpy(mask, lastname, mask_len);
2495 }
2496 mask_len = strnlen(mask, mask_len);
2497 VERBOSE("new mask, len=%d@%d of %d, mask=%.*s\n",
2498 mask_len, ff_lastname, req->rq_ldata, mask_len, mask);
2499
2500 first = 0;
2501 loop_count = 0;
2502 }
2503
2504out_free:
2505 smb_rput(req);
2506out_name:
2507 kfree(name_buf);
2508out:
2509 unlock_kernel();
2510 return result;
2511}
2512
2513/*
2514 * This version uses the trans2 TRANSACT2_FINDFIRST message
2515 * to get the attribute data.
2516 *
2517 * Bugs Noted:
2518 */
2519static int
2520smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
2521 struct smb_fattr *fattr)
2522{
2523 char *param, *mask;
2524 __u16 date, time;
2525 int mask_len, result;
2526 struct smb_request *req;
2527
2528 result = -ENOMEM;
2529 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2530 goto out;
2531 param = req->rq_buffer;
2532 mask = param + 12;
2533
2534 mask_len = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dentry,NULL);
2535 if (mask_len < 0) {
2536 result = mask_len;
2537 goto out_free;
2538 }
2539 VERBOSE("name=%s, len=%d\n", mask, mask_len);
2540 WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
2541 WSET(param, 2, 1); /* max count */
2542 WSET(param, 4, 1); /* close after this call */
2543 WSET(param, 6, 1); /* info_level */
2544 DSET(param, 8, 0);
2545
2546 req->rq_trans2_command = TRANSACT2_FINDFIRST;
2547 req->rq_ldata = 0;
2548 req->rq_data = NULL;
2549 req->rq_lparm = 12 + mask_len;
2550 req->rq_parm = param;
2551 req->rq_flags = 0;
2552 result = smb_add_request(req);
2553 if (result < 0)
2554 goto out_free;
2555 if (req->rq_rcls != 0) {
2556 result = smb_errno(req);
2557#ifdef SMBFS_PARANOIA
2558 if (result != -ENOENT)
2559 PARANOIA("error for %s, rcls=%d, err=%d\n",
2560 mask, req->rq_rcls, req->rq_err);
2561#endif
2562 goto out_free;
2563 }
2564 /* Make sure we got enough data ... */
2565 result = -EINVAL;
2566 if (req->rq_ldata < 22 || WVAL(req->rq_parm, 2) != 1) {
2567 PARANOIA("bad result for %s, len=%d, count=%d\n",
2568 mask, req->rq_ldata, WVAL(req->rq_parm, 2));
2569 goto out_free;
2570 }
2571
2572 /*
2573 * Decode the response into the fattr ...
2574 */
2575 date = WVAL(req->rq_data, 0);
2576 time = WVAL(req->rq_data, 2);
2577 fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
2578 fattr->f_ctime.tv_nsec = 0;
2579
2580 date = WVAL(req->rq_data, 4);
2581 time = WVAL(req->rq_data, 6);
2582 fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
2583 fattr->f_atime.tv_nsec = 0;
2584
2585 date = WVAL(req->rq_data, 8);
2586 time = WVAL(req->rq_data, 10);
2587 fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
2588 fattr->f_mtime.tv_nsec = 0;
2589 VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
2590 mask, date, time, fattr->f_mtime.tv_sec);
2591 fattr->f_size = DVAL(req->rq_data, 12);
2592 /* ULONG allocation size */
2593 fattr->attr = WVAL(req->rq_data, 20);
2594 result = 0;
2595
2596out_free:
2597 smb_rput(req);
2598out:
2599 return result;
2600}
2601
2602static int
2603smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
2604 struct smb_fattr *fattr)
2605{
2606 int result;
2607 char *p;
2608 struct smb_request *req;
2609
2610 result = -ENOMEM;
2611 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2612 goto out;
2613
2614 p = smb_setup_header(req, SMBgetatr, 0, 0);
2615 result = smb_simple_encode_path(req, &p, dir, NULL);
2616 if (result < 0)
2617 goto out_free;
2618 smb_setup_bcc(req, p);
2619
2620 if ((result = smb_request_ok(req, SMBgetatr, 10, 0)) < 0)
2621 goto out_free;
2622 fattr->attr = WVAL(req->rq_header, smb_vwv0);
2623 fattr->f_mtime.tv_sec = local2utc(server, DVAL(req->rq_header, smb_vwv1));
2624 fattr->f_mtime.tv_nsec = 0;
2625 fattr->f_size = DVAL(req->rq_header, smb_vwv3);
2626 fattr->f_ctime = fattr->f_mtime;
2627 fattr->f_atime = fattr->f_mtime;
2628#ifdef SMBFS_DEBUG_TIMESTAMP
2629 printk("getattr_core: %s/%s, mtime=%ld\n",
2630 DENTRY_PATH(dir), fattr->f_mtime);
2631#endif
2632 result = 0;
2633
2634out_free:
2635 smb_rput(req);
2636out:
2637 return result;
2638}
2639
2640/*
2641 * Bugs Noted:
2642 * (1) Win 95 swaps the date and time fields in the standard info level.
2643 */
2644static int
2645smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
2646 struct smb_request *req, int infolevel)
2647{
2648 char *p, *param;
2649 int result;
2650
2651 param = req->rq_buffer;
2652 WSET(param, 0, infolevel);
2653 DSET(param, 2, 0);
2654 result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
2655 if (result < 0)
2656 goto out;
2657 p = param + 6 + result;
2658
2659 req->rq_trans2_command = TRANSACT2_QPATHINFO;
2660 req->rq_ldata = 0;
2661 req->rq_data = NULL;
2662 req->rq_lparm = p - param;
2663 req->rq_parm = param;
2664 req->rq_flags = 0;
2665 result = smb_add_request(req);
2666 if (result < 0)
2667 goto out;
2668 if (req->rq_rcls != 0) {
2669 VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
2670 &param[6], result, req->rq_rcls, req->rq_err);
2671 result = smb_errno(req);
2672 goto out;
2673 }
2674 result = -ENOENT;
2675 if (req->rq_ldata < 22) {
2676 PARANOIA("not enough data for %s, len=%d\n",
2677 &param[6], req->rq_ldata);
2678 goto out;
2679 }
2680
2681 result = 0;
2682out:
2683 return result;
2684}
2685
2686static int
2687smb_proc_getattr_trans2_std(struct smb_sb_info *server, struct dentry *dir,
2688 struct smb_fattr *attr)
2689{
2690 u16 date, time;
2691 int off_date = 0, off_time = 2;
2692 int result;
2693 struct smb_request *req;
2694
2695 result = -ENOMEM;
2696 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2697 goto out;
2698
2699 result = smb_proc_getattr_trans2(server, dir, req, SMB_INFO_STANDARD);
2700 if (result < 0)
2701 goto out_free;
2702
2703 /*
2704 * Kludge alert: Win 95 swaps the date and time field,
2705 * contrary to the CIFS docs and Win NT practice.
2706 */
2707 if (server->mnt->flags & SMB_MOUNT_WIN95) {
2708 off_date = 2;
2709 off_time = 0;
2710 }
2711 date = WVAL(req->rq_data, off_date);
2712 time = WVAL(req->rq_data, off_time);
2713 attr->f_ctime.tv_sec = date_dos2unix(server, date, time);
2714 attr->f_ctime.tv_nsec = 0;
2715
2716 date = WVAL(req->rq_data, 4 + off_date);
2717 time = WVAL(req->rq_data, 4 + off_time);
2718 attr->f_atime.tv_sec = date_dos2unix(server, date, time);
2719 attr->f_atime.tv_nsec = 0;
2720
2721 date = WVAL(req->rq_data, 8 + off_date);
2722 time = WVAL(req->rq_data, 8 + off_time);
2723 attr->f_mtime.tv_sec = date_dos2unix(server, date, time);
2724 attr->f_mtime.tv_nsec = 0;
2725#ifdef SMBFS_DEBUG_TIMESTAMP
2726 printk(KERN_DEBUG "getattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n",
2727 DENTRY_PATH(dir), date, time, attr->f_mtime);
2728#endif
2729 attr->f_size = DVAL(req->rq_data, 12);
2730 attr->attr = WVAL(req->rq_data, 20);
2731
2732out_free:
2733 smb_rput(req);
2734out:
2735 return result;
2736}
2737
2738static int
2739smb_proc_getattr_trans2_all(struct smb_sb_info *server, struct dentry *dir,
2740 struct smb_fattr *attr)
2741{
2742 struct smb_request *req;
2743 int result;
2744
2745 result = -ENOMEM;
2746 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2747 goto out;
2748
2749 result = smb_proc_getattr_trans2(server, dir, req,
2750 SMB_QUERY_FILE_ALL_INFO);
2751 if (result < 0)
2752 goto out_free;
2753
2754 attr->f_ctime = smb_ntutc2unixutc(LVAL(req->rq_data, 0));
2755 attr->f_atime = smb_ntutc2unixutc(LVAL(req->rq_data, 8));
2756 attr->f_mtime = smb_ntutc2unixutc(LVAL(req->rq_data, 16));
2757 /* change (24) */
2758 attr->attr = WVAL(req->rq_data, 32);
2759 /* pad? (34) */
2760 /* allocated size (40) */
2761 attr->f_size = LVAL(req->rq_data, 48);
2762
2763out_free:
2764 smb_rput(req);
2765out:
2766 return result;
2767}
2768
2769static int
2770smb_proc_getattr_unix(struct smb_sb_info *server, struct dentry *dir,
2771 struct smb_fattr *attr)
2772{
2773 struct smb_request *req;
2774 int result;
2775
2776 result = -ENOMEM;
2777 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2778 goto out;
2779
2780 result = smb_proc_getattr_trans2(server, dir, req,
2781 SMB_QUERY_FILE_UNIX_BASIC);
2782 if (result < 0)
2783 goto out_free;
2784
2785 smb_decode_unix_basic(attr, server, req->rq_data);
2786
2787out_free:
2788 smb_rput(req);
2789out:
2790 return result;
2791}
2792
2793static int
2794smb_proc_getattr_95(struct smb_sb_info *server, struct dentry *dir,
2795 struct smb_fattr *attr)
2796{
2797 struct inode *inode = dir->d_inode;
2798 int result;
2799
2800 /* FIXME: why not use the "all" version? */
2801 result = smb_proc_getattr_trans2_std(server, dir, attr);
2802 if (result < 0)
2803 goto out;
2804
2805 /*
2806 * None of the getattr versions here can make win9x return the right
2807 * filesize if there are changes made to an open file.
2808 * A seek-to-end does return the right size, but we only need to do
2809 * that on files we have written.
2810 */
2811 if (inode && SMB_I(inode)->flags & SMB_F_LOCALWRITE &&
2812 smb_is_open(inode))
2813 {
2814 __u16 fileid = SMB_I(inode)->fileid;
2815 attr->f_size = smb_proc_seek(server, fileid, 2, 0);
2816 }
2817
2818out:
2819 return result;
2820}
2821
2822static int
2823smb_proc_ops_wait(struct smb_sb_info *server)
2824{
2825 int result;
2826
2827 result = wait_event_interruptible_timeout(server->conn_wq,
2828 server->conn_complete, 30*HZ);
2829
2830 if (!result || signal_pending(current))
2831 return -EIO;
2832
2833 return 0;
2834}
2835
2836static int
2837smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
2838 struct smb_fattr *fattr)
2839{
2840 int result;
2841
2842 if (smb_proc_ops_wait(server) < 0)
2843 return -EIO;
2844
2845 smb_init_dirent(server, fattr);
2846 result = server->ops->getattr(server, dir, fattr);
2847 smb_finish_dirent(server, fattr);
2848
2849 return result;
2850}
2851
2852static int
2853smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
2854 struct smb_cache_control *ctl)
2855{
2856 struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry);
2857
2858 if (smb_proc_ops_wait(server) < 0)
2859 return -EIO;
2860
2861 return server->ops->readdir(filp, dirent, filldir, ctl);
2862}
2863
2864int
2865smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
2866{
2867 struct smb_sb_info *server = server_from_dentry(dir);
2868 int result;
2869
2870 smb_init_dirent(server, fattr);
2871 result = server->ops->getattr(server, dir, fattr);
2872 smb_finish_dirent(server, fattr);
2873
2874 return result;
2875}
2876
2877
2878/*
2879 * Because of bugs in the core protocol, we use this only to set
2880 * attributes. See smb_proc_settime() below for timestamp handling.
2881 *
2882 * Bugs Noted:
2883 * (1) If mtime is non-zero, both Win 3.1 and Win 95 fail
2884 * with an undocumented error (ERRDOS code 50). Setting
2885 * mtime to 0 allows the attributes to be set.
2886 * (2) The extra parameters following the name string aren't
2887 * in the CIFS docs, but seem to be necessary for operation.
2888 */
2889static int
2890smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
2891 __u16 attr)
2892{
2893 char *p;
2894 int result;
2895 struct smb_request *req;
2896
2897 result = -ENOMEM;
2898 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
2899 goto out;
2900
2901 p = smb_setup_header(req, SMBsetatr, 8, 0);
2902 WSET(req->rq_header, smb_vwv0, attr);
2903 DSET(req->rq_header, smb_vwv1, 0); /* mtime */
2904 WSET(req->rq_header, smb_vwv3, 0); /* reserved values */
2905 WSET(req->rq_header, smb_vwv4, 0);
2906 WSET(req->rq_header, smb_vwv5, 0);
2907 WSET(req->rq_header, smb_vwv6, 0);
2908 WSET(req->rq_header, smb_vwv7, 0);
2909 result = smb_simple_encode_path(req, &p, dentry, NULL);
2910 if (result < 0)
2911 goto out_free;
2912 if (p + 2 > (char *)req->rq_buffer + req->rq_bufsize) {
2913 result = -ENAMETOOLONG;
2914 goto out_free;
2915 }
2916 *p++ = 4;
2917 *p++ = 0;
2918 smb_setup_bcc(req, p);
2919
2920 result = smb_request_ok(req, SMBsetatr, 0, 0);
2921 if (result < 0)
2922 goto out_free;
2923 result = 0;
2924
2925out_free:
2926 smb_rput(req);
2927out:
2928 return result;
2929}
2930
2931/*
2932 * Because of bugs in the trans2 setattr messages, we must set
2933 * attributes and timestamps separately. The core SMBsetatr
2934 * message seems to be the only reliable way to set attributes.
2935 */
2936int
2937smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr)
2938{
2939 struct smb_sb_info *server = server_from_dentry(dir);
2940 int result;
2941
2942 VERBOSE("setting %s/%s, open=%d\n",
2943 DENTRY_PATH(dir), smb_is_open(dir->d_inode));
2944 result = smb_proc_setattr_core(server, dir, fattr->attr);
2945 return result;
2946}
2947
2948/*
2949 * Sets the timestamps for an file open with write permissions.
2950 */
2951static int
2952smb_proc_setattr_ext(struct smb_sb_info *server,
2953 struct inode *inode, struct smb_fattr *fattr)
2954{
2955 __u16 date, time;
2956 int result;
2957 struct smb_request *req;
2958
2959 result = -ENOMEM;
2960 if (! (req = smb_alloc_request(server, 0)))
2961 goto out;
2962
2963 smb_setup_header(req, SMBsetattrE, 7, 0);
2964 WSET(req->rq_header, smb_vwv0, SMB_I(inode)->fileid);
2965 /* We don't change the creation time */
2966 WSET(req->rq_header, smb_vwv1, 0);
2967 WSET(req->rq_header, smb_vwv2, 0);
2968 date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
2969 WSET(req->rq_header, smb_vwv3, date);
2970 WSET(req->rq_header, smb_vwv4, time);
2971 date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
2972 WSET(req->rq_header, smb_vwv5, date);
2973 WSET(req->rq_header, smb_vwv6, time);
2974#ifdef SMBFS_DEBUG_TIMESTAMP
2975 printk(KERN_DEBUG "smb_proc_setattr_ext: date=%d, time=%d, mtime=%ld\n",
2976 date, time, fattr->f_mtime);
2977#endif
2978
2979 req->rq_flags |= SMB_REQ_NORETRY;
2980 result = smb_request_ok(req, SMBsetattrE, 0, 0);
2981 if (result < 0)
2982 goto out_free;
2983 result = 0;
2984out_free:
2985 smb_rput(req);
2986out:
2987 return result;
2988}
2989
2990/*
2991 * Bugs Noted:
2992 * (1) The TRANSACT2_SETPATHINFO message under Win NT 4.0 doesn't
2993 * set the file's attribute flags.
2994 */
2995static int
2996smb_proc_setattr_trans2(struct smb_sb_info *server,
2997 struct dentry *dir, struct smb_fattr *fattr)
2998{
2999 __u16 date, time;
3000 char *p, *param;
3001 int result;
3002 char data[26];
3003 struct smb_request *req;
3004
3005 result = -ENOMEM;
3006 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
3007 goto out;
3008 param = req->rq_buffer;
3009
3010 WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */
3011 DSET(param, 2, 0);
3012 result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
3013 if (result < 0)
3014 goto out_free;
3015 p = param + 6 + result;
3016
3017 WSET(data, 0, 0); /* creation time */
3018 WSET(data, 2, 0);
3019 date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
3020 WSET(data, 4, date);
3021 WSET(data, 6, time);
3022 date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
3023 WSET(data, 8, date);
3024 WSET(data, 10, time);
3025#ifdef SMBFS_DEBUG_TIMESTAMP
3026 printk(KERN_DEBUG "setattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n",
3027 DENTRY_PATH(dir), date, time, fattr->f_mtime);
3028#endif
3029 DSET(data, 12, 0); /* size */
3030 DSET(data, 16, 0); /* blksize */
3031 WSET(data, 20, 0); /* attr */
3032 DSET(data, 22, 0); /* ULONG EA size */
3033
3034 req->rq_trans2_command = TRANSACT2_SETPATHINFO;
3035 req->rq_ldata = 26;
3036 req->rq_data = data;
3037 req->rq_lparm = p - param;
3038 req->rq_parm = param;
3039 req->rq_flags = 0;
3040 result = smb_add_request(req);
3041 if (result < 0)
3042 goto out_free;
3043 result = 0;
3044 if (req->rq_rcls != 0)
3045 result = smb_errno(req);
3046
3047out_free:
3048 smb_rput(req);
3049out:
3050 return result;
3051}
3052
3053/*
3054 * ATTR_MODE 0x001
3055 * ATTR_UID 0x002
3056 * ATTR_GID 0x004
3057 * ATTR_SIZE 0x008
3058 * ATTR_ATIME 0x010
3059 * ATTR_MTIME 0x020
3060 * ATTR_CTIME 0x040
3061 * ATTR_ATIME_SET 0x080
3062 * ATTR_MTIME_SET 0x100
3063 * ATTR_FORCE 0x200
3064 * ATTR_ATTR_FLAG 0x400
3065 *
3066 * major/minor should only be set by mknod.
3067 */
3068int
3069smb_proc_setattr_unix(struct dentry *d, struct iattr *attr,
3070 unsigned int major, unsigned int minor)
3071{
3072 struct smb_sb_info *server = server_from_dentry(d);
3073 u64 nttime;
3074 char *p, *param;
3075 int result;
3076 char data[100];
3077 struct smb_request *req;
3078
3079 result = -ENOMEM;
3080 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
3081 goto out;
3082 param = req->rq_buffer;
3083
3084 DEBUG1("valid flags = 0x%04x\n", attr->ia_valid);
3085
3086 WSET(param, 0, SMB_SET_FILE_UNIX_BASIC);
3087 DSET(param, 2, 0);
3088 result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, d, NULL);
3089 if (result < 0)
3090 goto out_free;
3091 p = param + 6 + result;
3092
3093 /* 0 L file size in bytes */
3094 /* 8 L file size on disk in bytes (block count) */
3095 /* 40 L uid */
3096 /* 48 L gid */
3097 /* 56 W file type enum */
3098 /* 60 L devmajor */
3099 /* 68 L devminor */
3100 /* 76 L unique ID (inode) */
3101 /* 84 L permissions */
3102 /* 92 L link count */
3103 LSET(data, 0, SMB_SIZE_NO_CHANGE);
3104 LSET(data, 8, SMB_SIZE_NO_CHANGE);
3105 LSET(data, 16, SMB_TIME_NO_CHANGE);
3106 LSET(data, 24, SMB_TIME_NO_CHANGE);
3107 LSET(data, 32, SMB_TIME_NO_CHANGE);
3108 LSET(data, 40, SMB_UID_NO_CHANGE);
3109 LSET(data, 48, SMB_GID_NO_CHANGE);
3110 DSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
3111 LSET(data, 60, major);
3112 LSET(data, 68, minor);
3113 LSET(data, 76, 0);
3114 LSET(data, 84, SMB_MODE_NO_CHANGE);
3115 LSET(data, 92, 0);
3116
3117 if (attr->ia_valid & ATTR_SIZE) {
3118 LSET(data, 0, attr->ia_size);
3119 LSET(data, 8, 0); /* can't set anyway */
3120 }
3121
3122 /*
3123 * FIXME: check the conversion function it the correct one
3124 *
3125 * we can't set ctime but we might as well pass this to the server
3126 * and let it ignore it.
3127 */
3128 if (attr->ia_valid & ATTR_CTIME) {
3129 nttime = smb_unixutc2ntutc(attr->ia_ctime);
3130 LSET(data, 16, nttime);
3131 }
3132 if (attr->ia_valid & ATTR_ATIME) {
3133 nttime = smb_unixutc2ntutc(attr->ia_atime);
3134 LSET(data, 24, nttime);
3135 }
3136 if (attr->ia_valid & ATTR_MTIME) {
3137 nttime = smb_unixutc2ntutc(attr->ia_mtime);
3138 LSET(data, 32, nttime);
3139 }
3140
3141 if (attr->ia_valid & ATTR_UID) {
3142 LSET(data, 40, attr->ia_uid);
3143 }
3144 if (attr->ia_valid & ATTR_GID) {
3145 LSET(data, 48, attr->ia_gid);
3146 }
3147
3148 if (attr->ia_valid & ATTR_MODE) {
3149 LSET(data, 84, attr->ia_mode);
3150 }
3151
3152 req->rq_trans2_command = TRANSACT2_SETPATHINFO;
3153 req->rq_ldata = 100;
3154 req->rq_data = data;
3155 req->rq_lparm = p - param;
3156 req->rq_parm = param;
3157 req->rq_flags = 0;
3158 result = smb_add_request(req);
3159
3160out_free:
3161 smb_rput(req);
3162out:
3163 return result;
3164}
3165
3166
3167/*
3168 * Set the modify and access timestamps for a file.
3169 *
3170 * Incredibly enough, in all of SMB there is no message to allow
3171 * setting both attributes and timestamps at once.
3172 *
3173 * Bugs Noted:
3174 * (1) Win 95 doesn't support the TRANSACT2_SETFILEINFO message
3175 * with info level 1 (INFO_STANDARD).
3176 * (2) Win 95 seems not to support setting directory timestamps.
3177 * (3) Under the core protocol apparently the only way to set the
3178 * timestamp is to open and close the file.
3179 */
3180int
3181smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
3182{
3183 struct smb_sb_info *server = server_from_dentry(dentry);
3184 struct inode *inode = dentry->d_inode;
3185 int result;
3186
3187 VERBOSE("setting %s/%s, open=%d\n",
3188 DENTRY_PATH(dentry), smb_is_open(inode));
3189
3190 /* setting the time on a Win95 server fails (tridge) */
3191 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 &&
3192 !(server->mnt->flags & SMB_MOUNT_WIN95)) {
3193 if (smb_is_open(inode) && SMB_I(inode)->access != SMB_O_RDONLY)
3194 result = smb_proc_setattr_ext(server, inode, fattr);
3195 else
3196 result = smb_proc_setattr_trans2(server, dentry, fattr);
3197 } else {
3198 /*
3199 * Fail silently on directories ... timestamp can't be set?
3200 */
3201 result = 0;
3202 if (S_ISREG(inode->i_mode)) {
3203 /*
3204 * Set the mtime by opening and closing the file.
3205 * Note that the file is opened read-only, but this
3206 * still allows us to set the date (tridge)
3207 */
3208 result = -EACCES;
3209 if (!smb_is_open(inode))
3210 smb_proc_open(server, dentry, SMB_O_RDONLY);
3211 if (smb_is_open(inode)) {
3212 inode->i_mtime = fattr->f_mtime;
3213 result = smb_proc_close_inode(server, inode);
3214 }
3215 }
3216 }
3217
3218 return result;
3219}
3220
3221int
3222smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr)
3223{
3224 struct smb_sb_info *server = SMB_SB(dentry->d_sb);
3225 int result;
3226 char *p;
3227 long unit;
3228 struct smb_request *req;
3229
3230 result = -ENOMEM;
3231 if (! (req = smb_alloc_request(server, 0)))
3232 goto out;
3233
3234 smb_setup_header(req, SMBdskattr, 0, 0);
3235 if ((result = smb_request_ok(req, SMBdskattr, 5, 0)) < 0)
3236 goto out_free;
3237 p = SMB_VWV(req->rq_header);
3238 unit = (WVAL(p, 2) * WVAL(p, 4)) >> SMB_ST_BLKSHIFT;
3239 attr->f_blocks = WVAL(p, 0) * unit;
3240 attr->f_bsize = SMB_ST_BLKSIZE;
3241 attr->f_bavail = attr->f_bfree = WVAL(p, 6) * unit;
3242 result = 0;
3243
3244out_free:
3245 smb_rput(req);
3246out:
3247 return result;
3248}
3249
3250int
3251smb_proc_read_link(struct smb_sb_info *server, struct dentry *d,
3252 char *buffer, int len)
3253{
3254 char *p, *param;
3255 int result;
3256 struct smb_request *req;
3257
3258 DEBUG1("readlink of %s/%s\n", DENTRY_PATH(d));
3259
3260 result = -ENOMEM;
3261 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
3262 goto out;
3263 param = req->rq_buffer;
3264
3265 WSET(param, 0, SMB_QUERY_FILE_UNIX_LINK);
3266 DSET(param, 2, 0);
3267 result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, d, NULL);
3268 if (result < 0)
3269 goto out_free;
3270 p = param + 6 + result;
3271
3272 req->rq_trans2_command = TRANSACT2_QPATHINFO;
3273 req->rq_ldata = 0;
3274 req->rq_data = NULL;
3275 req->rq_lparm = p - param;
3276 req->rq_parm = param;
3277 req->rq_flags = 0;
3278 result = smb_add_request(req);
3279 if (result < 0)
3280 goto out_free;
3281 DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
3282 &param[6], result, req->rq_rcls, req->rq_err);
3283
3284 /* copy data up to the \0 or buffer length */
3285 result = len;
3286 if (req->rq_ldata < len)
3287 result = req->rq_ldata;
3288 strncpy(buffer, req->rq_data, result);
3289
3290out_free:
3291 smb_rput(req);
3292out:
3293 return result;
3294}
3295
3296
3297/*
3298 * Create a symlink object called dentry which points to oldpath.
3299 * Samba does not permit dangling links but returns a suitable error message.
3300 */
3301int
3302smb_proc_symlink(struct smb_sb_info *server, struct dentry *d,
3303 const char *oldpath)
3304{
3305 char *p, *param;
3306 int result;
3307 struct smb_request *req;
3308
3309 result = -ENOMEM;
3310 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
3311 goto out;
3312 param = req->rq_buffer;
3313
3314 WSET(param, 0, SMB_SET_FILE_UNIX_LINK);
3315 DSET(param, 2, 0);
3316 result = smb_encode_path(server, param + 6, SMB_MAXPATHLEN+1, d, NULL);
3317 if (result < 0)
3318 goto out_free;
3319 p = param + 6 + result;
3320
3321 req->rq_trans2_command = TRANSACT2_SETPATHINFO;
3322 req->rq_ldata = strlen(oldpath) + 1;
3323 req->rq_data = (char *) oldpath;
3324 req->rq_lparm = p - param;
3325 req->rq_parm = param;
3326 req->rq_flags = 0;
3327 result = smb_add_request(req);
3328 if (result < 0)
3329 goto out_free;
3330
3331 DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
3332 &param[6], result, req->rq_rcls, req->rq_err);
3333 result = 0;
3334
3335out_free:
3336 smb_rput(req);
3337out:
3338 return result;
3339}
3340
3341/*
3342 * Create a hard link object called new_dentry which points to dentry.
3343 */
3344int
3345smb_proc_link(struct smb_sb_info *server, struct dentry *dentry,
3346 struct dentry *new_dentry)
3347{
3348 char *p, *param;
3349 int result;
3350 struct smb_request *req;
3351
3352 result = -ENOMEM;
3353 if (! (req = smb_alloc_request(server, PAGE_SIZE)))
3354 goto out;
3355 param = req->rq_buffer;
3356
3357 WSET(param, 0, SMB_SET_FILE_UNIX_HLINK);
3358 DSET(param, 2, 0);
3359 result = smb_encode_path(server, param + 6, SMB_MAXPATHLEN+1,
3360 new_dentry, NULL);
3361 if (result < 0)
3362 goto out_free;
3363 p = param + 6 + result;
3364
3365 /* Grr, pointless separation of parameters and data ... */
3366 req->rq_data = p;
3367 req->rq_ldata = smb_encode_path(server, p, SMB_MAXPATHLEN+1,
3368 dentry, NULL);
3369
3370 req->rq_trans2_command = TRANSACT2_SETPATHINFO;
3371 req->rq_lparm = p - param;
3372 req->rq_parm = param;
3373 req->rq_flags = 0;
3374 result = smb_add_request(req);
3375 if (result < 0)
3376 goto out_free;
3377
3378 DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
3379 &param[6], result, req->rq_rcls, req->rq_err);
3380 result = 0;
3381
3382out_free:
3383 smb_rput(req);
3384out:
3385 return result;
3386}
3387
3388static int
3389smb_proc_query_cifsunix(struct smb_sb_info *server)
3390{
3391 int result;
3392 int major, minor;
3393 u64 caps;
3394 char param[2];
3395 struct smb_request *req;
3396
3397 result = -ENOMEM;
3398 if (! (req = smb_alloc_request(server, 100)))
3399 goto out;
3400
3401 WSET(param, 0, SMB_QUERY_CIFS_UNIX_INFO);
3402
3403 req->rq_trans2_command = TRANSACT2_QFSINFO;
3404 req->rq_ldata = 0;
3405 req->rq_data = NULL;
3406 req->rq_lparm = 2;
3407 req->rq_parm = param;
3408 req->rq_flags = 0;
3409 result = smb_add_request(req);
3410 if (result < 0)
3411 goto out_free;
3412
3413 if (req->rq_ldata < 12) {
3414 PARANOIA("Not enough data\n");
3415 goto out_free;
3416 }
3417 major = WVAL(req->rq_data, 0);
3418 minor = WVAL(req->rq_data, 2);
3419
3420 DEBUG1("Server implements CIFS Extensions for UNIX systems v%d.%d\n",
3421 major, minor);
3422 /* FIXME: verify that we are ok with this major/minor? */
3423
3424 caps = LVAL(req->rq_data, 4);
3425 DEBUG1("Server capabilities 0x%016llx\n", caps);
3426
3427out_free:
3428 smb_rput(req);
3429out:
3430 return result;
3431}
3432
3433
3434static void
3435install_ops(struct smb_ops *dst, struct smb_ops *src)
3436{
3437 memcpy(dst, src, sizeof(void *) * SMB_OPS_NUM_STATIC);
3438}
3439
3440/* < LANMAN2 */
3441static struct smb_ops smb_ops_core =
3442{
3443 .read = smb_proc_read,
3444 .write = smb_proc_write,
3445 .readdir = smb_proc_readdir_short,
3446 .getattr = smb_proc_getattr_core,
3447 .truncate = smb_proc_trunc32,
3448};
3449
3450/* LANMAN2, OS/2, others? */
3451static struct smb_ops smb_ops_os2 =
3452{
3453 .read = smb_proc_read,
3454 .write = smb_proc_write,
3455 .readdir = smb_proc_readdir_long,
3456 .getattr = smb_proc_getattr_trans2_std,
3457 .truncate = smb_proc_trunc32,
3458};
3459
3460/* Win95, and possibly some NetApp versions too */
3461static struct smb_ops smb_ops_win95 =
3462{
3463 .read = smb_proc_read, /* does not support 12word readX */
3464 .write = smb_proc_write,
3465 .readdir = smb_proc_readdir_long,
3466 .getattr = smb_proc_getattr_95,
3467 .truncate = smb_proc_trunc95,
3468};
3469
3470/* Samba, NT4 and NT5 */
3471static struct smb_ops smb_ops_winNT =
3472{
3473 .read = smb_proc_readX,
3474 .write = smb_proc_writeX,
3475 .readdir = smb_proc_readdir_long,
3476 .getattr = smb_proc_getattr_trans2_all,
3477 .truncate = smb_proc_trunc64,
3478};
3479
3480/* Samba w/ unix extensions. Others? */
3481static struct smb_ops smb_ops_unix =
3482{
3483 .read = smb_proc_readX,
3484 .write = smb_proc_writeX,
3485 .readdir = smb_proc_readdir_long,
3486 .getattr = smb_proc_getattr_unix,
3487 /* FIXME: core/ext/time setattr needs to be cleaned up! */
3488 /* .setattr = smb_proc_setattr_unix, */
3489 .truncate = smb_proc_trunc64,
3490};
3491
3492/* Place holder until real ops are in place */
3493static struct smb_ops smb_ops_null =
3494{
3495 .readdir = smb_proc_readdir_null,
3496 .getattr = smb_proc_getattr_null,
3497};
3498
3499void smb_install_null_ops(struct smb_ops *ops)
3500{
3501 install_ops(ops, &smb_ops_null);
3502}
diff --git a/drivers/staging/smbfs/proto.h b/drivers/staging/smbfs/proto.h
deleted file mode 100644
index 3883cb16a3f..00000000000
--- a/drivers/staging/smbfs/proto.h
+++ /dev/null
@@ -1,89 +0,0 @@
1/*
2 * Autogenerated with cproto on: Sat Sep 13 17:18:51 CEST 2003
3 */
4
5struct smb_request;
6struct sock;
7struct statfs;
8
9/* proc.c */
10extern int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
11extern __u32 smb_len(__u8 *p);
12extern int smb_get_rsize(struct smb_sb_info *server);
13extern int smb_get_wsize(struct smb_sb_info *server);
14extern int smb_errno(struct smb_request *req);
15extern int smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt);
16extern __u8 *smb_setup_header(struct smb_request *req, __u8 command, __u16 wct, __u16 bcc);
17extern int smb_open(struct dentry *dentry, int wish);
18extern int smb_close(struct inode *ino);
19extern int smb_close_fileid(struct dentry *dentry, __u16 fileid);
20extern int smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid);
21extern int smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry);
22extern int smb_proc_mkdir(struct dentry *dentry);
23extern int smb_proc_rmdir(struct dentry *dentry);
24extern int smb_proc_unlink(struct dentry *dentry);
25extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
26extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr,
27 struct super_block *sb);
28extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
29extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
30extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor);
31extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
32extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr);
33extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len);
34extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
35extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
36extern void smb_install_null_ops(struct smb_ops *ops);
37/* dir.c */
38extern const struct file_operations smb_dir_operations;
39extern const struct inode_operations smb_dir_inode_operations;
40extern const struct inode_operations smb_dir_inode_operations_unix;
41extern const struct dentry_operations smbfs_dentry_operations_case;
42extern const struct dentry_operations smbfs_dentry_operations;
43extern void smb_new_dentry(struct dentry *dentry);
44extern void smb_renew_times(struct dentry *dentry);
45/* cache.c */
46extern void smb_invalid_dir_cache(struct inode *dir);
47extern void smb_invalidate_dircache_entries(struct dentry *parent);
48extern struct dentry *smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos);
49extern int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctrl, struct qstr *qname, struct smb_fattr *entry);
50/* sock.c */
51extern void smb_data_ready(struct sock *sk, int len);
52extern int smb_valid_socket(struct inode *inode);
53extern void smb_close_socket(struct smb_sb_info *server);
54extern int smb_recv_available(struct smb_sb_info *server);
55extern int smb_receive_header(struct smb_sb_info *server);
56extern int smb_receive_drop(struct smb_sb_info *server);
57extern int smb_receive(struct smb_sb_info *server, struct smb_request *req);
58extern int smb_send_request(struct smb_request *req);
59/* inode.c */
60extern struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr);
61extern void smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr);
62extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
63extern void smb_invalidate_inodes(struct smb_sb_info *server);
64extern int smb_revalidate_inode(struct dentry *dentry);
65extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
66extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
67/* file.c */
68extern const struct address_space_operations smb_file_aops;
69extern const struct file_operations smb_file_operations;
70extern const struct inode_operations smb_file_inode_operations;
71/* ioctl.c */
72extern long smb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
73/* smbiod.c */
74extern void smbiod_wake_up(void);
75extern int smbiod_register_server(struct smb_sb_info *server);
76extern void smbiod_unregister_server(struct smb_sb_info *server);
77extern void smbiod_flush(struct smb_sb_info *server);
78extern int smbiod_retry(struct smb_sb_info *server);
79/* request.c */
80extern int smb_init_request_cache(void);
81extern void smb_destroy_request_cache(void);
82extern struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize);
83extern void smb_rput(struct smb_request *req);
84extern int smb_add_request(struct smb_request *req);
85extern int smb_request_send_server(struct smb_sb_info *server);
86extern int smb_request_recv(struct smb_sb_info *server);
87/* symlink.c */
88extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname);
89extern const struct inode_operations smb_link_inode_operations;
diff --git a/drivers/staging/smbfs/request.c b/drivers/staging/smbfs/request.c
deleted file mode 100644
index 3e771686430..00000000000
--- a/drivers/staging/smbfs/request.c
+++ /dev/null
@@ -1,817 +0,0 @@
1/*
2 * request.c
3 *
4 * Copyright (C) 2001 by Urban Widmark
5 *
6 * Please add a note about your changes to smbfs in the ChangeLog file.
7 */
8
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/fs.h>
12#include <linux/slab.h>
13#include <linux/net.h>
14#include <linux/sched.h>
15
16#include "smb_fs.h"
17#include "smbno.h"
18#include "smb_mount.h"
19#include "smb_debug.h"
20#include "request.h"
21#include "proto.h"
22
23/* #define SMB_SLAB_DEBUG (SLAB_RED_ZONE | SLAB_POISON) */
24#define SMB_SLAB_DEBUG 0
25
26/* cache for request structures */
27static struct kmem_cache *req_cachep;
28
29static int smb_request_send_req(struct smb_request *req);
30
31/*
32 /proc/slabinfo:
33 name, active, num, objsize, active_slabs, num_slaps, #pages
34*/
35
36
37int smb_init_request_cache(void)
38{
39 req_cachep = kmem_cache_create("smb_request",
40 sizeof(struct smb_request), 0,
41 SMB_SLAB_DEBUG | SLAB_HWCACHE_ALIGN,
42 NULL);
43 if (req_cachep == NULL)
44 return -ENOMEM;
45
46 return 0;
47}
48
49void smb_destroy_request_cache(void)
50{
51 kmem_cache_destroy(req_cachep);
52}
53
54/*
55 * Allocate and initialise a request structure
56 */
57static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
58 int bufsize)
59{
60 struct smb_request *req;
61 unsigned char *buf = NULL;
62
63 req = kmem_cache_zalloc(req_cachep, GFP_KERNEL);
64 VERBOSE("allocating request: %p\n", req);
65 if (!req)
66 goto out;
67
68 if (bufsize > 0) {
69 buf = kmalloc(bufsize, GFP_NOFS);
70 if (!buf) {
71 kmem_cache_free(req_cachep, req);
72 return NULL;
73 }
74 }
75
76 req->rq_buffer = buf;
77 req->rq_bufsize = bufsize;
78 req->rq_server = server;
79 init_waitqueue_head(&req->rq_wait);
80 INIT_LIST_HEAD(&req->rq_queue);
81 atomic_set(&req->rq_count, 1);
82
83out:
84 return req;
85}
86
87struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize)
88{
89 struct smb_request *req = NULL;
90
91 for (;;) {
92 atomic_inc(&server->nr_requests);
93 if (atomic_read(&server->nr_requests) <= MAX_REQUEST_HARD) {
94 req = smb_do_alloc_request(server, bufsize);
95 if (req != NULL)
96 break;
97 }
98
99#if 0
100 /*
101 * Try to free up at least one request in order to stay
102 * below the hard limit
103 */
104 if (nfs_try_to_free_pages(server))
105 continue;
106
107 if (fatal_signal_pending(current))
108 return ERR_PTR(-ERESTARTSYS);
109 current->policy = SCHED_YIELD;
110 schedule();
111#else
112 /* FIXME: we want something like nfs does above, but that
113 requires changes to all callers and can wait. */
114 break;
115#endif
116 }
117 return req;
118}
119
120static void smb_free_request(struct smb_request *req)
121{
122 atomic_dec(&req->rq_server->nr_requests);
123 if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC))
124 kfree(req->rq_buffer);
125 kfree(req->rq_trans2buffer);
126 kmem_cache_free(req_cachep, req);
127}
128
129/*
130 * What prevents a rget to race with a rput? The count must never drop to zero
131 * while it is in use. Only rput if it is ok that it is free'd.
132 */
133static void smb_rget(struct smb_request *req)
134{
135 atomic_inc(&req->rq_count);
136}
137void smb_rput(struct smb_request *req)
138{
139 if (atomic_dec_and_test(&req->rq_count)) {
140 list_del_init(&req->rq_queue);
141 smb_free_request(req);
142 }
143}
144
145/* setup to receive the data part of the SMB */
146static int smb_setup_bcc(struct smb_request *req)
147{
148 int result = 0;
149 req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
150
151 if (req->rq_rlen > req->rq_bufsize) {
152 PARANOIA("Packet too large %d > %d\n",
153 req->rq_rlen, req->rq_bufsize);
154 return -ENOBUFS;
155 }
156
157 req->rq_iov[0].iov_base = req->rq_buffer;
158 req->rq_iov[0].iov_len = req->rq_rlen;
159 req->rq_iovlen = 1;
160
161 return result;
162}
163
164/*
165 * Prepare a "normal" request structure.
166 */
167static int smb_setup_request(struct smb_request *req)
168{
169 int len = smb_len(req->rq_header) + 4;
170 req->rq_slen = len;
171
172 /* if we expect a data part in the reply we set the iov's to read it */
173 if (req->rq_resp_bcc)
174 req->rq_setup_read = smb_setup_bcc;
175
176 /* This tries to support re-using the same request */
177 req->rq_bytes_sent = 0;
178 req->rq_rcls = 0;
179 req->rq_err = 0;
180 req->rq_errno = 0;
181 req->rq_fragment = 0;
182 kfree(req->rq_trans2buffer);
183 req->rq_trans2buffer = NULL;
184
185 return 0;
186}
187
188/*
189 * Prepare a transaction2 request structure
190 */
191static int smb_setup_trans2request(struct smb_request *req)
192{
193 struct smb_sb_info *server = req->rq_server;
194 int mparam, mdata;
195 static unsigned char padding[4];
196
197 /* I know the following is very ugly, but I want to build the
198 smb packet as efficiently as possible. */
199
200 const int smb_parameters = 15;
201 const int header = SMB_HEADER_LEN + 2 * smb_parameters + 2;
202 const int oparam = ALIGN(header + 3, sizeof(u32));
203 const int odata = ALIGN(oparam + req->rq_lparm, sizeof(u32));
204 const int bcc = (req->rq_data ? odata + req->rq_ldata :
205 oparam + req->rq_lparm) - header;
206
207 if ((bcc + oparam) > server->opt.max_xmit)
208 return -ENOMEM;
209 smb_setup_header(req, SMBtrans2, smb_parameters, bcc);
210
211 /*
212 * max parameters + max data + max setup == bufsize to make NT4 happy
213 * and not abort the transfer or split into multiple responses. It also
214 * makes smbfs happy as handling packets larger than the buffer size
215 * is extra work.
216 *
217 * OS/2 is probably going to hate me for this ...
218 */
219 mparam = SMB_TRANS2_MAX_PARAM;
220 mdata = req->rq_bufsize - mparam;
221
222 mdata = server->opt.max_xmit - mparam - 100;
223 if (mdata < 1024) {
224 mdata = 1024;
225 mparam = 20;
226 }
227
228#if 0
229 /* NT/win2k has ~4k max_xmit, so with this we request more than it wants
230 to return as one SMB. Useful for testing the fragmented trans2
231 handling. */
232 mdata = 8192;
233#endif
234
235 WSET(req->rq_header, smb_tpscnt, req->rq_lparm);
236 WSET(req->rq_header, smb_tdscnt, req->rq_ldata);
237 WSET(req->rq_header, smb_mprcnt, mparam);
238 WSET(req->rq_header, smb_mdrcnt, mdata);
239 WSET(req->rq_header, smb_msrcnt, 0); /* max setup always 0 ? */
240 WSET(req->rq_header, smb_flags, 0);
241 DSET(req->rq_header, smb_timeout, 0);
242 WSET(req->rq_header, smb_pscnt, req->rq_lparm);
243 WSET(req->rq_header, smb_psoff, oparam - 4);
244 WSET(req->rq_header, smb_dscnt, req->rq_ldata);
245 WSET(req->rq_header, smb_dsoff, req->rq_data ? odata - 4 : 0);
246 *(req->rq_header + smb_suwcnt) = 0x01; /* setup count */
247 *(req->rq_header + smb_suwcnt + 1) = 0x00; /* reserved */
248 WSET(req->rq_header, smb_setup0, req->rq_trans2_command);
249
250 req->rq_iovlen = 2;
251 req->rq_iov[0].iov_base = (void *) req->rq_header;
252 req->rq_iov[0].iov_len = oparam;
253 req->rq_iov[1].iov_base = (req->rq_parm==NULL) ? padding : req->rq_parm;
254 req->rq_iov[1].iov_len = req->rq_lparm;
255 req->rq_slen = oparam + req->rq_lparm;
256
257 if (req->rq_data) {
258 req->rq_iovlen += 2;
259 req->rq_iov[2].iov_base = padding;
260 req->rq_iov[2].iov_len = odata - oparam - req->rq_lparm;
261 req->rq_iov[3].iov_base = req->rq_data;
262 req->rq_iov[3].iov_len = req->rq_ldata;
263 req->rq_slen = odata + req->rq_ldata;
264 }
265
266 /* always a data part for trans2 replies */
267 req->rq_setup_read = smb_setup_bcc;
268
269 return 0;
270}
271
272/*
273 * Add a request and tell smbiod to process it
274 */
275int smb_add_request(struct smb_request *req)
276{
277 long timeleft;
278 struct smb_sb_info *server = req->rq_server;
279 int result = 0;
280
281 smb_setup_request(req);
282 if (req->rq_trans2_command) {
283 if (req->rq_buffer == NULL) {
284 PARANOIA("trans2 attempted without response buffer!\n");
285 return -EIO;
286 }
287 result = smb_setup_trans2request(req);
288 }
289 if (result < 0)
290 return result;
291
292#ifdef SMB_DEBUG_PACKET_SIZE
293 add_xmit_stats(req);
294#endif
295
296 /* add 'req' to the queue of requests */
297 if (smb_lock_server_interruptible(server))
298 return -EINTR;
299
300 /*
301 * Try to send the request as the process. If that fails we queue the
302 * request and let smbiod send it later.
303 */
304
305 /* FIXME: each server has a number on the maximum number of parallel
306 requests. 10, 50 or so. We should not allow more requests to be
307 active. */
308 if (server->mid > 0xf000)
309 server->mid = 0;
310 req->rq_mid = server->mid++;
311 WSET(req->rq_header, smb_mid, req->rq_mid);
312
313 result = 0;
314 if (server->state == CONN_VALID) {
315 if (list_empty(&server->xmitq))
316 result = smb_request_send_req(req);
317 if (result < 0) {
318 /* Connection lost? */
319 server->conn_error = result;
320 server->state = CONN_INVALID;
321 }
322 }
323 if (result != 1)
324 list_add_tail(&req->rq_queue, &server->xmitq);
325 smb_rget(req);
326
327 if (server->state != CONN_VALID)
328 smbiod_retry(server);
329
330 smb_unlock_server(server);
331
332 smbiod_wake_up();
333
334 timeleft = wait_event_interruptible_timeout(req->rq_wait,
335 req->rq_flags & SMB_REQ_RECEIVED, 30*HZ);
336 if (!timeleft || signal_pending(current)) {
337 /*
338 * On timeout or on interrupt we want to try and remove the
339 * request from the recvq/xmitq.
340 * First check if the request is still part of a queue. (May
341 * have been removed by some error condition)
342 */
343 smb_lock_server(server);
344 if (!list_empty(&req->rq_queue)) {
345 list_del_init(&req->rq_queue);
346 smb_rput(req);
347 }
348 smb_unlock_server(server);
349 }
350
351 if (!timeleft) {
352 PARANOIA("request [%p, mid=%d] timed out!\n",
353 req, req->rq_mid);
354 VERBOSE("smb_com: %02x\n", *(req->rq_header + smb_com));
355 VERBOSE("smb_rcls: %02x\n", *(req->rq_header + smb_rcls));
356 VERBOSE("smb_flg: %02x\n", *(req->rq_header + smb_flg));
357 VERBOSE("smb_tid: %04x\n", WVAL(req->rq_header, smb_tid));
358 VERBOSE("smb_pid: %04x\n", WVAL(req->rq_header, smb_pid));
359 VERBOSE("smb_uid: %04x\n", WVAL(req->rq_header, smb_uid));
360 VERBOSE("smb_mid: %04x\n", WVAL(req->rq_header, smb_mid));
361 VERBOSE("smb_wct: %02x\n", *(req->rq_header + smb_wct));
362
363 req->rq_rcls = ERRSRV;
364 req->rq_err = ERRtimeout;
365
366 /* Just in case it was "stuck" */
367 smbiod_wake_up();
368 }
369 VERBOSE("woke up, rcls=%d\n", req->rq_rcls);
370
371 if (req->rq_rcls != 0)
372 req->rq_errno = smb_errno(req);
373 if (signal_pending(current))
374 req->rq_errno = -ERESTARTSYS;
375 return req->rq_errno;
376}
377
378/*
379 * Send a request and place it on the recvq if successfully sent.
380 * Must be called with the server lock held.
381 */
382static int smb_request_send_req(struct smb_request *req)
383{
384 struct smb_sb_info *server = req->rq_server;
385 int result;
386
387 if (req->rq_bytes_sent == 0) {
388 WSET(req->rq_header, smb_tid, server->opt.tid);
389 WSET(req->rq_header, smb_pid, 1);
390 WSET(req->rq_header, smb_uid, server->opt.server_uid);
391 }
392
393 result = smb_send_request(req);
394 if (result < 0 && result != -EAGAIN)
395 goto out;
396
397 result = 0;
398 if (!(req->rq_flags & SMB_REQ_TRANSMITTED))
399 goto out;
400
401 list_move_tail(&req->rq_queue, &server->recvq);
402 result = 1;
403out:
404 return result;
405}
406
407/*
408 * Sends one request for this server. (smbiod)
409 * Must be called with the server lock held.
410 * Returns: <0 on error
411 * 0 if no request could be completely sent
412 * 1 if all data for one request was sent
413 */
414int smb_request_send_server(struct smb_sb_info *server)
415{
416 struct list_head *head;
417 struct smb_request *req;
418 int result;
419
420 if (server->state != CONN_VALID)
421 return 0;
422
423 /* dequeue first request, if any */
424 req = NULL;
425 head = server->xmitq.next;
426 if (head != &server->xmitq) {
427 req = list_entry(head, struct smb_request, rq_queue);
428 }
429 if (!req)
430 return 0;
431
432 result = smb_request_send_req(req);
433 if (result < 0) {
434 server->conn_error = result;
435 list_move(&req->rq_queue, &server->xmitq);
436 result = -EIO;
437 goto out;
438 }
439
440out:
441 return result;
442}
443
444/*
445 * Try to find a request matching this "mid". Typically the first entry will
446 * be the matching one.
447 */
448static struct smb_request *find_request(struct smb_sb_info *server, int mid)
449{
450 struct list_head *tmp;
451 struct smb_request *req = NULL;
452
453 list_for_each(tmp, &server->recvq) {
454 req = list_entry(tmp, struct smb_request, rq_queue);
455 if (req->rq_mid == mid) {
456 break;
457 }
458 req = NULL;
459 }
460
461 if (!req) {
462 VERBOSE("received reply with mid %d but no request!\n",
463 WVAL(server->header, smb_mid));
464 server->rstate = SMB_RECV_DROP;
465 }
466
467 return req;
468}
469
470/*
471 * Called when we have read the smb header and believe this is a response.
472 */
473static int smb_init_request(struct smb_sb_info *server, struct smb_request *req)
474{
475 int hdrlen, wct;
476
477 memcpy(req->rq_header, server->header, SMB_HEADER_LEN);
478
479 wct = *(req->rq_header + smb_wct);
480 if (wct > 20) {
481 PARANOIA("wct too large, %d > 20\n", wct);
482 server->rstate = SMB_RECV_DROP;
483 return 0;
484 }
485
486 req->rq_resp_wct = wct;
487 hdrlen = SMB_HEADER_LEN + wct*2 + 2;
488 VERBOSE("header length: %d smb_wct: %2d\n", hdrlen, wct);
489
490 req->rq_bytes_recvd = SMB_HEADER_LEN;
491 req->rq_rlen = hdrlen;
492 req->rq_iov[0].iov_base = req->rq_header;
493 req->rq_iov[0].iov_len = hdrlen;
494 req->rq_iovlen = 1;
495 server->rstate = SMB_RECV_PARAM;
496
497#ifdef SMB_DEBUG_PACKET_SIZE
498 add_recv_stats(smb_len(server->header));
499#endif
500 return 0;
501}
502
503/*
504 * Reads the SMB parameters
505 */
506static int smb_recv_param(struct smb_sb_info *server, struct smb_request *req)
507{
508 int result;
509
510 result = smb_receive(server, req);
511 if (result < 0)
512 return result;
513 if (req->rq_bytes_recvd < req->rq_rlen)
514 return 0;
515
516 VERBOSE("result: %d smb_bcc: %04x\n", result,
517 WVAL(req->rq_header, SMB_HEADER_LEN +
518 (*(req->rq_header + smb_wct) * 2)));
519
520 result = 0;
521 req->rq_iov[0].iov_base = NULL;
522 req->rq_rlen = 0;
523 if (req->rq_callback)
524 req->rq_callback(req);
525 else if (req->rq_setup_read)
526 result = req->rq_setup_read(req);
527 if (result < 0) {
528 server->rstate = SMB_RECV_DROP;
529 return result;
530 }
531
532 server->rstate = req->rq_rlen > 0 ? SMB_RECV_DATA : SMB_RECV_END;
533
534 req->rq_bytes_recvd = 0; // recvd out of the iov
535
536 VERBOSE("rlen: %d\n", req->rq_rlen);
537 if (req->rq_rlen < 0) {
538 PARANOIA("Parameters read beyond end of packet!\n");
539 server->rstate = SMB_RECV_END;
540 return -EIO;
541 }
542 return 0;
543}
544
545/*
546 * Reads the SMB data
547 */
548static int smb_recv_data(struct smb_sb_info *server, struct smb_request *req)
549{
550 int result;
551
552 result = smb_receive(server, req);
553 if (result < 0)
554 goto out;
555 if (req->rq_bytes_recvd < req->rq_rlen)
556 goto out;
557 server->rstate = SMB_RECV_END;
558out:
559 VERBOSE("result: %d\n", result);
560 return result;
561}
562
563/*
564 * Receive a transaction2 response
565 * Return: 0 if the response has been fully read
566 * 1 if there are further "fragments" to read
567 * <0 if there is an error
568 */
569static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req)
570{
571 unsigned char *inbuf;
572 unsigned int parm_disp, parm_offset, parm_count, parm_tot;
573 unsigned int data_disp, data_offset, data_count, data_tot;
574 int hdrlen = SMB_HEADER_LEN + req->rq_resp_wct*2 - 2;
575
576 VERBOSE("handling trans2\n");
577
578 inbuf = req->rq_header;
579 data_tot = WVAL(inbuf, smb_tdrcnt);
580 parm_tot = WVAL(inbuf, smb_tprcnt);
581 parm_disp = WVAL(inbuf, smb_prdisp);
582 parm_offset = WVAL(inbuf, smb_proff);
583 parm_count = WVAL(inbuf, smb_prcnt);
584 data_disp = WVAL(inbuf, smb_drdisp);
585 data_offset = WVAL(inbuf, smb_droff);
586 data_count = WVAL(inbuf, smb_drcnt);
587
588 /* Modify offset for the split header/buffer we use */
589 if (data_count || data_offset) {
590 if (unlikely(data_offset < hdrlen))
591 goto out_bad_data;
592 else
593 data_offset -= hdrlen;
594 }
595 if (parm_count || parm_offset) {
596 if (unlikely(parm_offset < hdrlen))
597 goto out_bad_parm;
598 else
599 parm_offset -= hdrlen;
600 }
601
602 if (parm_count == parm_tot && data_count == data_tot) {
603 /*
604 * This packet has all the trans2 data.
605 *
606 * We setup the request so that this will be the common
607 * case. It may be a server error to not return a
608 * response that fits.
609 */
610 VERBOSE("single trans2 response "
611 "dcnt=%u, pcnt=%u, doff=%u, poff=%u\n",
612 data_count, parm_count,
613 data_offset, parm_offset);
614 req->rq_ldata = data_count;
615 req->rq_lparm = parm_count;
616 req->rq_data = req->rq_buffer + data_offset;
617 req->rq_parm = req->rq_buffer + parm_offset;
618 if (unlikely(parm_offset + parm_count > req->rq_rlen))
619 goto out_bad_parm;
620 if (unlikely(data_offset + data_count > req->rq_rlen))
621 goto out_bad_data;
622 return 0;
623 }
624
625 VERBOSE("multi trans2 response "
626 "frag=%d, dcnt=%u, pcnt=%u, doff=%u, poff=%u\n",
627 req->rq_fragment,
628 data_count, parm_count,
629 data_offset, parm_offset);
630
631 if (!req->rq_fragment) {
632 int buf_len;
633
634 /* We got the first trans2 fragment */
635 req->rq_fragment = 1;
636 req->rq_total_data = data_tot;
637 req->rq_total_parm = parm_tot;
638 req->rq_ldata = 0;
639 req->rq_lparm = 0;
640
641 buf_len = data_tot + parm_tot;
642 if (buf_len > SMB_MAX_PACKET_SIZE)
643 goto out_too_long;
644
645 req->rq_trans2bufsize = buf_len;
646 req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS);
647 if (!req->rq_trans2buffer)
648 goto out_no_mem;
649
650 req->rq_parm = req->rq_trans2buffer;
651 req->rq_data = req->rq_trans2buffer + parm_tot;
652 } else if (unlikely(req->rq_total_data < data_tot ||
653 req->rq_total_parm < parm_tot))
654 goto out_data_grew;
655
656 if (unlikely(parm_disp + parm_count > req->rq_total_parm ||
657 parm_offset + parm_count > req->rq_rlen))
658 goto out_bad_parm;
659 if (unlikely(data_disp + data_count > req->rq_total_data ||
660 data_offset + data_count > req->rq_rlen))
661 goto out_bad_data;
662
663 inbuf = req->rq_buffer;
664 memcpy(req->rq_parm + parm_disp, inbuf + parm_offset, parm_count);
665 memcpy(req->rq_data + data_disp, inbuf + data_offset, data_count);
666
667 req->rq_ldata += data_count;
668 req->rq_lparm += parm_count;
669
670 /*
671 * Check whether we've received all of the data. Note that
672 * we use the packet totals -- total lengths might shrink!
673 */
674 if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot) {
675 req->rq_ldata = data_tot;
676 req->rq_lparm = parm_tot;
677 return 0;
678 }
679 return 1;
680
681out_too_long:
682 printk(KERN_ERR "smb_trans2: data/param too long, data=%u, parm=%u\n",
683 data_tot, parm_tot);
684 goto out_EIO;
685out_no_mem:
686 printk(KERN_ERR "smb_trans2: couldn't allocate data area of %d bytes\n",
687 req->rq_trans2bufsize);
688 req->rq_errno = -ENOMEM;
689 goto out;
690out_data_grew:
691 printk(KERN_ERR "smb_trans2: data/params grew!\n");
692 goto out_EIO;
693out_bad_parm:
694 printk(KERN_ERR "smb_trans2: invalid parms, disp=%u, cnt=%u, tot=%u, ofs=%u\n",
695 parm_disp, parm_count, parm_tot, parm_offset);
696 goto out_EIO;
697out_bad_data:
698 printk(KERN_ERR "smb_trans2: invalid data, disp=%u, cnt=%u, tot=%u, ofs=%u\n",
699 data_disp, data_count, data_tot, data_offset);
700out_EIO:
701 req->rq_errno = -EIO;
702out:
703 return req->rq_errno;
704}
705
706/*
707 * State machine for receiving responses. We handle the fact that we can't
708 * read the full response in one try by having states telling us how much we
709 * have read.
710 *
711 * Must be called with the server lock held (only called from smbiod).
712 *
713 * Return: <0 on error
714 */
715int smb_request_recv(struct smb_sb_info *server)
716{
717 struct smb_request *req = NULL;
718 int result = 0;
719
720 if (smb_recv_available(server) <= 0)
721 return 0;
722
723 VERBOSE("state: %d\n", server->rstate);
724 switch (server->rstate) {
725 case SMB_RECV_DROP:
726 result = smb_receive_drop(server);
727 if (result < 0)
728 break;
729 if (server->rstate == SMB_RECV_DROP)
730 break;
731 server->rstate = SMB_RECV_START;
732 /* fallthrough */
733 case SMB_RECV_START:
734 server->smb_read = 0;
735 server->rstate = SMB_RECV_HEADER;
736 /* fallthrough */
737 case SMB_RECV_HEADER:
738 result = smb_receive_header(server);
739 if (result < 0)
740 break;
741 if (server->rstate == SMB_RECV_HEADER)
742 break;
743 if (! (*(server->header + smb_flg) & SMB_FLAGS_REPLY) ) {
744 server->rstate = SMB_RECV_REQUEST;
745 break;
746 }
747 if (server->rstate != SMB_RECV_HCOMPLETE)
748 break;
749 /* fallthrough */
750 case SMB_RECV_HCOMPLETE:
751 req = find_request(server, WVAL(server->header, smb_mid));
752 if (!req)
753 break;
754 smb_init_request(server, req);
755 req->rq_rcls = *(req->rq_header + smb_rcls);
756 req->rq_err = WVAL(req->rq_header, smb_err);
757 if (server->rstate != SMB_RECV_PARAM)
758 break;
759 /* fallthrough */
760 case SMB_RECV_PARAM:
761 if (!req)
762 req = find_request(server,WVAL(server->header,smb_mid));
763 if (!req)
764 break;
765 result = smb_recv_param(server, req);
766 if (result < 0)
767 break;
768 if (server->rstate != SMB_RECV_DATA)
769 break;
770 /* fallthrough */
771 case SMB_RECV_DATA:
772 if (!req)
773 req = find_request(server,WVAL(server->header,smb_mid));
774 if (!req)
775 break;
776 result = smb_recv_data(server, req);
777 if (result < 0)
778 break;
779 break;
780
781 /* We should never be called with any of these states */
782 case SMB_RECV_END:
783 case SMB_RECV_REQUEST:
784 BUG();
785 }
786
787 if (result < 0) {
788 /* We saw an error */
789 return result;
790 }
791
792 if (server->rstate != SMB_RECV_END)
793 return 0;
794
795 result = 0;
796 if (req->rq_trans2_command && req->rq_rcls == SUCCESS)
797 result = smb_recv_trans2(server, req);
798
799 /*
800 * Response completely read. Drop any extra bytes sent by the server.
801 * (Yes, servers sometimes add extra bytes to responses)
802 */
803 VERBOSE("smb_len: %d smb_read: %d\n",
804 server->smb_len, server->smb_read);
805 if (server->smb_read < server->smb_len)
806 smb_receive_drop(server);
807
808 server->rstate = SMB_RECV_START;
809
810 if (!result) {
811 list_del_init(&req->rq_queue);
812 req->rq_flags |= SMB_REQ_RECEIVED;
813 smb_rput(req);
814 wake_up_interruptible(&req->rq_wait);
815 }
816 return 0;
817}
diff --git a/drivers/staging/smbfs/request.h b/drivers/staging/smbfs/request.h
deleted file mode 100644
index efb21451e7c..00000000000
--- a/drivers/staging/smbfs/request.h
+++ /dev/null
@@ -1,70 +0,0 @@
1#include <linux/list.h>
2#include <linux/types.h>
3#include <linux/uio.h>
4#include <linux/wait.h>
5
6struct smb_request {
7 struct list_head rq_queue; /* recvq or xmitq for the server */
8
9 atomic_t rq_count;
10
11 wait_queue_head_t rq_wait;
12 int rq_flags;
13 int rq_mid; /* multiplex ID, set by request.c */
14
15 struct smb_sb_info *rq_server;
16
17 /* header + word count + parameter words + byte count */
18 unsigned char rq_header[SMB_HEADER_LEN + 20*2 + 2];
19
20 int rq_bufsize;
21 unsigned char *rq_buffer;
22
23 /* FIXME: this is not good enough for merging IO requests. */
24 unsigned char *rq_page;
25 int rq_rsize;
26
27 int rq_resp_wct;
28 int rq_resp_bcc;
29
30 int rq_rlen;
31 int rq_bytes_recvd;
32
33 int rq_slen;
34 int rq_bytes_sent;
35
36 int rq_iovlen;
37 struct kvec rq_iov[4];
38
39 int (*rq_setup_read) (struct smb_request *);
40 void (*rq_callback) (struct smb_request *);
41
42 /* ------ trans2 stuff ------ */
43
44 u16 rq_trans2_command; /* 0 if not a trans2 request */
45 unsigned int rq_ldata;
46 unsigned char *rq_data;
47 unsigned int rq_lparm;
48 unsigned char *rq_parm;
49
50 int rq_fragment;
51 u32 rq_total_data;
52 u32 rq_total_parm;
53 int rq_trans2bufsize;
54 unsigned char *rq_trans2buffer;
55
56 /* ------ response ------ */
57
58 unsigned short rq_rcls;
59 unsigned short rq_err;
60 int rq_errno;
61};
62
63#define SMB_REQ_STATIC 0x0001 /* rq_buffer is static */
64#define SMB_REQ_NORETRY 0x0002 /* request is invalid after retry */
65
66#define SMB_REQ_TRANSMITTED 0x4000 /* all data has been sent */
67#define SMB_REQ_RECEIVED 0x8000 /* reply received, smbiod is done */
68
69#define xSMB_REQ_NOREPLY 0x0004 /* we don't want the reply (if any) */
70#define xSMB_REQ_NORECEIVER 0x0008 /* caller doesn't wait for response */
diff --git a/drivers/staging/smbfs/smb.h b/drivers/staging/smbfs/smb.h
deleted file mode 100644
index 82fefddc598..00000000000
--- a/drivers/staging/smbfs/smb.h
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * smb.h
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 */
8
9#ifndef _LINUX_SMB_H
10#define _LINUX_SMB_H
11
12#include <linux/types.h>
13#include <linux/magic.h>
14#ifdef __KERNEL__
15#include <linux/time.h>
16#endif
17
18enum smb_protocol {
19 SMB_PROTOCOL_NONE,
20 SMB_PROTOCOL_CORE,
21 SMB_PROTOCOL_COREPLUS,
22 SMB_PROTOCOL_LANMAN1,
23 SMB_PROTOCOL_LANMAN2,
24 SMB_PROTOCOL_NT1
25};
26
27enum smb_case_hndl {
28 SMB_CASE_DEFAULT,
29 SMB_CASE_LOWER,
30 SMB_CASE_UPPER
31};
32
33struct smb_dskattr {
34 __u16 total;
35 __u16 allocblocks;
36 __u16 blocksize;
37 __u16 free;
38};
39
40struct smb_conn_opt {
41
42 /* The socket */
43 unsigned int fd;
44
45 enum smb_protocol protocol;
46 enum smb_case_hndl case_handling;
47
48 /* Connection-Options */
49
50 __u32 max_xmit;
51 __u16 server_uid;
52 __u16 tid;
53
54 /* The following are LANMAN 1.0 options */
55 __u16 secmode;
56 __u16 maxmux;
57 __u16 maxvcs;
58 __u16 rawmode;
59 __u32 sesskey;
60
61 /* The following are NT LM 0.12 options */
62 __u32 maxraw;
63 __u32 capabilities;
64 __s16 serverzone;
65};
66
67#ifdef __KERNEL__
68
69#define SMB_NLS_MAXNAMELEN 20
70struct smb_nls_codepage {
71 char local_name[SMB_NLS_MAXNAMELEN];
72 char remote_name[SMB_NLS_MAXNAMELEN];
73};
74
75
76#define SMB_MAXNAMELEN 255
77#define SMB_MAXPATHLEN 1024
78
79/*
80 * Contains all relevant data on a SMB networked file.
81 */
82struct smb_fattr {
83 __u16 attr;
84
85 unsigned long f_ino;
86 umode_t f_mode;
87 nlink_t f_nlink;
88 uid_t f_uid;
89 gid_t f_gid;
90 dev_t f_rdev;
91 loff_t f_size;
92 struct timespec f_atime;
93 struct timespec f_mtime;
94 struct timespec f_ctime;
95 unsigned long f_blocks;
96 int f_unix;
97};
98
99enum smb_conn_state {
100 CONN_VALID, /* everything's fine */
101 CONN_INVALID, /* Something went wrong, but did not
102 try to reconnect yet. */
103 CONN_RETRIED, /* Tried a reconnection, but was refused */
104 CONN_RETRYING /* Currently trying to reconnect */
105};
106
107#define SMB_HEADER_LEN 37 /* includes everything up to, but not
108 * including smb_bcc */
109
110#define SMB_INITIAL_PACKET_SIZE 4000
111#define SMB_MAX_PACKET_SIZE 32768
112
113/* reserve this much space for trans2 parameters. Shouldn't have to be more
114 than 10 or so, but OS/2 seems happier like this. */
115#define SMB_TRANS2_MAX_PARAM 64
116
117#endif
118#endif
diff --git a/drivers/staging/smbfs/smb_debug.h b/drivers/staging/smbfs/smb_debug.h
deleted file mode 100644
index fc4b1a5dd75..00000000000
--- a/drivers/staging/smbfs/smb_debug.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * Defines some debug macros for smbfs.
3 */
4
5/* This makes a dentry parent/child name pair. Useful for debugging printk's */
6#define DENTRY_PATH(dentry) \
7 (dentry)->d_parent->d_name.name,(dentry)->d_name.name
8
9/*
10 * safety checks that should never happen ???
11 * these are normally enabled.
12 */
13#ifdef SMBFS_PARANOIA
14# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __func__ , ## a)
15#else
16# define PARANOIA(f, a...) do { ; } while(0)
17#endif
18
19/* lots of debug messages */
20#ifdef SMBFS_DEBUG_VERBOSE
21# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
22#else
23# define VERBOSE(f, a...) do { ; } while(0)
24#endif
25
26/*
27 * "normal" debug messages, but not with a normal DEBUG define ... way
28 * too common name.
29 */
30#ifdef SMBFS_DEBUG
31#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
32#else
33#define DEBUG1(f, a...) do { ; } while(0)
34#endif
diff --git a/drivers/staging/smbfs/smb_fs.h b/drivers/staging/smbfs/smb_fs.h
deleted file mode 100644
index 20a05c188eb..00000000000
--- a/drivers/staging/smbfs/smb_fs.h
+++ /dev/null
@@ -1,153 +0,0 @@
1/*
2 * smb_fs.h
3 *
4 * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 */
8
9#ifndef _LINUX_SMB_FS_H
10#define _LINUX_SMB_FS_H
11
12#include "smb.h"
13
14/*
15 * ioctl commands
16 */
17#define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_old_uid_t)
18#define SMB_IOC_NEWCONN _IOW('u', 2, struct smb_conn_opt)
19
20/* __kernel_uid_t can never change, so we have to use __kernel_uid32_t */
21#define SMB_IOC_GETMOUNTUID32 _IOR('u', 3, __kernel_uid32_t)
22
23
24#ifdef __KERNEL__
25#include "smb_fs_i.h"
26#include "smb_fs_sb.h"
27#include "smb_mount.h"
28
29#include <linux/fs.h>
30#include <linux/pagemap.h>
31#include <linux/vmalloc.h>
32#include <linux/jiffies.h>
33#include <asm/unaligned.h>
34
35static inline struct smb_sb_info *SMB_SB(struct super_block *sb)
36{
37 return sb->s_fs_info;
38}
39
40static inline struct smb_inode_info *SMB_I(struct inode *inode)
41{
42 return container_of(inode, struct smb_inode_info, vfs_inode);
43}
44
45/* macro names are short for word, double-word, long value (?) */
46#define WVAL(buf, pos) (get_unaligned_le16((u8 *)(buf) + (pos)))
47#define DVAL(buf, pos) (get_unaligned_le32((u8 *)(buf) + (pos)))
48#define LVAL(buf, pos) (get_unaligned_le64((u8 *)(buf) + (pos)))
49
50#define WSET(buf, pos, val) put_unaligned_le16((val), (u8 *)(buf) + (pos))
51#define DSET(buf, pos, val) put_unaligned_le32((val), (u8 *)(buf) + (pos))
52#define LSET(buf, pos, val) put_unaligned_le64((val), (u8 *)(buf) + (pos))
53
54/* where to find the base of the SMB packet proper */
55#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
56
57/*
58 * Flags for the in-memory inode
59 */
60#define SMB_F_LOCALWRITE 0x02 /* file modified locally */
61
62
63/* NT1 protocol capability bits */
64#define SMB_CAP_RAW_MODE 0x00000001
65#define SMB_CAP_MPX_MODE 0x00000002
66#define SMB_CAP_UNICODE 0x00000004
67#define SMB_CAP_LARGE_FILES 0x00000008
68#define SMB_CAP_NT_SMBS 0x00000010
69#define SMB_CAP_RPC_REMOTE_APIS 0x00000020
70#define SMB_CAP_STATUS32 0x00000040
71#define SMB_CAP_LEVEL_II_OPLOCKS 0x00000080
72#define SMB_CAP_LOCK_AND_READ 0x00000100
73#define SMB_CAP_NT_FIND 0x00000200
74#define SMB_CAP_DFS 0x00001000
75#define SMB_CAP_LARGE_READX 0x00004000
76#define SMB_CAP_LARGE_WRITEX 0x00008000
77#define SMB_CAP_UNIX 0x00800000 /* unofficial ... */
78
79
80/*
81 * This is the time we allow an inode, dentry or dir cache to live. It is bad
82 * for performance to have shorter ttl on an inode than on the cache. It can
83 * cause refresh on each inode for a dir listing ... one-by-one
84 */
85#define SMB_MAX_AGE(server) (((server)->mnt->ttl * HZ) / 1000)
86
87static inline void
88smb_age_dentry(struct smb_sb_info *server, struct dentry *dentry)
89{
90 dentry->d_time = jiffies - SMB_MAX_AGE(server);
91}
92
93struct smb_cache_head {
94 time_t mtime; /* unused */
95 unsigned long time; /* cache age */
96 unsigned long end; /* last valid fpos in cache */
97 int eof;
98};
99
100#define SMB_DIRCACHE_SIZE ((int)(PAGE_CACHE_SIZE/sizeof(struct dentry *)))
101union smb_dir_cache {
102 struct smb_cache_head head;
103 struct dentry *dentry[SMB_DIRCACHE_SIZE];
104};
105
106#define SMB_FIRSTCACHE_SIZE ((int)((SMB_DIRCACHE_SIZE * \
107 sizeof(struct dentry *) - sizeof(struct smb_cache_head)) / \
108 sizeof(struct dentry *)))
109
110#define SMB_DIRCACHE_START (SMB_DIRCACHE_SIZE - SMB_FIRSTCACHE_SIZE)
111
112struct smb_cache_control {
113 struct smb_cache_head head;
114 struct page *page;
115 union smb_dir_cache *cache;
116 unsigned long fpos, ofs;
117 int filled, valid, idx;
118};
119
120#define SMB_OPS_NUM_STATIC 5
121struct smb_ops {
122 int (*read)(struct inode *inode, loff_t offset, int count,
123 char *data);
124 int (*write)(struct inode *inode, loff_t offset, int count, const
125 char *data);
126 int (*readdir)(struct file *filp, void *dirent, filldir_t filldir,
127 struct smb_cache_control *ctl);
128
129 int (*getattr)(struct smb_sb_info *server, struct dentry *dir,
130 struct smb_fattr *fattr);
131 /* int (*setattr)(...); */ /* setattr is really icky! */
132
133 int (*truncate)(struct inode *inode, loff_t length);
134
135
136 /* --- --- --- end of "static" entries --- --- --- */
137
138 int (*convert)(unsigned char *output, int olen,
139 const unsigned char *input, int ilen,
140 struct nls_table *nls_from,
141 struct nls_table *nls_to);
142};
143
144static inline int
145smb_is_open(struct inode *i)
146{
147 return (SMB_I(i)->open == server_from_inode(i)->generation);
148}
149
150extern void smb_install_null_ops(struct smb_ops *);
151#endif /* __KERNEL__ */
152
153#endif /* _LINUX_SMB_FS_H */
diff --git a/drivers/staging/smbfs/smb_fs_i.h b/drivers/staging/smbfs/smb_fs_i.h
deleted file mode 100644
index 8ccf4eca2c3..00000000000
--- a/drivers/staging/smbfs/smb_fs_i.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * smb_fs_i.h
3 *
4 * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 */
8
9#ifndef _LINUX_SMB_FS_I
10#define _LINUX_SMB_FS_I
11
12#include <linux/types.h>
13#include <linux/fs.h>
14
15/*
16 * smb fs inode data (in memory only)
17 */
18struct smb_inode_info {
19
20 /*
21 * file handles are local to a connection. A file is open if
22 * (open == generation).
23 */
24 unsigned int open; /* open generation */
25 __u16 fileid; /* What id to handle a file with? */
26 __u16 attr; /* Attribute fields, DOS value */
27
28 __u16 access; /* Access mode */
29 __u16 flags;
30 unsigned long oldmtime; /* last time refreshed */
31 unsigned long closed; /* timestamp when closed */
32 unsigned openers; /* number of fileid users */
33
34 struct inode vfs_inode; /* must be at the end */
35};
36
37#endif
diff --git a/drivers/staging/smbfs/smb_fs_sb.h b/drivers/staging/smbfs/smb_fs_sb.h
deleted file mode 100644
index ca058afda90..00000000000
--- a/drivers/staging/smbfs/smb_fs_sb.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * smb_fs_sb.h
3 *
4 * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 */
8
9#ifndef _SMB_FS_SB
10#define _SMB_FS_SB
11
12#include <linux/types.h>
13#include <linux/backing-dev.h>
14#include "smb.h"
15
16/*
17 * Upper limit on the total number of active smb_request structs.
18 */
19#define MAX_REQUEST_HARD 256
20
21enum smb_receive_state {
22 SMB_RECV_START, /* No data read, looking for length + sig */
23 SMB_RECV_HEADER, /* Reading the header data */
24 SMB_RECV_HCOMPLETE, /* Done with the header */
25 SMB_RECV_PARAM, /* Reading parameter words */
26 SMB_RECV_DATA, /* Reading data bytes */
27 SMB_RECV_END, /* End of request */
28 SMB_RECV_DROP, /* Dropping this SMB */
29 SMB_RECV_REQUEST, /* Received a request and not a reply */
30};
31
32/* structure access macros */
33#define server_from_inode(inode) SMB_SB((inode)->i_sb)
34#define server_from_dentry(dentry) SMB_SB((dentry)->d_sb)
35#define SB_of(server) ((server)->super_block)
36
37struct smb_sb_info {
38 /* List of all smbfs superblocks */
39 struct list_head entry;
40
41 enum smb_conn_state state;
42 struct file * sock_file;
43 int conn_error;
44 enum smb_receive_state rstate;
45
46 atomic_t nr_requests;
47 struct list_head xmitq;
48 struct list_head recvq;
49 u16 mid;
50
51 struct smb_mount_data_kernel *mnt;
52
53 /* Connections are counted. Each time a new socket arrives,
54 * generation is incremented.
55 */
56 unsigned int generation;
57 struct pid *conn_pid;
58 struct smb_conn_opt opt;
59 wait_queue_head_t conn_wq;
60 int conn_complete;
61 struct semaphore sem;
62
63 unsigned char header[SMB_HEADER_LEN + 20*2 + 2];
64 u32 header_len;
65 u32 smb_len;
66 u32 smb_read;
67
68 /* We use our own data_ready callback, but need the original one */
69 void *data_ready;
70
71 /* nls pointers for codepage conversions */
72 struct nls_table *remote_nls;
73 struct nls_table *local_nls;
74
75 struct smb_ops *ops;
76
77 struct super_block *super_block;
78
79 struct backing_dev_info bdi;
80};
81
82static inline int
83smb_lock_server_interruptible(struct smb_sb_info *server)
84{
85 return down_interruptible(&(server->sem));
86}
87
88static inline void
89smb_lock_server(struct smb_sb_info *server)
90{
91 down(&(server->sem));
92}
93
94static inline void
95smb_unlock_server(struct smb_sb_info *server)
96{
97 up(&(server->sem));
98}
99
100#endif
diff --git a/drivers/staging/smbfs/smb_mount.h b/drivers/staging/smbfs/smb_mount.h
deleted file mode 100644
index d10f00cb570..00000000000
--- a/drivers/staging/smbfs/smb_mount.h
+++ /dev/null
@@ -1,65 +0,0 @@
1/*
2 * smb_mount.h
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 */
8
9#ifndef _LINUX_SMB_MOUNT_H
10#define _LINUX_SMB_MOUNT_H
11
12#include <linux/types.h>
13
14#define SMB_MOUNT_VERSION 6
15
16struct smb_mount_data {
17 int version;
18 __kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */
19 __kernel_uid_t uid;
20 __kernel_gid_t gid;
21 __kernel_mode_t file_mode;
22 __kernel_mode_t dir_mode;
23};
24
25
26#ifdef __KERNEL__
27
28/* "vers" in big-endian */
29#define SMB_MOUNT_ASCII 0x76657273
30
31#define SMB_MOUNT_OLDVERSION 6
32#undef SMB_MOUNT_VERSION
33#define SMB_MOUNT_VERSION 7
34
35/* flags */
36#define SMB_MOUNT_WIN95 0x0001 /* Win 95 server */
37#define SMB_MOUNT_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
38#define SMB_MOUNT_DIRATTR 0x0004 /* Use find_first for getattr */
39#define SMB_MOUNT_CASE 0x0008 /* Be case sensitive */
40#define SMB_MOUNT_UNICODE 0x0010 /* Server talks unicode */
41#define SMB_MOUNT_UID 0x0020 /* Use user specified uid */
42#define SMB_MOUNT_GID 0x0040 /* Use user specified gid */
43#define SMB_MOUNT_FMODE 0x0080 /* Use user specified file mode */
44#define SMB_MOUNT_DMODE 0x0100 /* Use user specified dir mode */
45
46struct smb_mount_data_kernel {
47 int version;
48
49 uid_t mounted_uid; /* Who may umount() this filesystem? */
50 uid_t uid;
51 gid_t gid;
52 mode_t file_mode;
53 mode_t dir_mode;
54
55 u32 flags;
56
57 /* maximum age in jiffies (inode, dentry and dircache) */
58 int ttl;
59
60 struct smb_nls_codepage codepage;
61};
62
63#endif
64
65#endif
diff --git a/drivers/staging/smbfs/smbfs.txt b/drivers/staging/smbfs/smbfs.txt
deleted file mode 100644
index 194fb0decd2..00000000000
--- a/drivers/staging/smbfs/smbfs.txt
+++ /dev/null
@@ -1,8 +0,0 @@
1Smbfs is a filesystem that implements the SMB protocol, which is the
2protocol used by Windows for Workgroups, Windows 95 and Windows NT.
3Smbfs was inspired by Samba, the program written by Andrew Tridgell
4that turns any Unix host into a file server for DOS or Windows clients.
5
6Smbfs is a SMB client, but uses parts of samba for its operation. For
7more info on samba, including documentation, please go to
8http://www.samba.org/ and then on to your nearest mirror.
diff --git a/drivers/staging/smbfs/smbiod.c b/drivers/staging/smbfs/smbiod.c
deleted file mode 100644
index ec998920f8d..00000000000
--- a/drivers/staging/smbfs/smbiod.c
+++ /dev/null
@@ -1,343 +0,0 @@
1/*
2 * smbiod.c
3 *
4 * Copyright (C) 2000, Charles Loep / Corel Corp.
5 * Copyright (C) 2001, Urban Widmark
6 */
7
8
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/string.h>
13#include <linux/stat.h>
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/file.h>
17#include <linux/dcache.h>
18#include <linux/module.h>
19#include <linux/net.h>
20#include <linux/kthread.h>
21#include <net/ip.h>
22
23#include <asm/system.h>
24#include <asm/uaccess.h>
25
26#include "smb_fs.h"
27#include "smbno.h"
28#include "smb_mount.h"
29#include "smb_debug.h"
30#include "request.h"
31#include "proto.h"
32
33enum smbiod_state {
34 SMBIOD_DEAD,
35 SMBIOD_STARTING,
36 SMBIOD_RUNNING,
37};
38
39static enum smbiod_state smbiod_state = SMBIOD_DEAD;
40static struct task_struct *smbiod_thread;
41static DECLARE_WAIT_QUEUE_HEAD(smbiod_wait);
42static LIST_HEAD(smb_servers);
43static DEFINE_SPINLOCK(servers_lock);
44
45#define SMBIOD_DATA_READY (1<<0)
46static unsigned long smbiod_flags;
47
48static int smbiod(void *);
49static int smbiod_start(void);
50
51/*
52 * called when there's work for us to do
53 */
54void smbiod_wake_up(void)
55{
56 if (smbiod_state == SMBIOD_DEAD)
57 return;
58 set_bit(SMBIOD_DATA_READY, &smbiod_flags);
59 wake_up_interruptible(&smbiod_wait);
60}
61
62/*
63 * start smbiod if none is running
64 */
65static int smbiod_start(void)
66{
67 struct task_struct *tsk;
68 int err = 0;
69
70 if (smbiod_state != SMBIOD_DEAD)
71 return 0;
72 smbiod_state = SMBIOD_STARTING;
73 __module_get(THIS_MODULE);
74 spin_unlock(&servers_lock);
75 tsk = kthread_run(smbiod, NULL, "smbiod");
76 if (IS_ERR(tsk)) {
77 err = PTR_ERR(tsk);
78 module_put(THIS_MODULE);
79 }
80
81 spin_lock(&servers_lock);
82 if (err < 0) {
83 smbiod_state = SMBIOD_DEAD;
84 smbiod_thread = NULL;
85 } else {
86 smbiod_state = SMBIOD_RUNNING;
87 smbiod_thread = tsk;
88 }
89 return err;
90}
91
92/*
93 * register a server & start smbiod if necessary
94 */
95int smbiod_register_server(struct smb_sb_info *server)
96{
97 int ret;
98 spin_lock(&servers_lock);
99 list_add(&server->entry, &smb_servers);
100 VERBOSE("%p\n", server);
101 ret = smbiod_start();
102 spin_unlock(&servers_lock);
103 return ret;
104}
105
106/*
107 * Unregister a server
108 * Must be called with the server lock held.
109 */
110void smbiod_unregister_server(struct smb_sb_info *server)
111{
112 spin_lock(&servers_lock);
113 list_del_init(&server->entry);
114 VERBOSE("%p\n", server);
115 spin_unlock(&servers_lock);
116
117 smbiod_wake_up();
118 smbiod_flush(server);
119}
120
121void smbiod_flush(struct smb_sb_info *server)
122{
123 struct list_head *tmp, *n;
124 struct smb_request *req;
125
126 list_for_each_safe(tmp, n, &server->xmitq) {
127 req = list_entry(tmp, struct smb_request, rq_queue);
128 req->rq_errno = -EIO;
129 list_del_init(&req->rq_queue);
130 smb_rput(req);
131 wake_up_interruptible(&req->rq_wait);
132 }
133 list_for_each_safe(tmp, n, &server->recvq) {
134 req = list_entry(tmp, struct smb_request, rq_queue);
135 req->rq_errno = -EIO;
136 list_del_init(&req->rq_queue);
137 smb_rput(req);
138 wake_up_interruptible(&req->rq_wait);
139 }
140}
141
142/*
143 * Wake up smbmount and make it reconnect to the server.
144 * This must be called with the server locked.
145 *
146 * FIXME: add smbconnect version to this
147 */
148int smbiod_retry(struct smb_sb_info *server)
149{
150 struct list_head *head;
151 struct smb_request *req;
152 struct pid *pid = get_pid(server->conn_pid);
153 int result = 0;
154
155 VERBOSE("state: %d\n", server->state);
156 if (server->state == CONN_VALID || server->state == CONN_RETRYING)
157 goto out;
158
159 smb_invalidate_inodes(server);
160
161 /*
162 * Some requests are meaningless after a retry, so we abort them.
163 * One example are all requests using 'fileid' since the files are
164 * closed on retry.
165 */
166 head = server->xmitq.next;
167 while (head != &server->xmitq) {
168 req = list_entry(head, struct smb_request, rq_queue);
169 head = head->next;
170
171 req->rq_bytes_sent = 0;
172 if (req->rq_flags & SMB_REQ_NORETRY) {
173 VERBOSE("aborting request %p on xmitq\n", req);
174 req->rq_errno = -EIO;
175 list_del_init(&req->rq_queue);
176 smb_rput(req);
177 wake_up_interruptible(&req->rq_wait);
178 }
179 }
180
181 /*
182 * FIXME: test the code for retrying request we already sent
183 */
184 head = server->recvq.next;
185 while (head != &server->recvq) {
186 req = list_entry(head, struct smb_request, rq_queue);
187 head = head->next;
188#if 0
189 if (req->rq_flags & SMB_REQ_RETRY) {
190 /* must move the request to the xmitq */
191 VERBOSE("retrying request %p on recvq\n", req);
192 list_move(&req->rq_queue, &server->xmitq);
193 continue;
194 }
195#endif
196
197 VERBOSE("aborting request %p on recvq\n", req);
198 /* req->rq_rcls = ???; */ /* FIXME: set smb error code too? */
199 req->rq_errno = -EIO;
200 list_del_init(&req->rq_queue);
201 smb_rput(req);
202 wake_up_interruptible(&req->rq_wait);
203 }
204
205 smb_close_socket(server);
206
207 if (!pid) {
208 /* FIXME: this is fatal, umount? */
209 printk(KERN_ERR "smb_retry: no connection process\n");
210 server->state = CONN_RETRIED;
211 goto out;
212 }
213
214 /*
215 * Change state so that only one retry per server will be started.
216 */
217 server->state = CONN_RETRYING;
218
219 /*
220 * Note: use the "priv" flag, as a user process may need to reconnect.
221 */
222 result = kill_pid(pid, SIGUSR1, 1);
223 if (result) {
224 /* FIXME: this is most likely fatal, umount? */
225 printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
226 goto out;
227 }
228 VERBOSE("signalled pid %d\n", pid_nr(pid));
229
230 /* FIXME: The retried requests should perhaps get a "time boost". */
231
232out:
233 put_pid(pid);
234 return result;
235}
236
237/*
238 * Currently handles lockingX packets.
239 */
240static void smbiod_handle_request(struct smb_sb_info *server)
241{
242 PARANOIA("smbiod got a request ... and we don't implement oplocks!\n");
243 server->rstate = SMB_RECV_DROP;
244}
245
246/*
247 * Do some IO for one server.
248 */
249static void smbiod_doio(struct smb_sb_info *server)
250{
251 int result;
252 int maxwork = 7;
253
254 if (server->state != CONN_VALID)
255 goto out;
256
257 do {
258 result = smb_request_recv(server);
259 if (result < 0) {
260 server->state = CONN_INVALID;
261 smbiod_retry(server);
262 goto out; /* reconnecting is slow */
263 } else if (server->rstate == SMB_RECV_REQUEST)
264 smbiod_handle_request(server);
265 } while (result > 0 && maxwork-- > 0);
266
267 /*
268 * If there is more to read then we want to be sure to wake up again.
269 */
270 if (server->state != CONN_VALID)
271 goto out;
272 if (smb_recv_available(server) > 0)
273 set_bit(SMBIOD_DATA_READY, &smbiod_flags);
274
275 do {
276 result = smb_request_send_server(server);
277 if (result < 0) {
278 server->state = CONN_INVALID;
279 smbiod_retry(server);
280 goto out; /* reconnecting is slow */
281 }
282 } while (result > 0);
283
284 /*
285 * If the last request was not sent out we want to wake up again.
286 */
287 if (!list_empty(&server->xmitq))
288 set_bit(SMBIOD_DATA_READY, &smbiod_flags);
289
290out:
291 return;
292}
293
294/*
295 * smbiod kernel thread
296 */
297static int smbiod(void *unused)
298{
299 VERBOSE("SMB Kernel thread starting (%d) ...\n", current->pid);
300
301 for (;;) {
302 struct smb_sb_info *server;
303 struct list_head *pos, *n;
304
305 /* FIXME: Use poll? */
306 wait_event_interruptible(smbiod_wait,
307 test_bit(SMBIOD_DATA_READY, &smbiod_flags));
308 if (signal_pending(current)) {
309 spin_lock(&servers_lock);
310 smbiod_state = SMBIOD_DEAD;
311 spin_unlock(&servers_lock);
312 break;
313 }
314
315 clear_bit(SMBIOD_DATA_READY, &smbiod_flags);
316
317 spin_lock(&servers_lock);
318 if (list_empty(&smb_servers)) {
319 smbiod_state = SMBIOD_DEAD;
320 spin_unlock(&servers_lock);
321 break;
322 }
323
324 list_for_each_safe(pos, n, &smb_servers) {
325 server = list_entry(pos, struct smb_sb_info, entry);
326 VERBOSE("checking server %p\n", server);
327
328 if (server->state == CONN_VALID) {
329 spin_unlock(&servers_lock);
330
331 smb_lock_server(server);
332 smbiod_doio(server);
333 smb_unlock_server(server);
334
335 spin_lock(&servers_lock);
336 }
337 }
338 spin_unlock(&servers_lock);
339 }
340
341 VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid);
342 module_put_and_exit(0);
343}
diff --git a/drivers/staging/smbfs/smbno.h b/drivers/staging/smbfs/smbno.h
deleted file mode 100644
index f99e02d9ffe..00000000000
--- a/drivers/staging/smbfs/smbno.h
+++ /dev/null
@@ -1,363 +0,0 @@
1#ifndef _SMBNO_H_
2#define _SMBNO_H_
3
4/* these define the attribute byte as seen by DOS */
5#define aRONLY (1L<<0)
6#define aHIDDEN (1L<<1)
7#define aSYSTEM (1L<<2)
8#define aVOLID (1L<<3)
9#define aDIR (1L<<4)
10#define aARCH (1L<<5)
11
12/* error classes */
13#define SUCCESS 0 /* The request was successful. */
14#define ERRDOS 0x01 /* Error is from the core DOS operating system set. */
15#define ERRSRV 0x02 /* Error is generated by the server network file manager.*/
16#define ERRHRD 0x03 /* Error is an hardware error. */
17#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
18
19/* SMB X/Open error codes for the ERRdos error class */
20
21#define ERRbadfunc 1 /* Invalid function (or system call) */
22#define ERRbadfile 2 /* File not found (pathname error) */
23#define ERRbadpath 3 /* Directory not found */
24#define ERRnofids 4 /* Too many open files */
25#define ERRnoaccess 5 /* Access denied */
26#define ERRbadfid 6 /* Invalid fid */
27#define ERRbadmcb 7 /* Memory control blocks destroyed */
28#define ERRnomem 8 /* Out of memory */
29#define ERRbadmem 9 /* Invalid memory block address */
30#define ERRbadenv 10 /* Invalid environment */
31#define ERRbadformat 11 /* Invalid format */
32#define ERRbadaccess 12 /* Invalid open mode */
33#define ERRbaddata 13 /* Invalid data (only from ioctl call) */
34#define ERRres 14 /* reserved */
35#define ERRbaddrive 15 /* Invalid drive */
36#define ERRremcd 16 /* Attempt to delete current directory */
37#define ERRdiffdevice 17 /* rename/move across different filesystems */
38#define ERRnofiles 18 /* no more files found in file search */
39#define ERRbadshare 32 /* Share mode on file conflict with open mode */
40#define ERRlock 33 /* Lock request conflicts with existing lock */
41#define ERRfilexists 80 /* File in operation already exists */
42#define ERRbadpipe 230 /* Named pipe invalid */
43#define ERRpipebusy 231 /* All instances of pipe are busy */
44#define ERRpipeclosing 232 /* named pipe close in progress */
45#define ERRnotconnected 233 /* No process on other end of named pipe */
46#define ERRmoredata 234 /* More data to be returned */
47
48#define ERROR_INVALID_PARAMETER 87
49#define ERROR_DISK_FULL 112
50#define ERROR_INVALID_NAME 123
51#define ERROR_DIR_NOT_EMPTY 145
52#define ERROR_NOT_LOCKED 158
53#define ERROR_ALREADY_EXISTS 183 /* see also 80 ? */
54#define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */
55#define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not supported */
56
57/* Error codes for the ERRSRV class */
58
59#define ERRerror 1 /* Non specific error code */
60#define ERRbadpw 2 /* Bad password */
61#define ERRbadtype 3 /* reserved */
62#define ERRaccess 4 /* No permissions to do the requested operation */
63#define ERRinvnid 5 /* tid invalid */
64#define ERRinvnetname 6 /* Invalid servername */
65#define ERRinvdevice 7 /* Invalid device */
66#define ERRqfull 49 /* Print queue full */
67#define ERRqtoobig 50 /* Queued item too big */
68#define ERRinvpfid 52 /* Invalid print file in smb_fid */
69#define ERRsmbcmd 64 /* Unrecognised command */
70#define ERRsrverror 65 /* smb server internal error */
71#define ERRfilespecs 67 /* fid and pathname invalid combination */
72#define ERRbadlink 68 /* reserved */
73#define ERRbadpermits 69 /* Access specified for a file is not valid */
74#define ERRbadpid 70 /* reserved */
75#define ERRsetattrmode 71 /* attribute mode invalid */
76#define ERRpaused 81 /* Message server paused */
77#define ERRmsgoff 82 /* Not receiving messages */
78#define ERRnoroom 83 /* No room for message */
79#define ERRrmuns 87 /* too many remote usernames */
80#define ERRtimeout 88 /* operation timed out */
81#define ERRnoresource 89 /* No resources currently available for request. */
82#define ERRtoomanyuids 90 /* too many userids */
83#define ERRbaduid 91 /* bad userid */
84#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */
85#define ERRuseSTD 251 /* temporarily unable to use raw mode, use std.mode */
86#define ERRcontMPX 252 /* resume MPX mode */
87#define ERRbadPW /* reserved */
88#define ERRnosupport 0xFFFF
89
90/* Error codes for the ERRHRD class */
91
92#define ERRnowrite 19 /* read only media */
93#define ERRbadunit 20 /* Unknown device */
94#define ERRnotready 21 /* Drive not ready */
95#define ERRbadcmd 22 /* Unknown command */
96#define ERRdata 23 /* Data (CRC) error */
97#define ERRbadreq 24 /* Bad request structure length */
98#define ERRseek 25
99#define ERRbadmedia 26
100#define ERRbadsector 27
101#define ERRnopaper 28
102#define ERRwrite 29 /* write fault */
103#define ERRread 30 /* read fault */
104#define ERRgeneral 31 /* General hardware failure */
105#define ERRwrongdisk 34
106#define ERRFCBunavail 35
107#define ERRsharebufexc 36 /* share buffer exceeded */
108#define ERRdiskfull 39
109
110/*
111 * Access modes when opening a file
112 */
113#define SMB_ACCMASK 0x0003
114#define SMB_O_RDONLY 0x0000
115#define SMB_O_WRONLY 0x0001
116#define SMB_O_RDWR 0x0002
117
118/* offsets into message for common items */
119#define smb_com 8
120#define smb_rcls 9
121#define smb_reh 10
122#define smb_err 11
123#define smb_flg 13
124#define smb_flg2 14
125#define smb_reb 13
126#define smb_tid 28
127#define smb_pid 30
128#define smb_uid 32
129#define smb_mid 34
130#define smb_wct 36
131#define smb_vwv 37
132#define smb_vwv0 37
133#define smb_vwv1 39
134#define smb_vwv2 41
135#define smb_vwv3 43
136#define smb_vwv4 45
137#define smb_vwv5 47
138#define smb_vwv6 49
139#define smb_vwv7 51
140#define smb_vwv8 53
141#define smb_vwv9 55
142#define smb_vwv10 57
143#define smb_vwv11 59
144#define smb_vwv12 61
145#define smb_vwv13 63
146#define smb_vwv14 65
147
148/* these are the trans2 sub fields for primary requests */
149#define smb_tpscnt smb_vwv0
150#define smb_tdscnt smb_vwv1
151#define smb_mprcnt smb_vwv2
152#define smb_mdrcnt smb_vwv3
153#define smb_msrcnt smb_vwv4
154#define smb_flags smb_vwv5
155#define smb_timeout smb_vwv6
156#define smb_pscnt smb_vwv9
157#define smb_psoff smb_vwv10
158#define smb_dscnt smb_vwv11
159#define smb_dsoff smb_vwv12
160#define smb_suwcnt smb_vwv13
161#define smb_setup smb_vwv14
162#define smb_setup0 smb_setup
163#define smb_setup1 (smb_setup+2)
164#define smb_setup2 (smb_setup+4)
165
166/* these are for the secondary requests */
167#define smb_spscnt smb_vwv2
168#define smb_spsoff smb_vwv3
169#define smb_spsdisp smb_vwv4
170#define smb_sdscnt smb_vwv5
171#define smb_sdsoff smb_vwv6
172#define smb_sdsdisp smb_vwv7
173#define smb_sfid smb_vwv8
174
175/* and these for responses */
176#define smb_tprcnt smb_vwv0
177#define smb_tdrcnt smb_vwv1
178#define smb_prcnt smb_vwv3
179#define smb_proff smb_vwv4
180#define smb_prdisp smb_vwv5
181#define smb_drcnt smb_vwv6
182#define smb_droff smb_vwv7
183#define smb_drdisp smb_vwv8
184
185/* the complete */
186#define SMBmkdir 0x00 /* create directory */
187#define SMBrmdir 0x01 /* delete directory */
188#define SMBopen 0x02 /* open file */
189#define SMBcreate 0x03 /* create file */
190#define SMBclose 0x04 /* close file */
191#define SMBflush 0x05 /* flush file */
192#define SMBunlink 0x06 /* delete file */
193#define SMBmv 0x07 /* rename file */
194#define SMBgetatr 0x08 /* get file attributes */
195#define SMBsetatr 0x09 /* set file attributes */
196#define SMBread 0x0A /* read from file */
197#define SMBwrite 0x0B /* write to file */
198#define SMBlock 0x0C /* lock byte range */
199#define SMBunlock 0x0D /* unlock byte range */
200#define SMBctemp 0x0E /* create temporary file */
201#define SMBmknew 0x0F /* make new file */
202#define SMBchkpth 0x10 /* check directory path */
203#define SMBexit 0x11 /* process exit */
204#define SMBlseek 0x12 /* seek */
205#define SMBtcon 0x70 /* tree connect */
206#define SMBtconX 0x75 /* tree connect and X*/
207#define SMBtdis 0x71 /* tree disconnect */
208#define SMBnegprot 0x72 /* negotiate protocol */
209#define SMBdskattr 0x80 /* get disk attributes */
210#define SMBsearch 0x81 /* search directory */
211#define SMBsplopen 0xC0 /* open print spool file */
212#define SMBsplwr 0xC1 /* write to print spool file */
213#define SMBsplclose 0xC2 /* close print spool file */
214#define SMBsplretq 0xC3 /* return print queue */
215#define SMBsends 0xD0 /* send single block message */
216#define SMBsendb 0xD1 /* send broadcast message */
217#define SMBfwdname 0xD2 /* forward user name */
218#define SMBcancelf 0xD3 /* cancel forward */
219#define SMBgetmac 0xD4 /* get machine name */
220#define SMBsendstrt 0xD5 /* send start of multi-block message */
221#define SMBsendend 0xD6 /* send end of multi-block message */
222#define SMBsendtxt 0xD7 /* send text of multi-block message */
223
224/* Core+ protocol */
225#define SMBlockread 0x13 /* Lock a range and read */
226#define SMBwriteunlock 0x14 /* Unlock a range then write */
227#define SMBreadbraw 0x1a /* read a block of data with no smb header */
228#define SMBwritebraw 0x1d /* write a block of data with no smb header */
229#define SMBwritec 0x20 /* secondary write request */
230#define SMBwriteclose 0x2c /* write a file then close it */
231
232/* dos extended protocol */
233#define SMBreadBraw 0x1A /* read block raw */
234#define SMBreadBmpx 0x1B /* read block multiplexed */
235#define SMBreadBs 0x1C /* read block (secondary response) */
236#define SMBwriteBraw 0x1D /* write block raw */
237#define SMBwriteBmpx 0x1E /* write block multiplexed */
238#define SMBwriteBs 0x1F /* write block (secondary request) */
239#define SMBwriteC 0x20 /* write complete response */
240#define SMBsetattrE 0x22 /* set file attributes expanded */
241#define SMBgetattrE 0x23 /* get file attributes expanded */
242#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */
243#define SMBtrans 0x25 /* transaction - name, bytes in/out */
244#define SMBtranss 0x26 /* transaction (secondary request/response) */
245#define SMBioctl 0x27 /* IOCTL */
246#define SMBioctls 0x28 /* IOCTL (secondary request/response) */
247#define SMBcopy 0x29 /* copy */
248#define SMBmove 0x2A /* move */
249#define SMBecho 0x2B /* echo */
250#define SMBopenX 0x2D /* open and X */
251#define SMBreadX 0x2E /* read and X */
252#define SMBwriteX 0x2F /* write and X */
253#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */
254#define SMBtconX 0x75 /* tree connect and X */
255#define SMBffirst 0x82 /* find first */
256#define SMBfunique 0x83 /* find unique */
257#define SMBfclose 0x84 /* find close */
258#define SMBinvalid 0xFE /* invalid command */
259
260
261/* Extended 2.0 protocol */
262#define SMBtrans2 0x32 /* TRANS2 protocol set */
263#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */
264#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */
265#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
266#define SMBulogoffX 0x74 /* user logoff */
267
268/* these are the TRANS2 sub commands */
269#define TRANSACT2_OPEN 0
270#define TRANSACT2_FINDFIRST 1
271#define TRANSACT2_FINDNEXT 2
272#define TRANSACT2_QFSINFO 3
273#define TRANSACT2_SETFSINFO 4
274#define TRANSACT2_QPATHINFO 5
275#define TRANSACT2_SETPATHINFO 6
276#define TRANSACT2_QFILEINFO 7
277#define TRANSACT2_SETFILEINFO 8
278#define TRANSACT2_FSCTL 9
279#define TRANSACT2_IOCTL 10
280#define TRANSACT2_FINDNOTIFYFIRST 11
281#define TRANSACT2_FINDNOTIFYNEXT 12
282#define TRANSACT2_MKDIR 13
283
284/* Information Levels - Shared? */
285#define SMB_INFO_STANDARD 1
286#define SMB_INFO_QUERY_EA_SIZE 2
287#define SMB_INFO_QUERY_EAS_FROM_LIST 3
288#define SMB_INFO_QUERY_ALL_EAS 4
289#define SMB_INFO_IS_NAME_VALID 6
290
291/* Information Levels - TRANSACT2_FINDFIRST */
292#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
293#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
294#define SMB_FIND_FILE_NAMES_INFO 0x103
295#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
296
297/* Information Levels - TRANSACT2_QPATHINFO */
298#define SMB_QUERY_FILE_BASIC_INFO 0x101
299#define SMB_QUERY_FILE_STANDARD_INFO 0x102
300#define SMB_QUERY_FILE_EA_INFO 0x103
301#define SMB_QUERY_FILE_NAME_INFO 0x104
302#define SMB_QUERY_FILE_ALL_INFO 0x107
303#define SMB_QUERY_FILE_ALT_NAME_INFO 0x108
304#define SMB_QUERY_FILE_STREAM_INFO 0x109
305#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10b
306
307/* Information Levels - TRANSACT2_SETFILEINFO */
308#define SMB_SET_FILE_BASIC_INFO 0x101
309#define SMB_SET_FILE_DISPOSITION_INFO 0x102
310#define SMB_SET_FILE_ALLOCATION_INFO 0x103
311#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
312
313/* smb_flg field flags */
314#define SMB_FLAGS_SUPPORT_LOCKREAD 0x01
315#define SMB_FLAGS_CLIENT_BUF_AVAIL 0x02
316#define SMB_FLAGS_RESERVED 0x04
317#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
318#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
319#define SMB_FLAGS_REQUEST_OPLOCK 0x20
320#define SMB_FLAGS_REQUEST_BATCH_OPLOCK 0x40
321#define SMB_FLAGS_REPLY 0x80
322
323/* smb_flg2 field flags (samba-2.2.0/source/include/smb.h) */
324#define SMB_FLAGS2_LONG_PATH_COMPONENTS 0x0001
325#define SMB_FLAGS2_EXTENDED_ATTRIBUTES 0x0002
326#define SMB_FLAGS2_DFS_PATHNAMES 0x1000
327#define SMB_FLAGS2_READ_PERMIT_NO_EXECUTE 0x2000
328#define SMB_FLAGS2_32_BIT_ERROR_CODES 0x4000
329#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
330
331
332/*
333 * UNIX stuff (from samba trans2.h)
334 */
335#define MIN_UNIX_INFO_LEVEL 0x200
336#define MAX_UNIX_INFO_LEVEL 0x2FF
337#define SMB_FIND_FILE_UNIX 0x202
338#define SMB_QUERY_FILE_UNIX_BASIC 0x200
339#define SMB_QUERY_FILE_UNIX_LINK 0x201
340#define SMB_QUERY_FILE_UNIX_HLINK 0x202
341#define SMB_SET_FILE_UNIX_BASIC 0x200
342#define SMB_SET_FILE_UNIX_LINK 0x201
343#define SMB_SET_FILE_UNIX_HLINK 0x203
344#define SMB_QUERY_CIFS_UNIX_INFO 0x200
345
346/* values which means "don't change it" */
347#define SMB_MODE_NO_CHANGE 0xFFFFFFFF
348#define SMB_UID_NO_CHANGE 0xFFFFFFFF
349#define SMB_GID_NO_CHANGE 0xFFFFFFFF
350#define SMB_TIME_NO_CHANGE 0xFFFFFFFFFFFFFFFFULL
351#define SMB_SIZE_NO_CHANGE 0xFFFFFFFFFFFFFFFFULL
352
353/* UNIX filetype mappings. */
354#define UNIX_TYPE_FILE 0
355#define UNIX_TYPE_DIR 1
356#define UNIX_TYPE_SYMLINK 2
357#define UNIX_TYPE_CHARDEV 3
358#define UNIX_TYPE_BLKDEV 4
359#define UNIX_TYPE_FIFO 5
360#define UNIX_TYPE_SOCKET 6
361#define UNIX_TYPE_UNKNOWN 0xFFFFFFFF
362
363#endif /* _SMBNO_H_ */
diff --git a/drivers/staging/smbfs/sock.c b/drivers/staging/smbfs/sock.c
deleted file mode 100644
index 9e264090e61..00000000000
--- a/drivers/staging/smbfs/sock.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/*
2 * sock.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/fs.h>
11#include <linux/time.h>
12#include <linux/errno.h>
13#include <linux/socket.h>
14#include <linux/fcntl.h>
15#include <linux/file.h>
16#include <linux/in.h>
17#include <linux/net.h>
18#include <linux/mm.h>
19#include <linux/netdevice.h>
20#include <linux/workqueue.h>
21#include <net/scm.h>
22#include <net/tcp_states.h>
23#include <net/ip.h>
24
25#include <asm/uaccess.h>
26#include <asm/ioctls.h>
27
28#include "smb_fs.h"
29#include "smb.h"
30#include "smbno.h"
31#include "smb_debug.h"
32#include "proto.h"
33#include "request.h"
34
35
36static int
37_recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags)
38{
39 struct kvec iov = {ubuf, size};
40 struct msghdr msg = {.msg_flags = flags};
41 msg.msg_flags |= MSG_DONTWAIT | MSG_NOSIGNAL;
42 return kernel_recvmsg(socket, &msg, &iov, 1, size, msg.msg_flags);
43}
44
45/*
46 * Return the server this socket belongs to
47 */
48static struct smb_sb_info *
49server_from_socket(struct socket *socket)
50{
51 return socket->sk->sk_user_data;
52}
53
54/*
55 * Called when there is data on the socket.
56 */
57void
58smb_data_ready(struct sock *sk, int len)
59{
60 struct smb_sb_info *server = server_from_socket(sk->sk_socket);
61 void (*data_ready)(struct sock *, int) = server->data_ready;
62
63 data_ready(sk, len);
64 VERBOSE("(%p, %d)\n", sk, len);
65 smbiod_wake_up();
66}
67
68int
69smb_valid_socket(struct inode * inode)
70{
71 return (inode && S_ISSOCK(inode->i_mode) &&
72 SOCKET_I(inode)->type == SOCK_STREAM);
73}
74
75static struct socket *
76server_sock(struct smb_sb_info *server)
77{
78 struct file *file;
79
80 if (server && (file = server->sock_file))
81 {
82#ifdef SMBFS_PARANOIA
83 if (!smb_valid_socket(file->f_path.dentry->d_inode))
84 PARANOIA("bad socket!\n");
85#endif
86 return SOCKET_I(file->f_path.dentry->d_inode);
87 }
88 return NULL;
89}
90
91void
92smb_close_socket(struct smb_sb_info *server)
93{
94 struct file * file = server->sock_file;
95
96 if (file) {
97 struct socket *sock = server_sock(server);
98
99 VERBOSE("closing socket %p\n", sock);
100 sock->sk->sk_data_ready = server->data_ready;
101 server->sock_file = NULL;
102 fput(file);
103 }
104}
105
106static int
107smb_get_length(struct socket *socket, unsigned char *header)
108{
109 int result;
110
111 result = _recvfrom(socket, header, 4, MSG_PEEK);
112 if (result == -EAGAIN)
113 return -ENODATA;
114 if (result < 0) {
115 PARANOIA("recv error = %d\n", -result);
116 return result;
117 }
118 if (result < 4)
119 return -ENODATA;
120
121 switch (header[0]) {
122 case 0x00:
123 case 0x82:
124 break;
125
126 case 0x85:
127 DEBUG1("Got SESSION KEEP ALIVE\n");
128 _recvfrom(socket, header, 4, 0); /* read away */
129 return -ENODATA;
130
131 default:
132 PARANOIA("Invalid NBT packet, code=%x\n", header[0]);
133 return -EIO;
134 }
135
136 /* The length in the RFC NB header is the raw data length */
137 return smb_len(header);
138}
139
140int
141smb_recv_available(struct smb_sb_info *server)
142{
143 mm_segment_t oldfs;
144 int avail, err;
145 struct socket *sock = server_sock(server);
146
147 oldfs = get_fs();
148 set_fs(get_ds());
149 err = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail);
150 set_fs(oldfs);
151 return (err >= 0) ? avail : err;
152}
153
154/*
155 * Adjust the kvec to move on 'n' bytes (from nfs/sunrpc)
156 */
157static int
158smb_move_iov(struct kvec **data, size_t *num, struct kvec *vec, unsigned amount)
159{
160 struct kvec *iv = *data;
161 int i;
162 int len;
163
164 /*
165 * Eat any sent kvecs
166 */
167 while (iv->iov_len <= amount) {
168 amount -= iv->iov_len;
169 iv++;
170 (*num)--;
171 }
172
173 /*
174 * And chew down the partial one
175 */
176 vec[0].iov_len = iv->iov_len-amount;
177 vec[0].iov_base =((unsigned char *)iv->iov_base)+amount;
178 iv++;
179
180 len = vec[0].iov_len;
181
182 /*
183 * And copy any others
184 */
185 for (i = 1; i < *num; i++) {
186 vec[i] = *iv++;
187 len += vec[i].iov_len;
188 }
189
190 *data = vec;
191 return len;
192}
193
194/*
195 * smb_receive_header
196 * Only called by the smbiod thread.
197 */
198int
199smb_receive_header(struct smb_sb_info *server)
200{
201 struct socket *sock;
202 int result = 0;
203 unsigned char peek_buf[4];
204
205 result = -EIO;
206 sock = server_sock(server);
207 if (!sock)
208 goto out;
209 if (sock->sk->sk_state != TCP_ESTABLISHED)
210 goto out;
211
212 if (!server->smb_read) {
213 result = smb_get_length(sock, peek_buf);
214 if (result < 0) {
215 if (result == -ENODATA)
216 result = 0;
217 goto out;
218 }
219 server->smb_len = result + 4;
220
221 if (server->smb_len < SMB_HEADER_LEN) {
222 PARANOIA("short packet: %d\n", result);
223 server->rstate = SMB_RECV_DROP;
224 result = -EIO;
225 goto out;
226 }
227 if (server->smb_len > SMB_MAX_PACKET_SIZE) {
228 PARANOIA("long packet: %d\n", result);
229 server->rstate = SMB_RECV_DROP;
230 result = -EIO;
231 goto out;
232 }
233 }
234
235 result = _recvfrom(sock, server->header + server->smb_read,
236 SMB_HEADER_LEN - server->smb_read, 0);
237 VERBOSE("_recvfrom: %d\n", result);
238 if (result < 0) {
239 VERBOSE("receive error: %d\n", result);
240 goto out;
241 }
242 server->smb_read += result;
243
244 if (server->smb_read == SMB_HEADER_LEN)
245 server->rstate = SMB_RECV_HCOMPLETE;
246out:
247 return result;
248}
249
250static char drop_buffer[PAGE_SIZE];
251
252/*
253 * smb_receive_drop - read and throw away the data
254 * Only called by the smbiod thread.
255 *
256 * FIXME: we are in the kernel, could we just tell the socket that we want
257 * to drop stuff from the buffer?
258 */
259int
260smb_receive_drop(struct smb_sb_info *server)
261{
262 struct socket *sock;
263 unsigned int flags;
264 struct kvec iov;
265 struct msghdr msg;
266 int rlen = smb_len(server->header) - server->smb_read + 4;
267 int result = -EIO;
268
269 if (rlen > PAGE_SIZE)
270 rlen = PAGE_SIZE;
271
272 sock = server_sock(server);
273 if (!sock)
274 goto out;
275 if (sock->sk->sk_state != TCP_ESTABLISHED)
276 goto out;
277
278 flags = MSG_DONTWAIT | MSG_NOSIGNAL;
279 iov.iov_base = drop_buffer;
280 iov.iov_len = PAGE_SIZE;
281 msg.msg_flags = flags;
282 msg.msg_name = NULL;
283 msg.msg_namelen = 0;
284 msg.msg_control = NULL;
285
286 result = kernel_recvmsg(sock, &msg, &iov, 1, rlen, flags);
287
288 VERBOSE("read: %d\n", result);
289 if (result < 0) {
290 VERBOSE("receive error: %d\n", result);
291 goto out;
292 }
293 server->smb_read += result;
294
295 if (server->smb_read >= server->smb_len)
296 server->rstate = SMB_RECV_END;
297
298out:
299 return result;
300}
301
302/*
303 * smb_receive
304 * Only called by the smbiod thread.
305 */
306int
307smb_receive(struct smb_sb_info *server, struct smb_request *req)
308{
309 struct socket *sock;
310 unsigned int flags;
311 struct kvec iov[4];
312 struct kvec *p = req->rq_iov;
313 size_t num = req->rq_iovlen;
314 struct msghdr msg;
315 int rlen;
316 int result = -EIO;
317
318 sock = server_sock(server);
319 if (!sock)
320 goto out;
321 if (sock->sk->sk_state != TCP_ESTABLISHED)
322 goto out;
323
324 flags = MSG_DONTWAIT | MSG_NOSIGNAL;
325 msg.msg_flags = flags;
326 msg.msg_name = NULL;
327 msg.msg_namelen = 0;
328 msg.msg_control = NULL;
329
330 /* Dont repeat bytes and count available bufferspace */
331 rlen = min_t(int, smb_move_iov(&p, &num, iov, req->rq_bytes_recvd),
332 (req->rq_rlen - req->rq_bytes_recvd));
333
334 result = kernel_recvmsg(sock, &msg, p, num, rlen, flags);
335
336 VERBOSE("read: %d\n", result);
337 if (result < 0) {
338 VERBOSE("receive error: %d\n", result);
339 goto out;
340 }
341 req->rq_bytes_recvd += result;
342 server->smb_read += result;
343
344out:
345 return result;
346}
347
348/*
349 * Try to send a SMB request. This may return after sending only parts of the
350 * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
351 *
352 * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
353 */
354int
355smb_send_request(struct smb_request *req)
356{
357 struct smb_sb_info *server = req->rq_server;
358 struct socket *sock;
359 struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
360 int slen = req->rq_slen - req->rq_bytes_sent;
361 int result = -EIO;
362 struct kvec iov[4];
363 struct kvec *p = req->rq_iov;
364 size_t num = req->rq_iovlen;
365
366 sock = server_sock(server);
367 if (!sock)
368 goto out;
369 if (sock->sk->sk_state != TCP_ESTABLISHED)
370 goto out;
371
372 /* Dont repeat bytes */
373 if (req->rq_bytes_sent)
374 smb_move_iov(&p, &num, iov, req->rq_bytes_sent);
375
376 result = kernel_sendmsg(sock, &msg, p, num, slen);
377
378 if (result >= 0) {
379 req->rq_bytes_sent += result;
380 if (req->rq_bytes_sent >= req->rq_slen)
381 req->rq_flags |= SMB_REQ_TRANSMITTED;
382 }
383out:
384 return result;
385}
diff --git a/drivers/staging/smbfs/symlink.c b/drivers/staging/smbfs/symlink.c
deleted file mode 100644
index 632c4acd062..00000000000
--- a/drivers/staging/smbfs/symlink.c
+++ /dev/null
@@ -1,67 +0,0 @@
1/*
2 * symlink.c
3 *
4 * Copyright (C) 2002 by John Newbigin
5 *
6 * Please add a note about your changes to smbfs in the ChangeLog file.
7 */
8
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/fcntl.h>
12#include <linux/stat.h>
13#include <linux/mm.h>
14#include <linux/slab.h>
15#include <linux/pagemap.h>
16#include <linux/net.h>
17#include <linux/namei.h>
18
19#include <asm/uaccess.h>
20#include <asm/system.h>
21
22#include "smbno.h"
23#include "smb_fs.h"
24#include "smb_debug.h"
25#include "proto.h"
26
27int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname)
28{
29 DEBUG1("create symlink %s -> %s/%s\n", oldname, DENTRY_PATH(dentry));
30
31 return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname);
32}
33
34static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd)
35{
36 char *link = __getname();
37 DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));
38
39 if (!link) {
40 link = ERR_PTR(-ENOMEM);
41 } else {
42 int len = smb_proc_read_link(server_from_dentry(dentry),
43 dentry, link, PATH_MAX - 1);
44 if (len < 0) {
45 __putname(link);
46 link = ERR_PTR(len);
47 } else {
48 link[len] = 0;
49 }
50 }
51 nd_set_link(nd, link);
52 return NULL;
53}
54
55static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
56{
57 char *s = nd_get_link(nd);
58 if (!IS_ERR(s))
59 __putname(s);
60}
61
62const struct inode_operations smb_link_inode_operations =
63{
64 .readlink = generic_readlink,
65 .follow_link = smb_follow_link,
66 .put_link = smb_put_link,
67};