1 Index: source/smbd/nttrans.c
2 ===================================================================
3 --- source/smbd/nttrans.c (revision 1473)
4 +++ source/smbd/nttrans.c (working copy)
6 * Check to see if this is a mac fork of some kind.
9 - if( strchr_m(fname, ':')) {
10 - END_PROFILE(SMBntcreateX);
11 - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
14 + if( !strchr_m(fname, ':')) {
15 + /* it's not an alternate stream */
16 + END_PROFILE(SMBntcreateX);
17 + return(ERROR_DOS(ERRDOS,ERRbadfid));
19 + else if (-1 == SMB_VFS_LISTADS(conn, NULL, NULL, 0)) {
20 + /* fs have no support for alternate streams */
21 + END_PROFILE(SMBntcreateX);
22 + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
25 we need to handle the case when we get a
26 relative open relative to a file and the
28 (hint from demyn plantenberg)
31 - END_PROFILE(SMBntcreateX);
32 - return(ERROR_DOS(ERRDOS,ERRbadfid));
34 + * Copy in the base name.
36 + pstrcpy( fname, dir_fsp->fsp_name );
37 + dir_name_len = strlen(fname);
39 + else { /* it's a dir */
41 + * Copy in the base directory name.
45 - * Copy in the base directory name.
47 + pstrcpy( fname, dir_fsp->fsp_name );
48 + dir_name_len = strlen(fname);
50 - pstrcpy( fname, dir_fsp->fsp_name );
51 - dir_name_len = strlen(fname);
53 + * Ensure it ends in a '\'.
57 - * Ensure it ends in a '\'.
60 - if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
61 - pstrcat(fname, "/");
65 + if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
66 + pstrcat(fname, "/");
70 srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False);
71 if (!NT_STATUS_IS_OK(status)) {
72 END_PROFILE(SMBntcreateX);
75 * Check to see if this is a mac fork of some kind.
78 if( strchr_m(fname, ':')) {
80 #ifdef HAVE_SYS_QUOTAS
85 - END_PROFILE(SMBntcreateX);
86 - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
87 + if (-1 == SMB_VFS_LISTADS(conn, NULL, NULL, 0)) {
88 + END_PROFILE(SMBntcreateX);
89 + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
92 #ifdef HAVE_SYS_QUOTAS
95 @@ -1235,12 +1245,10 @@
99 - * Check to see if this is a mac fork of some kind.
100 + * Check to see if this is a mac fork of some kind. FIXME
103 - if( strchr_m(fname, ':'))
104 + if( strchr_m(fname, ':') && -1 == SMB_VFS_LISTADS(conn, NULL, NULL, 0))
105 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
107 return ERROR_DOS(ERRDOS,ERRbadfid);
110 @@ -1278,7 +1286,7 @@
111 * Check to see if this is a mac fork of some kind.
114 - if( strchr_m(fname, ':'))
115 + if( strchr_m(fname, ':') && -1 == SMB_VFS_LISTADS(conn, NULL, NULL, 0))
116 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
119 Index: source/smbd/vfs.c
120 ===================================================================
121 --- source/smbd/vfs.c (revision 1473)
122 +++ source/smbd/vfs.c (working copy)
124 vfswrap_fremovexattr,
130 + /* alternate streams operations. */
135 Index: source/smbd/vfs-wrap.c
136 ===================================================================
137 --- source/smbd/vfs-wrap.c (revision 1473)
138 +++ source/smbd/vfs-wrap.c (working copy)
139 @@ -1029,3 +1029,14 @@
141 return sys_fsetxattr(fd, name, value, size, flags);
144 +/****************************************************************
145 + Alternate stream operations.
146 +*****************************************************************/
148 +ssize_t vfswrap_listads(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
154 Index: source/smbd/trans2.c
155 ===================================================================
156 --- source/smbd/trans2.c (revision 1473)
157 +++ source/smbd/trans2.c (working copy)
158 @@ -406,6 +406,159 @@
161 /****************************************************************************
162 + ****************************************************************************
163 + Return a linked list of the alternate streams Plus the total size
164 +****************************************************************************/
166 + struct ads_list *next, *prev;
167 + struct ads_struct ads;
170 +static struct ads_list *get_ads_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pads_total_len)
172 + /* Get a list of all ads with size, lax namesize is 64k. */
173 + size_t ads_namelist_size = 4096;
174 + char *ads_namelist;
178 + struct ads_list *ads_list_head = NULL;
180 + *pads_total_len = 0;
182 + DEBUG(10,("get_ads_list\n" ));
184 + for (i = 0, ads_namelist = talloc(mem_ctx, ads_namelist_size); i < 6;
185 + ads_namelist = talloc_realloc(mem_ctx, ads_namelist, ads_namelist_size), i++) {
187 + sizeret = SMB_VFS_LISTADS(conn, fname, ads_namelist, ads_namelist_size);
188 + if (sizeret == -1 && errno == ERANGE) {
189 + ads_namelist_size *= 2;
198 + DEBUG(10,("get_ads_list: ads_namelist size = %d\n", sizeret ));
201 + for (p = ads_namelist; p - ads_namelist < sizeret; p += strlen(p) +1) {
202 + struct ads_list *listp, *tmp;
203 + SMB_STRUCT_STAT sbuf;
206 + listp = talloc(mem_ctx, sizeof(struct ads_list));
210 + listp->ads.name = talloc_strdup(mem_ctx, p);
211 + if (!listp->ads.name)
214 + listp->ads.size = 0;
215 + listp->ads.allocation_size = 0;
217 + t = talloc_asprintf(mem_ctx, "%s%s", fname, p);
220 + if (!SMB_VFS_STAT(conn, t ,&sbuf)) {
221 + listp->ads.size = get_file_size(sbuf);
222 + listp->ads.allocation_size = get_allocation_size(NULL,&sbuf);
224 + /* FIXME get ride of this */
226 + fstring dos_ads_name;
228 + push_ascii_fstring(dos_ads_name, listp->ads.name);
229 + *pads_total_len += strlen(dos_ads_name) + 1 + 24;
230 + DEBUG(10,("get_ads_list: total_len = %u, %s, size = %llu\n",
231 + *pads_total_len, dos_ads_name, listp->ads.size ));
233 + DLIST_ADD_END(ads_list_head, listp, tmp);
237 + DEBUG(10,("get_ads_list: total_len = %u\n", *pads_total_len));
238 + return ads_list_head;
241 +/****************************************************************************
242 + Fill a qfilepathinfo buffer with alternate streams.
243 + Returns the length of the buffer that was filled.
244 +****************************************************************************/
246 +static unsigned int fill_ads_buffer(char *pdata, unsigned int total_data_size,
247 + connection_struct *conn, files_struct *fsp, const char *fname)
249 + unsigned int ret_data_size = 0;
251 + size_t total_ads_len;
252 + TALLOC_CTX *mem_ctx;
253 + struct ads_list *ads_list;
255 + SMB_ASSERT(total_data_size >= 24);
257 + mem_ctx = talloc_init("fill_ads_buffer");
262 + ads_list = get_ads_list(mem_ctx, conn, fsp, fname, &total_ads_len);
264 + talloc_destroy(mem_ctx);
268 + if (total_ads_len > total_data_size) {
269 + talloc_destroy(mem_ctx);
273 + for (p = pdata; ads_list; ads_list = ads_list->next) {
275 + size_t dos_namelen;
276 + fstring dos_ads_name;
278 + push_ascii_fstring(dos_ads_name, ads_list->ads.name);
279 + dos_namelen = strlen(dos_ads_name);
280 + if (dos_namelen > 255 || dos_namelen == 0) {
283 + if (dos_namelen + 24 > total_data_size) {
287 + /* We know we have room. */
288 + size_t byte_len = dos_PutUniCode(p +24, ads_list->ads.name, -1, False);
289 + size_t off = SMB_ROUNDUP(24 +byte_len, 8);
291 + SIVAL(p,0,0); /* from ethereal next entry offset */
292 + SIVAL(p,4, byte_len); /* Byte length of unicode string :filename:$DATA */
293 + SOFF_T(p,8, ads_list->ads.size);
294 + SOFF_T(p,16, ads_list->ads.allocation_size);
295 + if (ads_list->next) {
299 + /* don't pad the last one */
300 + off = 24 +byte_len;
303 + total_data_size -= off;
307 + ret_data_size = PTR_DIFF(p, pdata);
308 + DEBUG(10,("fill_ads_buffer: data_size = %u, total_ads_len = %u\n",
309 + ret_data_size, total_ads_len ));
310 + talloc_destroy(mem_ctx);
311 + return ret_data_size;
314 +/****************************************************************************
315 Send the required number of replies back.
316 We assume all fields other than the data fields are
317 set correctly for the type of call.
318 @@ -2653,7 +2806,7 @@
325 * NT4 server just returns "invalid query" to this - if we try to answer
326 * it then NTws gets a BSOD! (tridge).
327 @@ -2663,16 +2816,24 @@
329 case SMB_FILE_STREAM_INFORMATION:
330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
334 - size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
335 - SIVAL(pdata,0,0); /* ??? */
336 - SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
337 - SOFF_T(pdata,8,file_size);
338 - SIVAL(pdata,16,allocation_size);
339 - SIVAL(pdata,20,0); /* ??? */
340 - data_size = 24 + byte_len;
347 + size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
349 + off = SMB_ROUNDUP(24 +byte_len, 8); /* FIXME or 8 ? */
350 + SIVAL(pdata,0,0); /* from ethereal next entry offset */
351 + SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
352 + SOFF_T(pdata,8,file_size);
353 + SOFF_T(pdata,16,allocation_size);
355 + if ((data_size = fill_ads_buffer(pdata +off, data_size, conn, fsp, fname))) {
356 + SIVAL(pdata,0,off);
362 Index: source/include/vfs_macros.h
363 ===================================================================
364 --- source/include/vfs_macros.h (revision 1473)
365 +++ source/include/vfs_macros.h (working copy)
367 #define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
368 #define SMB_VFS_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs.ops.fsetxattr((fsp)->conn->vfs.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
370 +/* ADS operations. */
371 +#define SMB_VFS_LISTADS(conn,path,list,size) ((conn)->vfs.ops.listads((conn)->vfs.handles.listads,(conn),(path),(list),(size)))
373 /*******************************************************************
374 Don't access conn->vfs_opaque.ops directly!!!
377 #define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
378 #define SMB_VFS_OPAQUE_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs_opaque.ops.fsetxattr((fsp)->conn->vfs_opaque.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
380 +/* ADS operations. */
381 +#define SMB_VFS_OPAQUE_LISTADS(conn,path,list,size) ((conn)->vfs_opaque.ops.listads((conn)->vfs_opaque.handles.listads,(conn),(path),(list),(size)))
383 /*******************************************************************
384 Don't access handle->vfs_next.ops.* directly!!!
387 #define SMB_VFS_NEXT_LSETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
388 #define SMB_VFS_NEXT_FSETXATTR(handle,fsp,fd,name,value,size,flags) ((handle)->vfs_next.ops.fsetxattr((handle)->vfs_next.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
390 +/* ADS operations. */
391 +#define SMB_VFS_NEXT_LISTADS(handle,conn,path,list,size) ((handle)->vfs_next.ops.listads((handle)->vfs_next.handles.listads,(conn),(path),(list),(size)))
393 #endif /* _VFS_MACROS_H */
394 Index: source/include/vfs.h
395 ===================================================================
396 --- source/include/vfs.h (revision 1473)
397 +++ source/include/vfs.h (working copy)
399 /* Changed to version 8 includes EA calls. JRA. */
400 /* Changed to version 9 to include the get_shadow_data call. --metze */
401 /* Changed to version 10 to include pread/pwrite calls. */
402 -#define SMB_VFS_INTERFACE_VERSION 10
403 +/* Changed to version 11 to include alternate data streams. */
404 +#define SMB_VFS_INTERFACE_VERSION 11
407 /* to bug old modules witch are trying to compile with the old functions */
410 SMB_VFS_OP_LSETXATTR,
411 SMB_VFS_OP_FSETXATTR,
413 + /* alternate stream */
414 + SMB_VFS_OP_LISTADS,
416 /* This should always be last enum value */
419 int (*lsetxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags);
420 int (*fsetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name, const void *value, size_t size, int flags);
422 + /* alternate stream operations. */
423 + ssize_t (*listads)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size);
427 struct vfs_handles_pointers {
429 struct vfs_handle_struct *lsetxattr;
430 struct vfs_handle_struct *fsetxattr;
432 + /* alternate stream operations. */
433 + struct vfs_handle_struct *listads;
437 Index: source/include/smb.h
438 ===================================================================
439 --- source/include/smb.h (revision 1473)
440 +++ source/include/smb.h (working copy)
441 @@ -1703,6 +1703,12 @@
447 + SMB_BIG_UINT allocation_size;
451 /* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
452 #define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
453 /* EA to use for DOS attributes */