1 /* $NetBSD: smbfs_smb.c,v 1.40 2009/04/18 14:58:04 tsutsui Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 2000-2001 Boris Popov
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by Boris Popov.
47 * 4. Neither the name of the author nor the names of any co-contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * FreeBSD: src/sys/fs/smbfs/smbfs_smb.c,v 1.3 2001/12/10 08:09:46 obrien Exp
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: smbfs_smb.c,v 1.40 2009/04/18 14:58:04 tsutsui Exp $");
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kernel.h>
72 #include <sys/malloc.h>
75 #include <sys/vnode.h>
77 #include <sys/mount.h>
83 #include <netsmb/smb.h>
84 #include <netsmb/smb_subr.h>
85 #include <netsmb/smb_rq.h>
86 #include <netsmb/smb_conn.h>
88 #include <fs/smbfs/smbfs.h>
89 #include <fs/smbfs/smbfs_node.h>
90 #include <fs/smbfs/smbfs_subr.h>
93 * Lack of inode numbers leads us to the problem of generating them.
94 * Partially this problem can be solved by having a dir/file cache
95 * with inode numbers generated from the incremented by one counter.
96 * However this way will require too much kernel memory, gives all
97 * sorts of locking and consistency problems, not to mentinon counter overflows.
98 * So, I'm decided to use a hash function to generate pseudo random (and unique)
102 smbfs_getino(struct smbnode
*dnp
, const char *name
, int nmlen
)
111 MD5Update(&md5
, name
, nmlen
);
112 MD5Final((u_char
*)state
, &md5
);
113 for (i
= 0, ino
= 0; i
< 4; i
++)
115 return dnp
->n_ino
+ ino
;
119 ino
= dnp
->n_ino
+ smbfs_hash(name
, nmlen
);
126 smbfs_smb_lockandx(struct smbnode
*np
, int op
, void *id
, off_t start
, off_t end
,
127 struct smb_cred
*scred
)
129 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
135 if (op
== SMB_LOCK_SHARED
)
136 ltype
|= SMB_LOCKING_ANDX_SHARED_LOCK
;
137 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_LOCKING_ANDX
, scred
, &rqp
);
140 smb_rq_getrequest(rqp
, &mbp
);
142 mb_put_uint8(mbp
, 0xff); /* secondary command */
143 mb_put_uint8(mbp
, 0); /* MBZ */
144 mb_put_uint16le(mbp
, 0);
145 mb_put_mem(mbp
, (void *)&np
->n_fid
, 2, MB_MSYSTEM
);
146 mb_put_uint8(mbp
, ltype
); /* locktype */
147 mb_put_uint8(mbp
, 0); /* oplocklevel - 0 seems is NO_OPLOCK */
148 mb_put_uint32le(mbp
, 0); /* timeout - break immediately */
149 mb_put_uint16le(mbp
, op
== SMB_LOCK_RELEASE
? 1 : 0);
150 mb_put_uint16le(mbp
, op
== SMB_LOCK_RELEASE
? 0 : 1);
153 mb_put_uint16le(mbp
, (((long) id
) & 0xffff)); /* process ID */
154 mb_put_uint32le(mbp
, start
);
155 mb_put_uint32le(mbp
, end
- start
);
157 error
= smb_rq_simple(rqp
);
163 smbfs_smb_lock(struct smbnode
*np
, int op
, void *id
,
164 off_t start
, off_t end
, struct smb_cred
*scred
)
166 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
168 if (SMB_DIALECT(SSTOVC(ssp
)) < SMB_DIALECT_LANMAN1_0
)
170 * TODO: use LOCK_BYTE_RANGE here.
174 return smbfs_smb_lockandx(np
, op
, id
, start
, end
, scred
);
178 smbfs_smb_statvfs(struct smb_share
*ssp
, struct statvfs
*sbp
,
179 struct smb_cred
*scred
)
181 unsigned long bsize
; /* Block (allocation unit) size */
182 unsigned long bavail
, bfree
;
185 * The SMB request work with notion of sector size and
186 * allocation units. Allocation unit is what 'block'
187 * means in Unix context, sector size might be HW sector size.
190 if (SMB_DIALECT(SSTOVC(ssp
)) >= SMB_DIALECT_LANMAN2_0
) {
191 struct smb_t2rq
*t2p
;
195 u_int32_t units
, bpu
, funits
;
198 error
= smb_t2_alloc(SSTOCP(ssp
),
199 SMB_TRANS2_QUERY_FS_INFORMATION
, scred
, &t2p
);
202 mbp
= &t2p
->t2_tparam
;
204 mb_put_uint16le(mbp
, SMB_INFO_ALLOCATION
);
205 t2p
->t2_maxpcount
= 4;
206 t2p
->t2_maxdcount
= 4 * 4 + 2;
207 error
= smb_t2_request(t2p
);
212 mdp
= &t2p
->t2_rdata
;
213 md_get_uint32(mdp
, NULL
); /* fs id */
214 md_get_uint32le(mdp
, &bpu
); /* Number of sectors per unit */
215 md_get_uint32le(mdp
, &units
); /* Total number of units */
216 md_get_uint32le(mdp
, &funits
); /* Number of available units */
217 md_get_uint16le(mdp
, &secsz
); /* Number of bytes per sector */
226 u_int16_t units
, bpu
, secsz
, funits
;
229 error
= smb_rq_alloc(SSTOCP(ssp
),
230 SMB_COM_QUERY_INFORMATION_DISK
, scred
, &rqp
);
237 error
= smb_rq_simple(rqp
);
242 smb_rq_getreply(rqp
, &mdp
);
243 md_get_uint16le(mdp
, &units
); /* Total units per server */
244 md_get_uint16le(mdp
, &bpu
); /* Blocks per allocation unit */
245 md_get_uint16le(mdp
, &secsz
); /* Block size (in bytes) */
246 md_get_uint16le(mdp
, &funits
); /* Number of free units */
254 sbp
->f_bsize
= bsize
; /* fundamental file system block size */
255 sbp
->f_frsize
= bsize
; /* fundamental file system frag size */
256 sbp
->f_iosize
= bsize
; /* optimal I/O size */
257 sbp
->f_blocks
= bavail
; /* total data blocks in file system */
258 sbp
->f_bfree
= bfree
; /* free blocks in fs */
259 sbp
->f_bresvd
= 0; /* reserved blocks in fs */
260 sbp
->f_bavail
= bfree
; /* free blocks avail to non-superuser */
261 sbp
->f_files
= 0xffff; /* total file nodes in file system */
262 sbp
->f_ffree
= 0xffff; /* free file nodes to non-superuser */
263 sbp
->f_favail
= 0xffff; /* free file nodes in fs */
264 sbp
->f_fresvd
= 0; /* reserved file nodes in fs */
269 smbfs_smb_seteof(struct smbnode
*np
, int64_t newsize
, struct smb_cred
*scred
)
271 struct smb_t2rq
*t2p
;
272 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
276 error
= smb_t2_alloc(SSTOCP(ssp
), SMB_TRANS2_SET_FILE_INFORMATION
,
280 mbp
= &t2p
->t2_tparam
;
282 mb_put_mem(mbp
, (void *)&np
->n_fid
, 2, MB_MSYSTEM
);
283 mb_put_uint16le(mbp
, SMB_SET_FILE_END_OF_FILE_INFO
);
284 mb_put_uint32le(mbp
, 0);
285 mbp
= &t2p
->t2_tdata
;
287 mb_put_int64le(mbp
, newsize
);
288 mb_put_uint32le(mbp
, 0); /* padding */
289 mb_put_uint16le(mbp
, 0);
290 t2p
->t2_maxpcount
= 2;
291 t2p
->t2_maxdcount
= 0;
292 error
= smb_t2_request(t2p
);
298 smbfs_smb_setfsize(struct smbnode
*np
, u_quad_t newsize
,
299 struct smb_cred
*scred
)
301 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
306 if (newsize
>= (1LL << 32)) {
307 if (!(SMB_CAPS(SSTOVC(ssp
)) & SMB_CAP_LARGE_FILES
))
309 return smbfs_smb_seteof(np
, (int64_t)newsize
, scred
);
312 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_WRITE
, scred
, &rqp
);
315 smb_rq_getrequest(rqp
, &mbp
);
317 mb_put_mem(mbp
, (void *)&np
->n_fid
, 2, MB_MSYSTEM
);
318 mb_put_uint16le(mbp
, 0);
319 mb_put_uint32le(mbp
, newsize
);
320 mb_put_uint16le(mbp
, 0);
323 mb_put_uint8(mbp
, SMB_DT_DATA
);
324 mb_put_uint16le(mbp
, 0);
326 error
= smb_rq_simple(rqp
);
333 * Set DOS file attributes. mtime should be NULL for dialects above lm10
336 smbfs_smb_setpattr(struct smbnode
*np
, u_int16_t attr
, struct timespec
*mtime
,
337 struct smb_cred
*scred
)
340 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
345 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_SET_INFORMATION
, scred
, &rqp
);
348 svtz
= SSTOVC(ssp
)->vc_sopt
.sv_tz
;
349 smb_rq_getrequest(rqp
, &mbp
);
351 mb_put_uint16le(mbp
, attr
);
353 smb_time_local2server(mtime
, svtz
, &xtime
);
356 mb_put_uint32le(mbp
, xtime
); /* mtime */
357 mb_put_mem(mbp
, NULL
, 5 * 2, MB_MZERO
);
360 mb_put_uint8(mbp
, SMB_DT_ASCII
);
362 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), np
, NULL
, 0);
365 mb_put_uint8(mbp
, SMB_DT_ASCII
);
366 mb_put_uint8(mbp
, 0);
368 error
= smb_rq_simple(rqp
);
377 * Note, win95 doesn't support this call.
380 smbfs_smb_setptime2(struct smbnode
*np
, struct timespec
*mtime
,
381 struct timespec
*atime
, int attr
, struct smb_cred
*scred
)
383 struct smb_t2rq
*t2p
;
384 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
385 struct smb_vc
*vcp
= SSTOVC(ssp
);
387 u_int16_t xdate
, xtime
;
390 error
= smb_t2_alloc(SSTOCP(ssp
), SMB_TRANS2_SET_PATH_INFORMATION
,
394 mbp
= &t2p
->t2_tparam
;
396 mb_put_uint16le(mbp
, SMB_INFO_STANDARD
);
397 mb_put_uint32le(mbp
, 0); /* MBZ */
398 error
= smbfs_fullpath(mbp
, vcp
, np
, NULL
, 0);
403 tzoff
= vcp
->vc_sopt
.sv_tz
;
404 mbp
= &t2p
->t2_tdata
;
406 mb_put_uint32le(mbp
, 0); /* creation time */
408 smb_time_unix2dos(atime
, tzoff
, &xdate
, &xtime
, NULL
);
411 mb_put_uint16le(mbp
, xdate
);
412 mb_put_uint16le(mbp
, xtime
);
414 smb_time_unix2dos(mtime
, tzoff
, &xdate
, &xtime
, NULL
);
417 mb_put_uint16le(mbp
, xdate
);
418 mb_put_uint16le(mbp
, xtime
);
419 mb_put_uint32le(mbp
, 0); /* file size */
420 mb_put_uint32le(mbp
, 0); /* allocation unit size */
421 mb_put_uint16le(mbp
, attr
); /* DOS attr */
422 mb_put_uint32le(mbp
, 0); /* EA size */
423 t2p
->t2_maxpcount
= 5 * 2;
424 t2p
->t2_maxdcount
= vcp
->vc_txmax
;
425 error
= smb_t2_request(t2p
);
431 * NT level. Specially for win9x
435 smbfs_smb_setpattrNT(struct smbnode
*np
, u_short attr
, struct timespec
*mtime
,
436 struct timespec
*atime
, struct smb_cred
*scred
)
438 struct smb_t2rq
*t2p
;
439 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
440 struct smb_vc
*vcp
= SSTOVC(ssp
);
445 error
= smb_t2_alloc(SSTOCP(ssp
), SMB_TRANS2_SET_PATH_INFORMATION
,
449 mbp
= &t2p
->t2_tparam
;
451 mb_put_uint16le(mbp
, SMB_SET_FILE_BASIC_INFO
);
452 mb_put_uint32le(mbp
, 0); /* MBZ */
453 error
= smbfs_fullpath(mbp
, vcp
, np
, NULL
, 0);
458 tzoff
= vcp
->vc_sopt
.sv_tz
;
459 mbp
= &t2p
->t2_tdata
;
461 mb_put_int64le(mbp
, 0); /* creation time */
463 smb_time_local2NT(atime
, tzoff
, &tm
);
466 mb_put_int64le(mbp
, tm
);
468 smb_time_local2NT(mtime
, tzoff
, &tm
);
471 mb_put_int64le(mbp
, tm
);
472 mb_put_int64le(mbp
, tm
); /* change time */
473 mb_put_uint32le(mbp
, attr
); /* attr */
474 t2p
->t2_maxpcount
= 24;
475 t2p
->t2_maxdcount
= 56;
476 error
= smb_t2_request(t2p
);
483 * Set file atime and mtime. Doesn't supported by core dialect.
486 smbfs_smb_setftime(struct smbnode
*np
, struct timespec
*mtime
,
487 struct timespec
*atime
, struct smb_cred
*scred
)
490 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
492 u_int16_t xdate
, xtime
;
495 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_SET_INFORMATION2
, scred
, &rqp
);
498 tzoff
= SSTOVC(ssp
)->vc_sopt
.sv_tz
;
499 smb_rq_getrequest(rqp
, &mbp
);
501 mb_put_mem(mbp
, (void *)&np
->n_fid
, 2, MB_MSYSTEM
);
502 mb_put_uint32le(mbp
, 0); /* creation time */
505 smb_time_unix2dos(atime
, tzoff
, &xdate
, &xtime
, NULL
);
508 mb_put_uint16le(mbp
, xdate
);
509 mb_put_uint16le(mbp
, xtime
);
511 smb_time_unix2dos(mtime
, tzoff
, &xdate
, &xtime
, NULL
);
514 mb_put_uint16le(mbp
, xdate
);
515 mb_put_uint16le(mbp
, xtime
);
519 error
= smb_rq_simple(rqp
);
520 SMBSDEBUG(("%d\n", error
));
526 * Set DOS file attributes.
527 * Looks like this call can be used only if CAP_NT_SMBS bit is on.
530 smbfs_smb_setfattrNT(struct smbnode
*np
, u_int16_t attr
, struct timespec
*mtime
,
531 struct timespec
*atime
, struct smb_cred
*scred
)
533 struct smb_t2rq
*t2p
;
534 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
539 error
= smb_t2_alloc(SSTOCP(ssp
), SMB_TRANS2_SET_FILE_INFORMATION
,
543 svtz
= SSTOVC(ssp
)->vc_sopt
.sv_tz
;
544 mbp
= &t2p
->t2_tparam
;
546 mb_put_mem(mbp
, (void *)&np
->n_fid
, 2, MB_MSYSTEM
); /* FID */
547 mb_put_uint16le(mbp
, SMB_SET_FILE_BASIC_INFO
); /* info level */
548 mb_put_uint32le(mbp
, 0); /* reserved */
549 mbp
= &t2p
->t2_tdata
;
551 mb_put_int64le(mbp
, 0); /* creation time */
553 smb_time_local2NT(atime
, svtz
, &tm
);
556 mb_put_int64le(mbp
, tm
);
558 smb_time_local2NT(mtime
, svtz
, &tm
);
561 mb_put_int64le(mbp
, tm
);
562 mb_put_int64le(mbp
, tm
); /* change time */
563 mb_put_uint16le(mbp
, attr
);
564 mb_put_uint32le(mbp
, 0); /* padding */
565 mb_put_uint16le(mbp
, 0);
566 t2p
->t2_maxpcount
= 2;
567 t2p
->t2_maxdcount
= 0;
568 error
= smb_t2_request(t2p
);
575 smbfs_smb_open(struct smbnode
*np
, int accmode
, struct smb_cred
*scred
)
578 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
582 u_int16_t fid
, wattr
, grantedmode
;
585 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_OPEN
, scred
, &rqp
);
588 smb_rq_getrequest(rqp
, &mbp
);
590 mb_put_uint16le(mbp
, accmode
);
591 mb_put_uint16le(mbp
, SMB_FA_SYSTEM
| SMB_FA_HIDDEN
);
594 mb_put_uint8(mbp
, SMB_DT_ASCII
);
596 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), np
, NULL
, 0);
600 error
= smb_rq_simple(rqp
);
603 smb_rq_getreply(rqp
, &mdp
);
604 if (md_get_uint8(mdp
, &wc
) != 0 || wc
!= 7) {
608 md_get_uint16(mdp
, &fid
);
609 md_get_uint16le(mdp
, &wattr
);
610 md_get_uint32(mdp
, NULL
); /* mtime */
611 md_get_uint32(mdp
, NULL
); /* fsize */
612 md_get_uint16le(mdp
, &grantedmode
);
614 * TODO: refresh attributes from this reply
621 np
->n_rwstate
= grantedmode
;
627 smbfs_smb_close(struct smb_share
*ssp
, u_int16_t fid
, struct timespec
*mtime
,
628 struct smb_cred
*scred
)
635 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_CLOSE
, scred
, &rqp
);
638 smb_rq_getrequest(rqp
, &mbp
);
640 mb_put_mem(mbp
, (void *)&fid
, sizeof(fid
), MB_MSYSTEM
);
642 smb_time_local2server(mtime
, SSTOVC(ssp
)->vc_sopt
.sv_tz
, &xtime
);
645 mb_put_uint32le(mbp
, xtime
);
649 error
= smb_rq_simple(rqp
);
655 smbfs_smb_create(struct smbnode
*dnp
, const char *name
, int nmlen
,
656 struct smb_cred
*scred
)
659 struct smb_share
*ssp
= dnp
->n_mount
->sm_share
;
662 struct timespec ctime
;
668 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_CREATE_NEW
, scred
, &rqp
);
671 smb_rq_getrequest(rqp
, &mbp
);
673 /* get current time */
675 smb_time_local2server(&ctime
, SSTOVC(ssp
)->vc_sopt
.sv_tz
, &tm
);
678 mb_put_uint16le(mbp
, SMB_FA_ARCHIVE
); /* attributes */
679 mb_put_uint32le(mbp
, tm
);
683 mb_put_uint8(mbp
, SMB_DT_ASCII
);
684 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), dnp
, name
, nmlen
);
687 error
= smb_rq_simple(rqp
);
689 smb_rq_getreply(rqp
, &mdp
);
690 md_get_uint8(mdp
, &wc
);
692 md_get_uint16le(mdp
, &fid
);
700 smbfs_smb_close(ssp
, fid
, &ctime
, scred
);
706 smbfs_smb_delete(struct smbnode
*np
, struct smb_cred
*scred
)
709 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
713 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_DELETE
, scred
, &rqp
);
716 smb_rq_getrequest(rqp
, &mbp
);
718 mb_put_uint16le(mbp
, SMB_FA_SYSTEM
| SMB_FA_HIDDEN
);
721 mb_put_uint8(mbp
, SMB_DT_ASCII
);
722 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), np
, NULL
, 0);
725 error
= smb_rq_simple(rqp
);
732 smbfs_smb_rename(struct smbnode
*src
, struct smbnode
*tdnp
,
733 const char *tname
, int tnmlen
, struct smb_cred
*scred
)
736 struct smb_share
*ssp
= src
->n_mount
->sm_share
;
740 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_RENAME
, scred
, &rqp
);
743 smb_rq_getrequest(rqp
, &mbp
);
745 mb_put_uint16le(mbp
, SMB_FA_SYSTEM
| SMB_FA_HIDDEN
);
748 mb_put_uint8(mbp
, SMB_DT_ASCII
);
750 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), src
, NULL
, 0);
753 mb_put_uint8(mbp
, SMB_DT_ASCII
);
754 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), tdnp
, tname
, tnmlen
);
758 error
= smb_rq_simple(rqp
);
766 smbfs_smb_move(struct smbnode
*src
, struct smbnode
*tdnp
,
767 const char *tname
, int tnmlen
, u_int16_t flags
, struct smb_cred
*scred
)
770 struct smb_share
*ssp
= src
->n_mount
->sm_share
;
774 error
= smb_rq_alloc(rqp
, SSTOCP(ssp
), SMB_COM_MOVE
, scred
, &rqp
);
777 smb_rq_getrequest(rqp
, &mbp
);
779 mb_put_uint16le(mbp
, SMB_TID_UNKNOWN
);
780 mb_put_uint16le(mbp
, 0x20); /* delete target file */
781 mb_put_uint16le(mbp
, flags
);
784 mb_put_uint8(mbp
, SMB_DT_ASCII
);
786 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), src
, NULL
, 0);
789 mb_put_uint8(mbp
, SMB_DT_ASCII
);
790 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), tdnp
, tname
, tnmlen
);
794 error
= smb_rq_simple(rqp
);
802 smbfs_smb_mkdir(struct smbnode
*dnp
, const char *name
, int len
,
803 struct smb_cred
*scred
)
806 struct smb_share
*ssp
= dnp
->n_mount
->sm_share
;
810 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_CREATE_DIRECTORY
, scred
, &rqp
);
813 smb_rq_getrequest(rqp
, &mbp
);
817 mb_put_uint8(mbp
, SMB_DT_ASCII
);
818 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), dnp
, name
, len
);
821 error
= smb_rq_simple(rqp
);
828 smbfs_smb_rmdir(struct smbnode
*np
, struct smb_cred
*scred
)
831 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
835 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_DELETE_DIRECTORY
, scred
, &rqp
);
838 smb_rq_getrequest(rqp
, &mbp
);
842 mb_put_uint8(mbp
, SMB_DT_ASCII
);
843 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), np
, NULL
, 0);
846 error
= smb_rq_simple(rqp
);
853 smbfs_smb_search(struct smbfs_fctx
*ctx
)
855 struct smb_vc
*vcp
= SSTOVC(ctx
->f_ssp
);
860 u_int16_t ec
, dlen
, bc
;
863 maxent
= min(ctx
->f_left
, (vcp
->vc_txmax
- SMB_HDRLEN
- 3) / SMB_DENTRYLEN
);
865 smb_rq_done(ctx
->f_rq
);
868 error
= smb_rq_alloc(SSTOCP(ctx
->f_ssp
), SMB_COM_SEARCH
, ctx
->f_scred
, &rqp
);
872 smb_rq_getrequest(rqp
, &mbp
);
874 mb_put_uint16le(mbp
, maxent
); /* max entries to return */
875 mb_put_uint16le(mbp
, ctx
->f_attrmask
);
878 mb_put_uint8(mbp
, SMB_DT_ASCII
); /* buffer format */
879 if (ctx
->f_flags
& SMBFS_RDD_FINDFIRST
) {
880 error
= smbfs_fullpath(mbp
, vcp
, ctx
->f_dnp
, ctx
->f_wildcard
, ctx
->f_wclen
);
883 mb_put_uint8(mbp
, SMB_DT_VARIABLE
);
884 mb_put_uint16le(mbp
, 0); /* context length */
885 ctx
->f_flags
&= ~SMBFS_RDD_FINDFIRST
;
887 mb_put_uint8(mbp
, 0); /* file name length */
888 mb_put_uint8(mbp
, SMB_DT_VARIABLE
);
889 mb_put_uint16le(mbp
, SMB_SKEYLEN
);
890 mb_put_mem(mbp
, ctx
->f_skey
, SMB_SKEYLEN
, MB_MSYSTEM
);
893 error
= smb_rq_simple(rqp
);
896 ctx
->f_flags
|= SMBFS_RDD_EOF
;
900 smb_rq_getreply(rqp
, &mdp
);
901 md_get_uint8(mdp
, &wc
);
904 md_get_uint16le(mdp
, &ec
);
908 md_get_uint16le(mdp
, &bc
);
912 md_get_uint8(mdp
, &bt
);
913 if (bt
!= SMB_DT_VARIABLE
)
915 md_get_uint16le(mdp
, &dlen
);
916 if (dlen
!= bc
|| dlen
% SMB_DENTRYLEN
!= 0)
922 smbfs_findopenLM1(struct smbfs_fctx
*ctx
, struct smbnode
*dnp
,
923 const char *wildcard
, int wclen
, int attr
, struct smb_cred
*scred
)
925 ctx
->f_attrmask
= attr
;
927 if (wclen
== 1 && wildcard
[0] == '*') {
928 ctx
->f_wildcard
= "*.*";
931 ctx
->f_wildcard
= wildcard
;
932 ctx
->f_wclen
= wclen
;
935 ctx
->f_wildcard
= NULL
;
938 ctx
->f_name
= ctx
->f_fname
;
943 smbfs_findnextLM1(struct smbfs_fctx
*ctx
, int limit
)
949 u_int16_t xdate
, xtime
;
953 if (ctx
->f_ecnt
== 0) {
954 if (ctx
->f_flags
& SMBFS_RDD_EOF
)
956 ctx
->f_left
= ctx
->f_limit
= limit
;
957 error
= smbfs_smb_search(ctx
);
962 smb_rq_getreply(rqp
, &mbp
);
963 md_get_mem(mbp
, ctx
->f_skey
, SMB_SKEYLEN
, MB_MSYSTEM
);
964 md_get_uint8(mbp
, &battr
);
965 md_get_uint16le(mbp
, &xtime
);
966 md_get_uint16le(mbp
, &xdate
);
967 md_get_uint32le(mbp
, &size
);
968 KASSERT(ctx
->f_name
== ctx
->f_fname
);
970 md_get_mem(mbp
, cp
, sizeof(ctx
->f_fname
), MB_MSYSTEM
);
971 cp
[sizeof(ctx
->f_fname
) - 1] = '\0';
972 cp
+= strlen(cp
) - 1;
973 while(*cp
== ' ' && cp
> ctx
->f_name
)
975 ctx
->f_attr
.fa_attr
= battr
;
976 smb_dos2unixtime(xdate
, xtime
, 0, rqp
->sr_vc
->vc_sopt
.sv_tz
,
977 &ctx
->f_attr
.fa_mtime
);
978 ctx
->f_attr
.fa_size
= size
;
979 ctx
->f_nmlen
= strlen(ctx
->f_name
);
986 smbfs_findcloseLM1(struct smbfs_fctx
*ctx
)
989 smb_rq_done(ctx
->f_rq
);
994 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
997 smbfs_smb_trans2find2(struct smbfs_fctx
*ctx
)
999 struct smb_t2rq
*t2p
;
1000 struct smb_vc
*vcp
= SSTOVC(ctx
->f_ssp
);
1001 struct mbchain
*mbp
;
1002 struct mdchain
*mdp
;
1003 u_int16_t tw
, flags
;
1007 smb_t2_done(ctx
->f_t2
);
1010 ctx
->f_flags
&= ~SMBFS_RDD_GOTRNAME
;
1011 flags
= 8 | 2; /* <resume> | <close if EOS> */
1012 if (ctx
->f_flags
& SMBFS_RDD_FINDSINGLE
) {
1013 flags
|= 1; /* close search after this request */
1014 ctx
->f_flags
|= SMBFS_RDD_NOCLOSE
;
1016 if (ctx
->f_flags
& SMBFS_RDD_FINDFIRST
) {
1017 error
= smb_t2_alloc(SSTOCP(ctx
->f_ssp
), SMB_TRANS2_FIND_FIRST2
,
1018 ctx
->f_scred
, &t2p
);
1022 mbp
= &t2p
->t2_tparam
;
1024 mb_put_uint16le(mbp
, ctx
->f_attrmask
);
1025 mb_put_uint16le(mbp
, ctx
->f_limit
);
1026 mb_put_uint16le(mbp
, flags
);
1027 mb_put_uint16le(mbp
, ctx
->f_infolevel
);
1028 mb_put_uint32le(mbp
, 0);
1029 error
= smbfs_fullpath(mbp
, vcp
, ctx
->f_dnp
, ctx
->f_wildcard
, ctx
->f_wclen
);
1033 error
= smb_t2_alloc(SSTOCP(ctx
->f_ssp
), SMB_TRANS2_FIND_NEXT2
,
1034 ctx
->f_scred
, &t2p
);
1038 mbp
= &t2p
->t2_tparam
;
1040 mb_put_mem(mbp
, (void *)&ctx
->f_Sid
, 2, MB_MSYSTEM
);
1041 mb_put_uint16le(mbp
, ctx
->f_limit
);
1042 mb_put_uint16le(mbp
, ctx
->f_infolevel
);
1043 mb_put_uint32le(mbp
, 0); /* resume key */
1044 mb_put_uint16le(mbp
, flags
);
1046 mb_put_mem(mbp
, ctx
->f_rname
, strlen(ctx
->f_rname
) + 1, MB_MSYSTEM
);
1048 mb_put_uint8(mbp
, 0); /* resume file name */
1052 tv
.tv_usec
= 200 * 1000; /* 200ms */
1053 if (vcp
->vc_flags
& SMBC_WIN95
) {
1055 * some implementations suggests to sleep here
1056 * for 200ms, due to the bug in the Win95.
1057 * I've didn't notice any problem, but put code
1060 tsleep(&flags
, PVFS
, "fix95", tvtohz(&tv
));
1064 t2p
->t2_maxpcount
= 5 * 2;
1065 t2p
->t2_maxdcount
= vcp
->vc_txmax
;
1066 error
= smb_t2_request(t2p
);
1069 mdp
= &t2p
->t2_rparam
;
1070 if (ctx
->f_flags
& SMBFS_RDD_FINDFIRST
) {
1071 if ((error
= md_get_uint16(mdp
, &ctx
->f_Sid
)) != 0)
1073 ctx
->f_flags
&= ~SMBFS_RDD_FINDFIRST
;
1075 if ((error
= md_get_uint16le(mdp
, &tw
)) != 0)
1078 if ((error
= md_get_uint16le(mdp
, &tw
)) != 0)
1081 ctx
->f_flags
|= SMBFS_RDD_EOF
| SMBFS_RDD_NOCLOSE
;
1082 if ((error
= md_get_uint16le(mdp
, &tw
)) != 0)
1084 if ((error
= md_get_uint16le(mdp
, &tw
)) != 0)
1086 if (ctx
->f_ecnt
== 0) {
1087 ctx
->f_flags
|= SMBFS_RDD_EOF
| SMBFS_RDD_NOCLOSE
;
1090 ctx
->f_rnameofs
= tw
;
1091 mdp
= &t2p
->t2_rdata
;
1093 KASSERT(mdp
->md_top
!= NULL
);
1094 KASSERT(mdp
->md_top
->m_len
!= 0);
1101 smbfs_smb_findclose2(struct smbfs_fctx
*ctx
)
1104 struct mbchain
*mbp
;
1107 error
= smb_rq_alloc(SSTOCP(ctx
->f_ssp
), SMB_COM_FIND_CLOSE2
, ctx
->f_scred
, &rqp
);
1110 smb_rq_getrequest(rqp
, &mbp
);
1112 mb_put_mem(mbp
, (void *)&ctx
->f_Sid
, 2, MB_MSYSTEM
);
1116 error
= smb_rq_simple(rqp
);
1122 smbfs_findopenLM2(struct smbfs_fctx
*ctx
, struct smbnode
*dnp
,
1123 const char *wildcard
, int wclen
, int attr
, struct smb_cred
*scred
)
1125 ctx
->f_name
= malloc(SMB_MAXFNAMELEN
, M_SMBFSDATA
, M_WAITOK
);
1126 if (ctx
->f_name
== NULL
)
1128 ctx
->f_infolevel
= SMB_DIALECT(SSTOVC(ctx
->f_ssp
)) < SMB_DIALECT_NTLM0_12
?
1129 SMB_INFO_STANDARD
: SMB_FIND_FILE_DIRECTORY_INFO
;
1130 ctx
->f_attrmask
= attr
;
1131 ctx
->f_wildcard
= wildcard
;
1132 ctx
->f_wclen
= wclen
;
1137 smbfs_findnextLM2(struct smbfs_fctx
*ctx
, int limit
)
1139 struct mdchain
*mbp
;
1140 struct smb_t2rq
*t2p
;
1143 u_int16_t xdate
, xtime
, wattr
;
1144 u_int32_t size
, next
, dattr
;
1146 int error
, svtz
, cnt
, fxsz
, nmlen
, recsz
;
1148 if (ctx
->f_ecnt
== 0) {
1149 if (ctx
->f_flags
& SMBFS_RDD_EOF
)
1151 ctx
->f_left
= ctx
->f_limit
= limit
;
1152 error
= smbfs_smb_trans2find2(ctx
);
1157 mbp
= &t2p
->t2_rdata
;
1158 svtz
= SSTOVC(ctx
->f_ssp
)->vc_sopt
.sv_tz
;
1159 switch (ctx
->f_infolevel
) {
1160 case SMB_INFO_STANDARD
:
1163 md_get_uint16le(mbp
, &xdate
);
1164 md_get_uint16le(mbp
, &xtime
); /* creation time */
1165 md_get_uint16le(mbp
, &xdate
);
1166 md_get_uint16le(mbp
, &xtime
); /* access time */
1167 smb_dos2unixtime(xdate
, xtime
, 0, svtz
, &ctx
->f_attr
.fa_atime
);
1168 md_get_uint16le(mbp
, &xdate
);
1169 md_get_uint16le(mbp
, &xtime
); /* access time */
1170 smb_dos2unixtime(xdate
, xtime
, 0, svtz
, &ctx
->f_attr
.fa_mtime
);
1171 md_get_uint32le(mbp
, &size
);
1172 ctx
->f_attr
.fa_size
= size
;
1173 md_get_uint32(mbp
, NULL
); /* allocation size */
1174 md_get_uint16le(mbp
, &wattr
);
1175 ctx
->f_attr
.fa_attr
= wattr
;
1176 md_get_uint8(mbp
, &tb
);
1179 recsz
= next
= 24 + nmlen
; /* docs misses zero byte at end */
1181 case SMB_FIND_FILE_DIRECTORY_INFO
:
1182 md_get_uint32le(mbp
, &next
);
1183 md_get_uint32(mbp
, NULL
); /* file index */
1184 md_get_int64(mbp
, NULL
); /* creation time */
1185 md_get_int64le(mbp
, &tmp
);
1186 smb_time_NT2local(tmp
, svtz
, &ctx
->f_attr
.fa_atime
);
1187 md_get_int64le(mbp
, &tmp
);
1188 smb_time_NT2local(tmp
, svtz
, &ctx
->f_attr
.fa_mtime
);
1189 md_get_int64le(mbp
, &tmp
);
1190 smb_time_NT2local(tmp
, svtz
, &ctx
->f_attr
.fa_ctime
);
1191 md_get_int64le(mbp
, &tmp
); /* file size */
1192 ctx
->f_attr
.fa_size
= tmp
;
1193 md_get_int64(mbp
, NULL
); /* real size (should use) */
1194 md_get_uint32le(mbp
, &dattr
); /* EA */
1195 ctx
->f_attr
.fa_attr
= dattr
;
1196 md_get_uint32le(mbp
, &size
); /* name len */
1198 recsz
= next
? next
: fxsz
+ size
;
1202 panic("smbfs_findnextLM2: unexpected info level %d\n",
1208 nmlen
= min(size
, SMB_MAXFNAMELEN
);
1210 error
= md_get_mem(mbp
, cp
, nmlen
, MB_MSYSTEM
);
1214 cnt
= next
- nmlen
- fxsz
;
1216 md_get_mem(mbp
, NULL
, cnt
, MB_MSYSTEM
);
1219 panic("smbfs_findnextLM2: out of sync");
1222 if (nmlen
&& cp
[nmlen
- 1] == 0)
1227 next
= ctx
->f_eofs
+ recsz
;
1228 if (ctx
->f_rnameofs
&& (ctx
->f_flags
& SMBFS_RDD_GOTRNAME
) == 0 &&
1229 (ctx
->f_rnameofs
>= ctx
->f_eofs
&& ctx
->f_rnameofs
< next
)) {
1231 * Server needs a resume filename.
1233 if (ctx
->f_rnamelen
<= nmlen
) {
1235 free(ctx
->f_rname
, M_SMBFSDATA
);
1236 ctx
->f_rname
= malloc(nmlen
+ 1, M_SMBFSDATA
, M_WAITOK
);
1237 ctx
->f_rnamelen
= nmlen
;
1239 memcpy(ctx
->f_rname
, ctx
->f_name
, nmlen
);
1240 ctx
->f_rname
[nmlen
] = 0;
1241 ctx
->f_flags
|= SMBFS_RDD_GOTRNAME
;
1243 ctx
->f_nmlen
= nmlen
;
1251 smbfs_findcloseLM2(struct smbfs_fctx
*ctx
)
1254 free(ctx
->f_name
, M_SMBFSDATA
);
1256 smb_t2_done(ctx
->f_t2
);
1257 if ((ctx
->f_flags
& SMBFS_RDD_NOCLOSE
) == 0)
1258 smbfs_smb_findclose2(ctx
);
1263 smbfs_findopen(struct smbnode
*dnp
, const char *wildcard
, int wclen
, int attr
,
1264 struct smb_cred
*scred
, struct smbfs_fctx
**ctxpp
)
1266 struct smbfs_fctx
*ctx
;
1269 ctx
= malloc(sizeof(*ctx
), M_SMBFSDATA
, M_WAITOK
|M_ZERO
);
1270 ctx
->f_ssp
= dnp
->n_mount
->sm_share
;
1272 ctx
->f_flags
= SMBFS_RDD_FINDFIRST
;
1273 ctx
->f_scred
= scred
;
1274 if (SMB_DIALECT(SSTOVC(ctx
->f_ssp
)) < SMB_DIALECT_LANMAN2_0
||
1275 (dnp
->n_mount
->sm_args
.flags
& SMBFS_MOUNT_NO_LONG
)) {
1276 ctx
->f_flags
|= SMBFS_RDD_USESEARCH
;
1277 error
= smbfs_findopenLM1(ctx
, dnp
, wildcard
, wclen
, attr
, scred
);
1279 error
= smbfs_findopenLM2(ctx
, dnp
, wildcard
, wclen
, attr
, scred
);
1281 smbfs_findclose(ctx
, scred
);
1288 smbfs_findnext(struct smbfs_fctx
*ctx
, int limit
, struct smb_cred
*scred
)
1295 limit
*= 4; /* empirical */
1296 ctx
->f_scred
= scred
;
1298 if (ctx
->f_flags
& SMBFS_RDD_USESEARCH
) {
1299 error
= smbfs_findnextLM1(ctx
, limit
);
1301 error
= smbfs_findnextLM2(ctx
, limit
);
1305 /* Skip '.' and '..' */
1306 if ((ctx
->f_nmlen
== 1 && ctx
->f_name
[0] == '.') ||
1307 (ctx
->f_nmlen
== 2 && ctx
->f_name
[0] == '.' &&
1308 ctx
->f_name
[1] == '.'))
1312 smbfs_fname_tolocal(SSTOVC(ctx
->f_ssp
), ctx
->f_name
, ctx
->f_nmlen
,
1313 ctx
->f_dnp
->n_mount
->sm_caseopt
);
1314 ctx
->f_attr
.fa_ino
= smbfs_getino(ctx
->f_dnp
, ctx
->f_name
, ctx
->f_nmlen
);
1319 smbfs_findclose(struct smbfs_fctx
*ctx
, struct smb_cred
*scred
)
1321 ctx
->f_scred
= scred
;
1322 if (ctx
->f_flags
& SMBFS_RDD_USESEARCH
) {
1323 smbfs_findcloseLM1(ctx
);
1325 smbfs_findcloseLM2(ctx
);
1327 free(ctx
->f_rname
, M_SMBFSDATA
);
1328 free(ctx
, M_SMBFSDATA
);
1333 smbfs_smb_lookup(struct smbnode
*dnp
, const char *name
, int nmlen
,
1334 struct smbfattr
*fap
, struct smb_cred
*scred
)
1336 struct smbfs_fctx
*ctx
;
1339 if (dnp
== NULL
|| (dnp
->n_ino
== 2 && name
== NULL
)) {
1340 memset(fap
, 0, sizeof(*fap
));
1341 fap
->fa_attr
= SMB_FA_DIR
;
1345 if (nmlen
== 1 && name
[0] == '.') {
1346 error
= smbfs_smb_lookup(dnp
, NULL
, 0, fap
, scred
);
1348 } else if (nmlen
== 2 && name
[0] == '.' && name
[1] == '.') {
1349 error
= smbfs_smb_lookup(VTOSMB(dnp
->n_parent
), NULL
, 0,
1351 printf("%s: knows NOTHING about '..'\n", __func__
);
1354 error
= smbfs_findopen(dnp
, name
, nmlen
,
1355 SMB_FA_SYSTEM
| SMB_FA_HIDDEN
| SMB_FA_DIR
, scred
, &ctx
);
1358 ctx
->f_flags
|= SMBFS_RDD_FINDSINGLE
;
1359 error
= smbfs_findnext(ctx
, 1, scred
);
1363 fap
->fa_ino
= dnp
->n_ino
;
1366 * Check the returned file name case exactly
1367 * matches requested file name. ctx->f_nmlen is
1368 * guaranteed to always match nmlen.
1370 if (nmlen
> 0 && strncmp(name
, ctx
->f_name
, nmlen
) != 0)
1373 smbfs_findclose(ctx
, scred
);
1378 * This call is used to fetch FID for directories. For normal files,
1379 * SMB_COM_OPEN is used.
1382 smbfs_smb_ntcreatex(struct smbnode
*np
, int accmode
,
1383 struct smb_cred
*scred
)
1386 struct smb_share
*ssp
= np
->n_mount
->sm_share
;
1387 struct mbchain
*mbp
;
1388 struct mdchain
*mdp
;
1394 KASSERT(SMBTOV(np
)->v_type
== VDIR
);
1396 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_NT_CREATE_ANDX
, scred
, &rqp
);
1399 smb_rq_getrequest(rqp
, &mbp
);
1401 mb_put_uint8(mbp
, 0xff); /* Secondary command; 0xFF = None */
1402 mb_put_uint8(mbp
, 0); /* Reserved (must be 0) */
1403 mb_put_uint16le(mbp
, 0); /* Off to next cmd WordCount */
1404 mb_put_uint8(mbp
, 0); /* Reserved (must be 0) */
1405 nmlen
= mb_reserve(mbp
, sizeof(u_int16_t
));
1406 /* Length of Name[] in bytes */
1407 mb_put_uint32le(mbp
, SMB_FL_CANONICAL_PATHNAMES
);
1408 /* Flags - Create bit set */
1409 mb_put_uint32le(mbp
, 0); /* If nonzero, open relative to this */
1410 mb_put_uint32le(mbp
, NT_FILE_LIST_DIRECTORY
); /* Access mask */
1411 mb_put_uint32le(mbp
, 0); /* Low 32bit */
1412 mb_put_uint32le(mbp
, 0); /* Hi 32bit */
1413 /* Initial allocation size */
1414 mb_put_uint32le(mbp
, 0); /* File attributes */
1415 mb_put_uint32le(mbp
, NT_FILE_SHARE_READ
|NT_FILE_SHARE_WRITE
);
1416 /* Type of share access */
1417 mb_put_uint32le(mbp
, NT_OPEN_EXISTING
);
1418 /* Create disposition - just open */
1419 mb_put_uint32le(mbp
, NT_FILE_DIRECTORY_FILE
);
1420 /* Options to use if creating a file */
1421 mb_put_uint32le(mbp
, 0); /* Security QOS information */
1422 mb_put_uint8(mbp
, 0); /* Security tracking mode flags */
1428 error
= smbfs_fullpath(mbp
, SSTOVC(ssp
), np
, NULL
, 0);
1432 /* Windows XP seems to include the final zero. Better do that too. */
1433 mb_put_uint8(mbp
, 0);
1435 flen
= mbp
->mb_count
;
1436 SMBRQ_PUTLE16(nmlen
, flen
);
1438 error
= smb_rq_simple(rqp
);
1442 smb_rq_getreply(rqp
, &mdp
);
1443 md_get_uint8(mdp
, &wc
); /* WordCount - check? */
1444 md_get_uint8(mdp
, NULL
); /* AndXCommand */
1445 md_get_uint8(mdp
, NULL
); /* Reserved - must be zero */
1446 md_get_uint16(mdp
, NULL
); /* Offset to next cmd WordCount */
1447 md_get_uint8(mdp
, NULL
); /* Oplock level granted */
1448 md_get_uint16(mdp
, &np
->n_fid
); /* FID */
1457 * Setup a request for NT DIRECTORY CHANGE NOTIFY.
1460 smbfs_smb_nt_dirnotify_setup(struct smbnode
*dnp
, struct smb_rq
**rqpp
, struct smb_cred
*scred
, void (*notifyhook
)(void *), void *notifyarg
)
1463 struct smb_share
*ssp
= dnp
->n_mount
->sm_share
;
1464 struct mbchain
*mbp
;
1467 error
= smb_rq_alloc(SSTOCP(ssp
), SMB_COM_NT_TRANSACT
, scred
, &rqp
);
1470 smb_rq_getrequest(rqp
, &mbp
);
1472 mb_put_uint8(mbp
, 0xff); /* Max setup words to return */
1473 mb_put_uint16le(mbp
, 0); /* Flags (according to Samba) */
1474 mb_put_uint32le(mbp
, 0); /* Total parameter bytes being sent*/
1475 mb_put_uint32le(mbp
, 0); /* Total data bytes being sent */
1476 mb_put_uint32le(mbp
, 10*1024); /* Max parameter bytes to return */
1477 mb_put_uint32le(mbp
, 0); /* Max data bytes to return */
1478 mb_put_uint32le(mbp
, 0); /* Parameter bytes sent this buffer */
1479 mb_put_uint32le(mbp
, 0); /* Offset (from h. start) to Param */
1480 mb_put_uint32le(mbp
, 0); /* Data bytes sent this buffer */
1481 mb_put_uint32le(mbp
, 0); /* Offset (from h. start) to Data */
1482 mb_put_uint8(mbp
, 4); /* Count of setup words */
1483 mb_put_uint16le(mbp
, SMB_NTTRANS_NOTIFY_CHANGE
); /* Trans func code */
1485 /* NT TRANSACT NOTIFY CHANGE: Request Change Notification */
1486 mb_put_uint32le(mbp
,
1487 FILE_NOTIFY_CHANGE_NAME
|FILE_NOTIFY_CHANGE_ATTRIBUTES
|
1488 FILE_NOTIFY_CHANGE_SIZE
|FILE_NOTIFY_CHANGE_LAST_WRITE
|
1489 FILE_NOTIFY_CHANGE_CREATION
); /* CompletionFilter */
1490 mb_put_mem(mbp
, (void *)&dnp
->n_fid
, 2, MB_MSYSTEM
); /* FID */
1491 mb_put_uint8(mbp
, 0); /* WatchTree - Watch all subdirs too */
1492 mb_put_uint8(mbp
, 0); /* Reserved - must be zero */
1499 smb_rq_setcallback(rqp
, notifyhook
, notifyarg
);
1501 error
= smb_rq_enqueue(rqp
);
1511 smbfs_smb_nt_dirnotify_fetch(struct smb_rq
*rqp
, int *hint
)
1514 struct mdchain
*mdp
;
1516 u_int32_t nextentry
;
1518 error
= smb_rq_reply(rqp
);
1521 * If we get EMSGSIZE, there is already too many notifications
1522 * available for the directory, and the internal buffer
1523 * overflew. Just flag any possible relevant change.
1525 if (error
== EMSGSIZE
) {
1526 *hint
= NOTE_ATTRIB
| NOTE_WRITE
;
1533 smb_rq_getreply(rqp
, &mdp
);
1536 error
= md_get_mem(mdp
, NULL
, 4 + (8*4), MB_MZERO
); /* skip */
1540 md_get_uint8(mdp
, &sc
); /* SetupCount */
1542 md_get_mem(mdp
, NULL
, sc
* sizeof(u_int16_t
), MB_MZERO
);
1543 md_get_uint16(mdp
, NULL
); /* ByteCount */
1544 md_get_mem(mdp
, NULL
, 1 + (sc
% 2) * 2, MB_MZERO
); /* Pad */
1547 * The notify data are blocks of
1548 * ULONG nextentry - offset of next entry from start of this one
1549 * ULONG action - type of notification
1550 * ULONG filenamelen - length of filename in bytes
1551 * WCHAR filename[filenamelen/2] - Unicode filename
1552 * nexentry == 0 means last notification, filename is in 16bit LE
1563 md_get_uint32le(mdp
, &nextentry
);
1564 md_get_uint32le(mdp
, &action
);
1566 md_get_mem(mdp
, NULL
, nextentry
- 2 * 4, MB_MZERO
);
1568 md_get_uint32le(mdp
, &fnlen
);
1570 printf("notify: next %u act %u fnlen %u fname '",
1571 nextentry
, action
, fnlen
);
1572 for(; fnlen
> 0; fnlen
-= 2) {
1573 md_get_uint16le(mdp
, &fnc
);
1574 printf("%c", fnc
&0xff);
1580 case FILE_ACTION_ADDED
:
1581 case FILE_ACTION_REMOVED
:
1582 case FILE_ACTION_RENAMED_OLD_NAME
:
1583 case FILE_ACTION_RENAMED_NEW_NAME
:
1584 *hint
|= NOTE_ATTRIB
| NOTE_WRITE
;
1587 case FILE_ACTION_MODIFIED
:
1588 *hint
|= NOTE_ATTRIB
;
1591 } while(nextentry
> 0);
1599 * Cancel previous SMB, with message ID mid. No reply is generated
1600 * to this one (only the previous message returns with error).
1603 smbfs_smb_ntcancel(struct smb_connobj
*layer
, u_int16_t mid
, struct smb_cred
*scred
)
1606 struct mbchain
*mbp
;
1611 error
= smb_rq_alloc(layer
, SMB_COM_NT_CANCEL
, scred
, &rqp
);
1614 rqp
->sr_flags
|= SMBR_NOWAIT
; /* do not wait for reply */
1615 smb_rq_getrequest(rqp
, &mbp
);
1618 * This is nonstandard. We need to rewrite the just written
1619 * mid to different one. Access underlying mbuf directly.
1620 * We assume mid is the last thing written smb_rq_alloc()
1621 * to request buffer.
1624 mp
= mtod(m
, u_int8_t
*) + m
->m_len
- 2;
1625 SMBRQ_PUTLE16(mp
, mid
);
1633 error
= (smb_rq_simple(rqp
));
1635 /* Discard, there is no real reply */