root/source3/smbd/trans2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smb_roundup
  2. samba_private_attr_name
  3. get_ea_value
  4. get_ea_names_from_file
  5. get_ea_list_from_file
  6. fill_ea_buffer
  7. estimate_ea_size
  8. canonicalize_ea_name
  9. set_ea
  10. read_ea_name_list
  11. read_ea_list_entry
  12. read_ea_list
  13. ea_list_size
  14. ea_list_union
  15. send_trans2_replies
  16. call_trans2open
  17. exact_match
  18. unix_filetype
  19. unix_perms_from_wire
  20. check_msdfs_link
  21. get_lanman2_dir_entry
  22. call_trans2findfirst
  23. call_trans2findnext
  24. create_volume_objectid
  25. samba_extended_info_version
  26. call_trans2qfsinfo
  27. call_trans2setfsinfo
  28. count_acl_entries
  29. marshall_posix_acl
  30. store_file_unix_basic
  31. map_info2_flags_from_sbuf
  32. map_info2_flags_to_sbuf
  33. store_file_unix_basic_info2
  34. marshall_stream_info
  35. call_trans2qpipeinfo
  36. call_trans2qfilepathinfo
  37. hardlink_internals
  38. smb_set_file_time
  39. smb_set_file_dosmode
  40. smb_set_file_size
  41. smb_info_set_ea
  42. smb_set_file_disposition_info
  43. smb_file_position_information
  44. smb_file_mode_information
  45. smb_set_file_unix_link
  46. smb_set_file_unix_hlink
  47. smb_file_rename_information
  48. smb_set_posix_acl
  49. smb_set_posix_lock
  50. smb_set_info_standard
  51. smb_set_file_basic_info
  52. smb_set_file_allocation_info
  53. smb_set_file_end_of_file_info
  54. smb_unix_mknod
  55. smb_set_file_unix_basic
  56. smb_set_file_unix_info2
  57. smb_posix_mkdir
  58. smb_posix_open
  59. smb_posix_unlink
  60. call_trans2setfilepathinfo
  61. call_trans2mkdir
  62. call_trans2findnotifyfirst
  63. call_trans2findnotifynext
  64. call_trans2getdfsreferral
  65. call_trans2ioctl
  66. reply_findclose
  67. reply_findnclose
  68. handle_trans2
  69. reply_trans2
  70. reply_transs2

   1 /*
   2    Unix SMB/CIFS implementation.
   3    SMB transaction2 handling
   4    Copyright (C) Jeremy Allison                 1994-2007
   5    Copyright (C) Stefan (metze) Metzmacher      2003
   6    Copyright (C) Volker Lendecke                2005-2007
   7    Copyright (C) Steve French                   2005
   8    Copyright (C) James Peach                    2006-2007
   9 
  10    Extensively modified by Andrew Tridgell, 1995
  11 
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 3 of the License, or
  15    (at your option) any later version.
  16 
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24 */
  25 
  26 #include "includes.h"
  27 #include "version.h"
  28 #include "smbd/globals.h"
  29 
  30 extern enum protocol_types Protocol;
  31 
  32 #define DIR_ENTRY_SAFETY_MARGIN 4096
  33 
  34 static char *store_file_unix_basic(connection_struct *conn,
  35                                 char *pdata,
  36                                 files_struct *fsp,
  37                                 const SMB_STRUCT_STAT *psbuf);
  38 
  39 static char *store_file_unix_basic_info2(connection_struct *conn,
  40                                 char *pdata,
  41                                 files_struct *fsp,
  42                                 const SMB_STRUCT_STAT *psbuf);
  43 
  44 /********************************************************************
  45  Roundup a value to the nearest allocation roundup size boundary.
  46  Only do this for Windows clients.
  47 ********************************************************************/
  48 
  49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
  52 
  53         /* Only roundup for Windows clients. */
  54         enum remote_arch_types ra_type = get_remote_arch();
  55         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
  56                 val = SMB_ROUNDUP(val,rval);
  57         }
  58         return val;
  59 }
  60 
  61 /****************************************************************************
  62  Utility functions for dealing with extended attributes.
  63 ****************************************************************************/
  64 
  65 /****************************************************************************
  66  Refuse to allow clients to overwrite our private xattrs.
  67 ****************************************************************************/
  68 
  69 static bool samba_private_attr_name(const char *unix_ea_name)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71         static const char * const prohibited_ea_names[] = {
  72                 SAMBA_POSIX_INHERITANCE_EA_NAME,
  73                 SAMBA_XATTR_DOS_ATTRIB,
  74                 NULL
  75         };
  76 
  77         int i;
  78 
  79         for (i = 0; prohibited_ea_names[i]; i++) {
  80                 if (strequal( prohibited_ea_names[i], unix_ea_name))
  81                         return true;
  82         }
  83         if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
  84                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
  85                 return true;
  86         }
  87         return false;
  88 }
  89 
  90 /****************************************************************************
  91  Get one EA value. Fill in a struct ea_struct.
  92 ****************************************************************************/
  93 
  94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
  95                       files_struct *fsp, const char *fname,
  96                       const char *ea_name, struct ea_struct *pea)
  97 {
  98         /* Get the value of this xattr. Max size is 64k. */
  99         size_t attr_size = 256;
 100         char *val = NULL;
 101         ssize_t sizeret;
 102 
 103  again:
 104 
 105         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
 106         if (!val) {
 107                 return NT_STATUS_NO_MEMORY;
 108         }
 109 
 110         if (fsp && fsp->fh->fd != -1) {
 111                 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
 112         } else {
 113                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
 114         }
 115 
 116         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
 117                 attr_size = 65536;
 118                 goto again;
 119         }
 120 
 121         if (sizeret == -1) {
 122                 return map_nt_error_from_unix(errno);
 123         }
 124 
 125         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
 126         dump_data(10, (uint8 *)val, sizeret);
 127 
 128         pea->flags = 0;
 129         if (strnequal(ea_name, "user.", 5)) {
 130                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
 131         } else {
 132                 pea->name = talloc_strdup(mem_ctx, ea_name);
 133         }
 134         if (pea->name == NULL) {
 135                 TALLOC_FREE(val);
 136                 return NT_STATUS_NO_MEMORY;
 137         }
 138         pea->value.data = (unsigned char *)val;
 139         pea->value.length = (size_t)sizeret;
 140         return NT_STATUS_OK;
 141 }
 142 
 143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 144                                 files_struct *fsp, const char *fname,
 145                                 char ***pnames, size_t *pnum_names)
 146 {
 147         /* Get a list of all xattrs. Max namesize is 64k. */
 148         size_t ea_namelist_size = 1024;
 149         char *ea_namelist = NULL;
 150 
 151         char *p;
 152         char **names, **tmp;
 153         size_t num_names;
 154         ssize_t sizeret = -1;
 155 
 156         if (!lp_ea_support(SNUM(conn))) {
 157                 *pnames = NULL;
 158                 *pnum_names = 0;
 159                 return NT_STATUS_OK;
 160         }
 161 
 162         /*
 163          * TALLOC the result early to get the talloc hierarchy right.
 164          */
 165 
 166         names = TALLOC_ARRAY(mem_ctx, char *, 1);
 167         if (names == NULL) {
 168                 DEBUG(0, ("talloc failed\n"));
 169                 return NT_STATUS_NO_MEMORY;
 170         }
 171 
 172         while (ea_namelist_size <= 65536) {
 173 
 174                 ea_namelist = TALLOC_REALLOC_ARRAY(
 175                         names, ea_namelist, char, ea_namelist_size);
 176                 if (ea_namelist == NULL) {
 177                         DEBUG(0, ("talloc failed\n"));
 178                         TALLOC_FREE(names);
 179                         return NT_STATUS_NO_MEMORY;
 180                 }
 181 
 182                 if (fsp && fsp->fh->fd != -1) {
 183                         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
 184                                                      ea_namelist_size);
 185                 } else {
 186                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
 187                                                     ea_namelist_size);
 188                 }
 189 
 190                 if ((sizeret == -1) && (errno == ERANGE)) {
 191                         ea_namelist_size *= 2;
 192                 }
 193                 else {
 194                         break;
 195                 }
 196         }
 197 
 198         if (sizeret == -1) {
 199                 TALLOC_FREE(names);
 200                 return map_nt_error_from_unix(errno);
 201         }
 202 
 203         DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
 204                    (unsigned int)sizeret));
 205 
 206         if (sizeret == 0) {
 207                 TALLOC_FREE(names);
 208                 *pnames = NULL;
 209                 *pnum_names = 0;
 210                 return NT_STATUS_OK;
 211         }
 212 
 213         /*
 214          * Ensure the result is 0-terminated
 215          */
 216 
 217         if (ea_namelist[sizeret-1] != '\0') {
 218                 TALLOC_FREE(names);
 219                 return NT_STATUS_INTERNAL_ERROR;
 220         }
 221 
 222         /*
 223          * count the names
 224          */
 225         num_names = 0;
 226 
 227         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
 228                 num_names += 1;
 229         }
 230 
 231         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
 232         if (tmp == NULL) {
 233                 DEBUG(0, ("talloc failed\n"));
 234                 TALLOC_FREE(names);
 235                 return NT_STATUS_NO_MEMORY;
 236         }
 237 
 238         names = tmp;
 239         num_names = 0;
 240 
 241         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
 242                 names[num_names++] = p;
 243         }
 244 
 245         *pnames = names;
 246         *pnum_names = num_names;
 247         return NT_STATUS_OK;
 248 }
 249 
 250 /****************************************************************************
 251  Return a linked list of the total EA's. Plus the total size
 252 ****************************************************************************/
 253 
 254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
     /* [<][>][^][v][top][bottom][index][help] */
 255                                         const char *fname, size_t *pea_total_len)
 256 {
 257         /* Get a list of all xattrs. Max namesize is 64k. */
 258         size_t i, num_names;
 259         char **names;
 260         struct ea_list *ea_list_head = NULL;
 261         NTSTATUS status;
 262 
 263         *pea_total_len = 0;
 264 
 265         if (!lp_ea_support(SNUM(conn))) {
 266                 return NULL;
 267         }
 268 
 269         status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
 270                                         &names, &num_names);
 271 
 272         if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
 273                 return NULL;
 274         }
 275 
 276         for (i=0; i<num_names; i++) {
 277                 struct ea_list *listp;
 278                 fstring dos_ea_name;
 279 
 280                 if (strnequal(names[i], "system.", 7)
 281                     || samba_private_attr_name(names[i]))
 282                         continue;
 283 
 284                 listp = TALLOC_P(mem_ctx, struct ea_list);
 285                 if (listp == NULL) {
 286                         return NULL;
 287                 }
 288 
 289                 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
 290                                                   fname, names[i],
 291                                                   &listp->ea))) {
 292                         return NULL;
 293                 }
 294 
 295                 push_ascii_fstring(dos_ea_name, listp->ea.name);
 296 
 297                 *pea_total_len +=
 298                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
 299 
 300                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
 301                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
 302                           (unsigned int)listp->ea.value.length));
 303 
 304                 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
 305 
 306         }
 307 
 308         /* Add on 4 for total length. */
 309         if (*pea_total_len) {
 310                 *pea_total_len += 4;
 311         }
 312 
 313         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
 314                    (unsigned int)*pea_total_len));
 315 
 316         return ea_list_head;
 317 }
 318 
 319 /****************************************************************************
 320  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
 321  that was filled.
 322 ****************************************************************************/
 323 
 324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
     /* [<][>][^][v][top][bottom][index][help] */
 325         connection_struct *conn, struct ea_list *ea_list)
 326 {
 327         unsigned int ret_data_size = 4;
 328         char *p = pdata;
 329 
 330         SMB_ASSERT(total_data_size >= 4);
 331 
 332         if (!lp_ea_support(SNUM(conn))) {
 333                 SIVAL(pdata,4,0);
 334                 return 4;
 335         }
 336 
 337         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
 338                 size_t dos_namelen;
 339                 fstring dos_ea_name;
 340                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
 341                 dos_namelen = strlen(dos_ea_name);
 342                 if (dos_namelen > 255 || dos_namelen == 0) {
 343                         break;
 344                 }
 345                 if (ea_list->ea.value.length > 65535) {
 346                         break;
 347                 }
 348                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
 349                         break;
 350                 }
 351 
 352                 /* We know we have room. */
 353                 SCVAL(p,0,ea_list->ea.flags);
 354                 SCVAL(p,1,dos_namelen);
 355                 SSVAL(p,2,ea_list->ea.value.length);
 356                 fstrcpy(p+4, dos_ea_name);
 357                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
 358 
 359                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
 360                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
 361         }
 362 
 363         ret_data_size = PTR_DIFF(p, pdata);
 364         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
 365         SIVAL(pdata,0,ret_data_size);
 366         return ret_data_size;
 367 }
 368 
 369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 370 {
 371         size_t total_ea_len = 0;
 372         TALLOC_CTX *mem_ctx = NULL;
 373 
 374         if (!lp_ea_support(SNUM(conn))) {
 375                 return 0;
 376         }
 377         mem_ctx = talloc_tos();
 378         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
 379         return total_ea_len;
 380 }
 381 
 382 /****************************************************************************
 383  Ensure the EA name is case insensitive by matching any existing EA name.
 384 ****************************************************************************/
 385 
 386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
     /* [<][>][^][v][top][bottom][index][help] */
 387 {
 388         size_t total_ea_len;
 389         TALLOC_CTX *mem_ctx = talloc_tos();
 390         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
 391 
 392         for (; ea_list; ea_list = ea_list->next) {
 393                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
 394                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
 395                                 &unix_ea_name[5], ea_list->ea.name));
 396                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
 397                         break;
 398                 }
 399         }
 400 }
 401 
 402 /****************************************************************************
 403  Set or delete an extended attribute.
 404 ****************************************************************************/
 405 
 406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
     /* [<][>][^][v][top][bottom][index][help] */
 407 {
 408         if (!lp_ea_support(SNUM(conn))) {
 409                 return NT_STATUS_EAS_NOT_SUPPORTED;
 410         }
 411 
 412         for (;ea_list; ea_list = ea_list->next) {
 413                 int ret;
 414                 fstring unix_ea_name;
 415 
 416                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
 417                 fstrcat(unix_ea_name, ea_list->ea.name);
 418 
 419                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
 420 
 421                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
 422 
 423                 if (samba_private_attr_name(unix_ea_name)) {
 424                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
 425                         return NT_STATUS_ACCESS_DENIED;
 426                 }
 427 
 428                 if (ea_list->ea.value.length == 0) {
 429                         /* Remove the attribute. */
 430                         if (fsp && (fsp->fh->fd != -1)) {
 431                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
 432                                         unix_ea_name, fsp->fsp_name));
 433                                 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
 434                         } else {
 435                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
 436                                         unix_ea_name, fname));
 437                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
 438                         }
 439 #ifdef ENOATTR
 440                         /* Removing a non existent attribute always succeeds. */
 441                         if (ret == -1 && errno == ENOATTR) {
 442                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
 443                                                 unix_ea_name));
 444                                 ret = 0;
 445                         }
 446 #endif
 447                 } else {
 448                         if (fsp && (fsp->fh->fd != -1)) {
 449                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
 450                                         unix_ea_name, fsp->fsp_name));
 451                                 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
 452                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
 453                         } else {
 454                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
 455                                         unix_ea_name, fname));
 456                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
 457                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
 458                         }
 459                 }
 460 
 461                 if (ret == -1) {
 462 #ifdef ENOTSUP
 463                         if (errno == ENOTSUP) {
 464                                 return NT_STATUS_EAS_NOT_SUPPORTED;
 465                         }
 466 #endif
 467                         return map_nt_error_from_unix(errno);
 468                 }
 469 
 470         }
 471         return NT_STATUS_OK;
 472 }
 473 /****************************************************************************
 474  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
 475 ****************************************************************************/
 476 
 477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     /* [<][>][^][v][top][bottom][index][help] */
 478 {
 479         struct ea_list *ea_list_head = NULL;
 480         size_t converted_size, offset = 0;
 481 
 482         while (offset + 2 < data_size) {
 483                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
 484                 unsigned int namelen = CVAL(pdata,offset);
 485 
 486                 offset++; /* Go past the namelen byte. */
 487 
 488                 /* integer wrap paranioa. */
 489                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
 490                                 (offset > data_size) || (namelen > data_size) ||
 491                                 (offset + namelen >= data_size)) {
 492                         break;
 493                 }
 494                 /* Ensure the name is null terminated. */
 495                 if (pdata[offset + namelen] != '\0') {
 496                         return NULL;
 497                 }
 498                 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
 499                                        &converted_size)) {
 500                         DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
 501                                  "failed: %s", strerror(errno)));
 502                 }
 503                 if (!eal->ea.name) {
 504                         return NULL;
 505                 }
 506 
 507                 offset += (namelen + 1); /* Go past the name + terminating zero. */
 508                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
 509                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
 510         }
 511 
 512         return ea_list_head;
 513 }
 514 
 515 /****************************************************************************
 516  Read one EA list entry from the buffer.
 517 ****************************************************************************/
 518 
 519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
     /* [<][>][^][v][top][bottom][index][help] */
 520 {
 521         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
 522         uint16 val_len;
 523         unsigned int namelen;
 524         size_t converted_size;
 525 
 526         if (!eal) {
 527                 return NULL;
 528         }
 529 
 530         if (data_size < 6) {
 531                 return NULL;
 532         }
 533 
 534         eal->ea.flags = CVAL(pdata,0);
 535         namelen = CVAL(pdata,1);
 536         val_len = SVAL(pdata,2);
 537 
 538         if (4 + namelen + 1 + val_len > data_size) {
 539                 return NULL;
 540         }
 541 
 542         /* Ensure the name is null terminated. */
 543         if (pdata[namelen + 4] != '\0') {
 544                 return NULL;
 545         }
 546         if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
 547                 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
 548                          strerror(errno)));
 549         }
 550         if (!eal->ea.name) {
 551                 return NULL;
 552         }
 553 
 554         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
 555         if (!eal->ea.value.data) {
 556                 return NULL;
 557         }
 558 
 559         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
 560 
 561         /* Ensure we're null terminated just in case we print the value. */
 562         eal->ea.value.data[val_len] = '\0';
 563         /* But don't count the null. */
 564         eal->ea.value.length--;
 565 
 566         if (pbytes_used) {
 567                 *pbytes_used = 4 + namelen + 1 + val_len;
 568         }
 569 
 570         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
 571         dump_data(10, eal->ea.value.data, eal->ea.value.length);
 572 
 573         return eal;
 574 }
 575 
 576 /****************************************************************************
 577  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
 578 ****************************************************************************/
 579 
 580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     /* [<][>][^][v][top][bottom][index][help] */
 581 {
 582         struct ea_list *ea_list_head = NULL;
 583         size_t offset = 0;
 584         size_t bytes_used = 0;
 585 
 586         while (offset < data_size) {
 587                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
 588 
 589                 if (!eal) {
 590                         return NULL;
 591                 }
 592 
 593                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
 594                 offset += bytes_used;
 595         }
 596 
 597         return ea_list_head;
 598 }
 599 
 600 /****************************************************************************
 601  Count the total EA size needed.
 602 ****************************************************************************/
 603 
 604 static size_t ea_list_size(struct ea_list *ealist)
     /* [<][>][^][v][top][bottom][index][help] */
 605 {
 606         fstring dos_ea_name;
 607         struct ea_list *listp;
 608         size_t ret = 0;
 609 
 610         for (listp = ealist; listp; listp = listp->next) {
 611                 push_ascii_fstring(dos_ea_name, listp->ea.name);
 612                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
 613         }
 614         /* Add on 4 for total length. */
 615         if (ret) {
 616                 ret += 4;
 617         }
 618 
 619         return ret;
 620 }
 621 
 622 /****************************************************************************
 623  Return a union of EA's from a file list and a list of names.
 624  The TALLOC context for the two lists *MUST* be identical as we steal
 625  memory from one list to add to another. JRA.
 626 ****************************************************************************/
 627 
 628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
     /* [<][>][^][v][top][bottom][index][help] */
 629 {
 630         struct ea_list *nlistp, *flistp;
 631 
 632         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
 633                 for (flistp = file_list; flistp; flistp = flistp->next) {
 634                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
 635                                 break;
 636                         }
 637                 }
 638 
 639                 if (flistp) {
 640                         /* Copy the data from this entry. */
 641                         nlistp->ea.flags = flistp->ea.flags;
 642                         nlistp->ea.value = flistp->ea.value;
 643                 } else {
 644                         /* Null entry. */
 645                         nlistp->ea.flags = 0;
 646                         ZERO_STRUCT(nlistp->ea.value);
 647                 }
 648         }
 649 
 650         *total_ea_len = ea_list_size(name_list);
 651         return name_list;
 652 }
 653 
 654 /****************************************************************************
 655   Send the required number of replies back.
 656   We assume all fields other than the data fields are
 657   set correctly for the type of call.
 658   HACK ! Always assumes smb_setup field is zero.
 659 ****************************************************************************/
 660 
 661 void send_trans2_replies(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 662                         struct smb_request *req,
 663                          const char *params,
 664                          int paramsize,
 665                          const char *pdata,
 666                          int datasize,
 667                          int max_data_bytes)
 668 {
 669         /* As we are using a protocol > LANMAN1 then the max_send
 670          variable must have been set in the sessetupX call.
 671          This takes precedence over the max_xmit field in the
 672          global struct. These different max_xmit variables should
 673          be merged as this is now too confusing */
 674 
 675         int data_to_send = datasize;
 676         int params_to_send = paramsize;
 677         int useable_space;
 678         const char *pp = params;
 679         const char *pd = pdata;
 680         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
 681         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
 682         int data_alignment_offset = 0;
 683         bool overflow = False;
 684 
 685         /* Modify the data_to_send and datasize and set the error if
 686            we're trying to send more than max_data_bytes. We still send
 687            the part of the packet(s) that fit. Strange, but needed
 688            for OS/2. */
 689 
 690         if (max_data_bytes > 0 && datasize > max_data_bytes) {
 691                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
 692                         max_data_bytes, datasize ));
 693                 datasize = data_to_send = max_data_bytes;
 694                 overflow = True;
 695         }
 696 
 697         /* If there genuinely are no parameters or data to send just send the empty packet */
 698 
 699         if(params_to_send == 0 && data_to_send == 0) {
 700                 reply_outbuf(req, 10, 0);
 701                 show_msg((char *)req->outbuf);
 702                 return;
 703         }
 704 
 705         /* When sending params and data ensure that both are nicely aligned */
 706         /* Only do this alignment when there is also data to send - else
 707                 can cause NT redirector problems. */
 708 
 709         if (((params_to_send % 4) != 0) && (data_to_send != 0))
 710                 data_alignment_offset = 4 - (params_to_send % 4);
 711 
 712         /* Space is bufsize minus Netbios over TCP header minus SMB header */
 713         /* The alignment_offset is to align the param bytes on an even byte
 714                 boundary. NT 4.0 Beta needs this to work correctly. */
 715 
 716         useable_space = max_send - (smb_size
 717                                     + 2 * 10 /* wct */
 718                                     + alignment_offset
 719                                     + data_alignment_offset);
 720 
 721         if (useable_space < 0) {
 722                 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
 723                           "= %d!!!", useable_space));
 724                 exit_server_cleanly("send_trans2_replies: Not enough space");
 725         }
 726 
 727         while (params_to_send || data_to_send) {
 728                 /* Calculate whether we will totally or partially fill this packet */
 729 
 730                 total_sent_thistime = params_to_send + data_to_send;
 731 
 732                 /* We can never send more than useable_space */
 733                 /*
 734                  * Note that 'useable_space' does not include the alignment offsets,
 735                  * but we must include the alignment offsets in the calculation of
 736                  * the length of the data we send over the wire, as the alignment offsets
 737                  * are sent here. Fix from Marc_Jacobsen@hp.com.
 738                  */
 739 
 740                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
 741 
 742                 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
 743                              + data_alignment_offset);
 744 
 745                 /*
 746                  * We might have SMBtrans2s in req which was transferred to
 747                  * the outbuf, fix that.
 748                  */
 749                 SCVAL(req->outbuf, smb_com, SMBtrans2);
 750 
 751                 /* Set total params and data to be sent */
 752                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
 753                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
 754 
 755                 /* Calculate how many parameters and data we can fit into
 756                  * this packet. Parameters get precedence
 757                  */
 758 
 759                 params_sent_thistime = MIN(params_to_send,useable_space);
 760                 data_sent_thistime = useable_space - params_sent_thistime;
 761                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
 762 
 763                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
 764 
 765                 /* smb_proff is the offset from the start of the SMB header to the
 766                         parameter bytes, however the first 4 bytes of outbuf are
 767                         the Netbios over TCP header. Thus use smb_base() to subtract
 768                         them from the calculation */
 769 
 770                 SSVAL(req->outbuf,smb_proff,
 771                       ((smb_buf(req->outbuf)+alignment_offset)
 772                        - smb_base(req->outbuf)));
 773 
 774                 if(params_sent_thistime == 0)
 775                         SSVAL(req->outbuf,smb_prdisp,0);
 776                 else
 777                         /* Absolute displacement of param bytes sent in this packet */
 778                         SSVAL(req->outbuf,smb_prdisp,pp - params);
 779 
 780                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
 781                 if(data_sent_thistime == 0) {
 782                         SSVAL(req->outbuf,smb_droff,0);
 783                         SSVAL(req->outbuf,smb_drdisp, 0);
 784                 } else {
 785                         /* The offset of the data bytes is the offset of the
 786                                 parameter bytes plus the number of parameters being sent this time */
 787                         SSVAL(req->outbuf, smb_droff,
 788                               ((smb_buf(req->outbuf)+alignment_offset)
 789                                - smb_base(req->outbuf))
 790                               + params_sent_thistime + data_alignment_offset);
 791                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
 792                 }
 793 
 794                 /* Initialize the padding for alignment */
 795 
 796                 if (alignment_offset != 0) {
 797                         memset(smb_buf(req->outbuf), 0, alignment_offset);
 798                 }
 799 
 800                 /* Copy the param bytes into the packet */
 801 
 802                 if(params_sent_thistime) {
 803                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
 804                                params_sent_thistime);
 805                 }
 806 
 807                 /* Copy in the data bytes */
 808                 if(data_sent_thistime) {
 809                         if (data_alignment_offset != 0) {
 810                                 memset((smb_buf(req->outbuf)+alignment_offset+
 811                                         params_sent_thistime), 0,
 812                                        data_alignment_offset);
 813                         }
 814                         memcpy(smb_buf(req->outbuf)+alignment_offset
 815                                +params_sent_thistime+data_alignment_offset,
 816                                pd,data_sent_thistime);
 817                 }
 818 
 819                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
 820                         params_sent_thistime, data_sent_thistime, useable_space));
 821                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
 822                         params_to_send, data_to_send, paramsize, datasize));
 823 
 824                 if (overflow) {
 825                         error_packet_set((char *)req->outbuf,
 826                                          ERRDOS,ERRbufferoverflow,
 827                                          STATUS_BUFFER_OVERFLOW,
 828                                          __LINE__,__FILE__);
 829                 }
 830 
 831                 /* Send the packet */
 832                 show_msg((char *)req->outbuf);
 833                 if (!srv_send_smb(smbd_server_fd(),
 834                                 (char *)req->outbuf,
 835                                 IS_CONN_ENCRYPTED(conn),
 836                                 &req->pcd))
 837                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
 838 
 839                 TALLOC_FREE(req->outbuf);
 840 
 841                 pp += params_sent_thistime;
 842                 pd += data_sent_thistime;
 843 
 844                 params_to_send -= params_sent_thistime;
 845                 data_to_send -= data_sent_thistime;
 846 
 847                 /* Sanity check */
 848                 if(params_to_send < 0 || data_to_send < 0) {
 849                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
 850                                 params_to_send, data_to_send));
 851                         return;
 852                 }
 853         }
 854 
 855         return;
 856 }
 857 
 858 /****************************************************************************
 859  Reply to a TRANSACT2_OPEN.
 860 ****************************************************************************/
 861 
 862 static void call_trans2open(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 863                             struct smb_request *req,
 864                             char **pparams, int total_params,
 865                             char **ppdata, int total_data,
 866                             unsigned int max_data_bytes)
 867 {
 868         char *params = *pparams;
 869         char *pdata = *ppdata;
 870         int deny_mode;
 871         int32 open_attr;
 872         bool oplock_request;
 873 #if 0
 874         bool return_additional_info;
 875         int16 open_sattr;
 876         time_t open_time;
 877 #endif
 878         int open_ofun;
 879         uint32 open_size;
 880         char *pname;
 881         char *fname = NULL;
 882         SMB_OFF_T size=0;
 883         int fattr=0,mtime=0;
 884         SMB_INO_T inode = 0;
 885         SMB_STRUCT_STAT sbuf;
 886         int smb_action = 0;
 887         files_struct *fsp;
 888         struct ea_list *ea_list = NULL;
 889         uint16 flags = 0;
 890         NTSTATUS status;
 891         uint32 access_mask;
 892         uint32 share_mode;
 893         uint32 create_disposition;
 894         uint32 create_options = 0;
 895         TALLOC_CTX *ctx = talloc_tos();
 896 
 897         SET_STAT_INVALID(sbuf);
 898 
 899         /*
 900          * Ensure we have enough parameters to perform the operation.
 901          */
 902 
 903         if (total_params < 29) {
 904                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 905                 return;
 906         }
 907 
 908         flags = SVAL(params, 0);
 909         deny_mode = SVAL(params, 2);
 910         open_attr = SVAL(params,6);
 911         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
 912         if (oplock_request) {
 913                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
 914         }
 915 
 916 #if 0
 917         return_additional_info = BITSETW(params,0);
 918         open_sattr = SVAL(params, 4);
 919         open_time = make_unix_date3(params+8);
 920 #endif
 921         open_ofun = SVAL(params,12);
 922         open_size = IVAL(params,14);
 923         pname = &params[28];
 924 
 925         if (IS_IPC(conn)) {
 926                 reply_doserror(req, ERRSRV, ERRaccess);
 927                 return;
 928         }
 929 
 930         srvstr_get_path(ctx, params, req->flags2, &fname, pname,
 931                         total_params - 28, STR_TERMINATE,
 932                         &status);
 933         if (!NT_STATUS_IS_OK(status)) {
 934                 reply_nterror(req, status);
 935                 return;
 936         }
 937 
 938         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
 939                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
 940                 (unsigned int)open_ofun, open_size));
 941 
 942         if (open_ofun == 0) {
 943                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
 944                 return;
 945         }
 946 
 947         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
 948                                 &access_mask,
 949                                 &share_mode,
 950                                 &create_disposition,
 951                                 &create_options)) {
 952                 reply_doserror(req, ERRDOS, ERRbadaccess);
 953                 return;
 954         }
 955 
 956         /* Any data in this call is an EA list. */
 957         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
 958                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
 959                 return;
 960         }
 961 
 962         if (total_data != 4) {
 963                 if (total_data < 10) {
 964                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 965                         return;
 966                 }
 967 
 968                 if (IVAL(pdata,0) > total_data) {
 969                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
 970                                 IVAL(pdata,0), (unsigned int)total_data));
 971                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 972                         return;
 973                 }
 974 
 975                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
 976                                        total_data - 4);
 977                 if (!ea_list) {
 978                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 979                         return;
 980                 }
 981         } else if (IVAL(pdata,0) != 4) {
 982                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 983                 return;
 984         }
 985 
 986         status = SMB_VFS_CREATE_FILE(
 987                 conn,                                   /* conn */
 988                 req,                                    /* req */
 989                 0,                                      /* root_dir_fid */
 990                 fname,                                  /* fname */
 991                 CFF_DOS_PATH,                           /* create_file_flags */
 992                 access_mask,                            /* access_mask */
 993                 share_mode,                             /* share_access */
 994                 create_disposition,                     /* create_disposition*/
 995                 create_options,                         /* create_options */
 996                 open_attr,                              /* file_attributes */
 997                 oplock_request,                         /* oplock_request */
 998                 open_size,                              /* allocation_size */
 999                 NULL,                                   /* sd */
1000                 ea_list,                                /* ea_list */
1001                 &fsp,                                   /* result */
1002                 &smb_action,                            /* pinfo */
1003                 &sbuf);                                 /* psbuf */
1004 
1005         if (!NT_STATUS_IS_OK(status)) {
1006                 if (open_was_deferred(req->mid)) {
1007                         /* We have re-scheduled this call. */
1008                         return;
1009                 }
1010                 reply_openerror(req, status);
1011                 return;
1012         }
1013 
1014         size = get_file_size_stat(&sbuf);
1015         fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016         mtime = sbuf.st_mtime;
1017         inode = sbuf.st_ino;
1018         if (fattr & aDIR) {
1019                 close_file(req, fsp, ERROR_CLOSE);
1020                 reply_doserror(req, ERRDOS,ERRnoaccess);
1021                 return;
1022         }
1023 
1024         /* Realloc the size of parameters and data we will return */
1025         *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026         if(*pparams == NULL ) {
1027                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1028                 return;
1029         }
1030         params = *pparams;
1031 
1032         SSVAL(params,0,fsp->fnum);
1033         SSVAL(params,2,fattr);
1034         srv_put_dos_date2(params,4, mtime);
1035         SIVAL(params,8, (uint32)size);
1036         SSVAL(params,12,deny_mode);
1037         SSVAL(params,14,0); /* open_type - file or directory. */
1038         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1039 
1040         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1042         }
1043 
1044         SSVAL(params,18,smb_action);
1045 
1046         /*
1047          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1048          */
1049         SIVAL(params,20,inode);
1050         SSVAL(params,24,0); /* Padding. */
1051         if (flags & 8) {
1052                 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053                 SIVAL(params, 26, ea_size);
1054         } else {
1055                 SIVAL(params, 26, 0);
1056         }
1057 
1058         /* Send the required number of replies */
1059         send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1060 }
1061 
1062 /*********************************************************
1063  Routine to check if a given string matches exactly.
1064  as a special case a mask of "." does NOT match. That
1065  is required for correct wildcard semantics
1066  Case can be significant or not.
1067 **********************************************************/
1068 
1069 static bool exact_match(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
1070                 const char *str,
1071                 const char *mask)
1072 {
1073         if (mask[0] == '.' && mask[1] == 0)
1074                 return False;
1075         if (dptr_has_wild(conn->dirptr)) {
1076                 return False;
1077         }
1078         if (conn->case_sensitive)
1079                 return strcmp(str,mask)==0;
1080         else
1081                 return StrCaseCmp(str,mask) == 0;
1082 }
1083 
1084 /****************************************************************************
1085  Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1087 
1088 static uint32 unix_filetype(mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
1089 {
1090         if(S_ISREG(mode))
1091                 return UNIX_TYPE_FILE;
1092         else if(S_ISDIR(mode))
1093                 return UNIX_TYPE_DIR;
1094 #ifdef S_ISLNK
1095         else if(S_ISLNK(mode))
1096                 return UNIX_TYPE_SYMLINK;
1097 #endif
1098 #ifdef S_ISCHR
1099         else if(S_ISCHR(mode))
1100                 return UNIX_TYPE_CHARDEV;
1101 #endif
1102 #ifdef S_ISBLK
1103         else if(S_ISBLK(mode))
1104                 return UNIX_TYPE_BLKDEV;
1105 #endif
1106 #ifdef S_ISFIFO
1107         else if(S_ISFIFO(mode))
1108                 return UNIX_TYPE_FIFO;
1109 #endif
1110 #ifdef S_ISSOCK
1111         else if(S_ISSOCK(mode))
1112                 return UNIX_TYPE_SOCKET;
1113 #endif
1114 
1115         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116         return UNIX_TYPE_UNKNOWN;
1117 }
1118 
1119 /****************************************************************************
1120  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1122 
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1124 
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
1126                                 SMB_STRUCT_STAT *psbuf,
1127                                 uint32 perms,
1128                                 enum perm_type ptype,
1129                                 mode_t *ret_perms)
1130 {
1131         mode_t ret = 0;
1132 
1133         if (perms == SMB_MODE_NO_CHANGE) {
1134                 if (!VALID_STAT(*psbuf)) {
1135                         return NT_STATUS_INVALID_PARAMETER;
1136                 } else {
1137                         *ret_perms = psbuf->st_mode;
1138                         return NT_STATUS_OK;
1139                 }
1140         }
1141 
1142         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1151 #ifdef S_ISVTX
1152         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1153 #endif
1154 #ifdef S_ISGID
1155         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1156 #endif
1157 #ifdef S_ISUID
1158         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1159 #endif
1160 
1161         switch (ptype) {
1162         case PERM_NEW_FILE:
1163                 /* Apply mode mask */
1164                 ret &= lp_create_mask(SNUM(conn));
1165                 /* Add in force bits */
1166                 ret |= lp_force_create_mode(SNUM(conn));
1167                 break;
1168         case PERM_NEW_DIR:
1169                 ret &= lp_dir_mask(SNUM(conn));
1170                 /* Add in force bits */
1171                 ret |= lp_force_dir_mode(SNUM(conn));
1172                 break;
1173         case PERM_EXISTING_FILE:
1174                 /* Apply mode mask */
1175                 ret &= lp_security_mask(SNUM(conn));
1176                 /* Add in force bits */
1177                 ret |= lp_force_security_mode(SNUM(conn));
1178                 break;
1179         case PERM_EXISTING_DIR:
1180                 /* Apply mode mask */
1181                 ret &= lp_dir_security_mask(SNUM(conn));
1182                 /* Add in force bits */
1183                 ret |= lp_force_dir_security_mode(SNUM(conn));
1184                 break;
1185         }
1186 
1187         *ret_perms = ret;
1188         return NT_STATUS_OK;
1189 }
1190 
1191 /****************************************************************************
1192  Needed to show the msdfs symlinks as directories. Modifies psbuf
1193  to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1195 
1196 static bool check_msdfs_link(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
1197                                 const char *pathname,
1198                                 SMB_STRUCT_STAT *psbuf)
1199 {
1200         int saved_errno = errno;
1201         if(lp_host_msdfs() &&
1202                 lp_msdfs_root(SNUM(conn)) &&
1203                 is_msdfs_link(conn, pathname, psbuf)) {
1204 
1205                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206                         "as a directory\n",
1207                         pathname));
1208                 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209                 errno = saved_errno;
1210                 return true;
1211         }
1212         errno = saved_errno;
1213         return false;
1214 }
1215 
1216 
1217 /****************************************************************************
1218  Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1220 
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1222                                 connection_struct *conn,
1223                                 uint16 flags2,
1224                                 const char *path_mask,
1225                                 uint32 dirtype,
1226                                 int info_level,
1227                                 int requires_resume_key,
1228                                 bool dont_descend,
1229                                 bool ask_sharemode,
1230                                 char **ppdata,
1231                                 char *base_data,
1232                                 char *end_data,
1233                                 int space_remaining,
1234                                 bool *out_of_space,
1235                                 bool *got_exact_match,
1236                                 int *last_entry_off,
1237                                 struct ea_list *name_list)
1238 {
1239         char *dname;
1240         bool found = False;
1241         SMB_STRUCT_STAT sbuf;
1242         const char *mask = NULL;
1243         char *pathreal = NULL;
1244         char *fname = NULL;
1245         char *p, *q, *pdata = *ppdata;
1246         uint32 reskey=0;
1247         long prev_dirpos=0;
1248         uint32 mode=0;
1249         SMB_OFF_T file_size = 0;
1250         uint64_t allocation_size = 0;
1251         uint32 len;
1252         struct timespec mdate_ts, adate_ts, create_date_ts;
1253         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1254         char *nameptr;
1255         char *last_entry_ptr;
1256         bool was_8_3;
1257         uint32 nt_extmode; /* Used for NT connections instead of mode */
1258         bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259         bool check_mangled_names = lp_manglednames(conn->params);
1260         char mangled_name[13]; /* mangled 8.3 name. */
1261 
1262         *out_of_space = False;
1263         *got_exact_match = False;
1264 
1265         ZERO_STRUCT(mdate_ts);
1266         ZERO_STRUCT(adate_ts);
1267         ZERO_STRUCT(create_date_ts);
1268 
1269         if (!conn->dirptr) {
1270                 return(False);
1271         }
1272 
1273         p = strrchr_m(path_mask,'/');
1274         if(p != NULL) {
1275                 if(p[1] == '\0') {
1276                         mask = talloc_strdup(ctx,"*.*");
1277                 } else {
1278                         mask = p+1;
1279                 }
1280         } else {
1281                 mask = path_mask;
1282         }
1283 
1284         while (!found) {
1285                 bool got_match;
1286                 bool ms_dfs_link = False;
1287 
1288                 /* Needed if we run out of space */
1289                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290                 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1291 
1292                 /*
1293                  * Due to bugs in NT client redirectors we are not using
1294                  * resume keys any more - set them to zero.
1295                  * Check out the related comments in findfirst/findnext.
1296                  * JRA.
1297                  */
1298 
1299                 reskey = 0;
1300 
1301                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302                         (long)conn->dirptr,curr_dirpos));
1303 
1304                 if (!dname) {
1305                         return(False);
1306                 }
1307 
1308                 /*
1309                  * fname may get mangled, dname is never mangled.
1310                  * Whenever we're accessing the filesystem we use
1311                  * pathreal which is composed from dname.
1312                  */
1313 
1314                 pathreal = NULL;
1315                 fname = dname;
1316 
1317                 /* Mangle fname if it's an illegal name. */
1318                 if (mangle_must_mangle(dname,conn->params)) {
1319                         if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1320                                 TALLOC_FREE(fname);
1321                                 continue; /* Error - couldn't mangle. */
1322                         }
1323                         fname = talloc_strdup(ctx, mangled_name);
1324                         if (!fname) {
1325                                 return False;
1326                         }
1327                 }
1328 
1329                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330                         got_match = mask_match(fname, mask, conn->case_sensitive);
1331                 }
1332 
1333                 if(!got_match && check_mangled_names &&
1334                    !mangle_is_8_3(fname, False, conn->params)) {
1335                         /*
1336                          * It turns out that NT matches wildcards against
1337                          * both long *and* short names. This may explain some
1338                          * of the wildcard wierdness from old DOS clients
1339                          * that some people have been seeing.... JRA.
1340                          */
1341                         /* Force the mangling into 8.3. */
1342                         if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1343                                 TALLOC_FREE(fname);
1344                                 continue; /* Error - couldn't mangle. */
1345                         }
1346 
1347                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1349                         }
1350                 }
1351 
1352                 if (got_match) {
1353                         bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1354 
1355                         if (dont_descend && !isdots) {
1356                                 TALLOC_FREE(fname);
1357                                 continue;
1358                         }
1359 
1360                         if (needslash) {
1361                                 pathreal = NULL;
1362                                 pathreal = talloc_asprintf(ctx,
1363                                         "%s/%s",
1364                                         conn->dirpath,
1365                                         dname);
1366                         } else {
1367                                 pathreal = talloc_asprintf(ctx,
1368                                         "%s%s",
1369                                         conn->dirpath,
1370                                         dname);
1371                         }
1372 
1373                         if (!pathreal) {
1374                                 TALLOC_FREE(fname);
1375                                 return False;
1376                         }
1377 
1378                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1379                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381                                                 pathreal,strerror(errno)));
1382                                         TALLOC_FREE(pathreal);
1383                                         TALLOC_FREE(fname);
1384                                         continue;
1385                                 }
1386                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387                                 /* Needed to show the msdfs symlinks as
1388                                  * directories */
1389 
1390                                 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391                                 if (!ms_dfs_link) {
1392                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393                                                 pathreal,strerror(errno)));
1394                                         TALLOC_FREE(pathreal);
1395                                         TALLOC_FREE(fname);
1396                                         continue;
1397                                 }
1398                         }
1399 
1400                         if (ms_dfs_link) {
1401                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1402                         } else {
1403                                 mode = dos_mode(conn,pathreal,&sbuf);
1404                         }
1405 
1406                         if (!dir_check_ftype(conn,mode,dirtype)) {
1407                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408                                 TALLOC_FREE(pathreal);
1409                                 TALLOC_FREE(fname);
1410                                 continue;
1411                         }
1412 
1413                         if (!(mode & aDIR)) {
1414                                 file_size = get_file_size_stat(&sbuf);
1415                         }
1416                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1417 
1418                         mdate_ts = get_mtimespec(&sbuf);
1419                         adate_ts = get_atimespec(&sbuf);
1420                         create_date_ts = get_create_timespec(&sbuf,
1421                             lp_fake_dir_create_times(SNUM(conn)));
1422 
1423                         if (ask_sharemode) {
1424                                 struct timespec write_time_ts;
1425                                 struct file_id fileid;
1426 
1427                                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1428                                 get_file_infos(fileid, NULL, &write_time_ts);
1429                                 if (!null_timespec(write_time_ts)) {
1430                                         mdate_ts = write_time_ts;
1431                                 }
1432                         }
1433 
1434                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1435                                 dos_filetime_timespec(&create_date_ts);
1436                                 dos_filetime_timespec(&mdate_ts);
1437                                 dos_filetime_timespec(&adate_ts);
1438                         }
1439 
1440                         create_date = convert_timespec_to_time_t(create_date_ts);
1441                         mdate = convert_timespec_to_time_t(mdate_ts);
1442                         adate = convert_timespec_to_time_t(adate_ts);
1443 
1444                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1445                                 pathreal,fname));
1446 
1447                         found = True;
1448 
1449                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1450                 }
1451 
1452                 if (!found)
1453                         TALLOC_FREE(fname);
1454         }
1455 
1456         p = pdata;
1457         last_entry_ptr = p;
1458 
1459         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1460 
1461         switch (info_level) {
1462                 case SMB_FIND_INFO_STANDARD:
1463                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464                         if(requires_resume_key) {
1465                                 SIVAL(p,0,reskey);
1466                                 p += 4;
1467                         }
1468                         srv_put_dos_date2(p,0,create_date);
1469                         srv_put_dos_date2(p,4,adate);
1470                         srv_put_dos_date2(p,8,mdate);
1471                         SIVAL(p,12,(uint32)file_size);
1472                         SIVAL(p,16,(uint32)allocation_size);
1473                         SSVAL(p,20,mode);
1474                         p += 23;
1475                         nameptr = p;
1476                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477                                 p += ucs2_align(base_data, p, 0);
1478                         }
1479                         len = srvstr_push(base_data, flags2, p,
1480                                           fname, PTR_DIFF(end_data, p),
1481                                           STR_TERMINATE);
1482                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483                                 if (len > 2) {
1484                                         SCVAL(nameptr, -1, len - 2);
1485                                 } else {
1486                                         SCVAL(nameptr, -1, 0);
1487                                 }
1488                         } else {
1489                                 if (len > 1) {
1490                                         SCVAL(nameptr, -1, len - 1);
1491                                 } else {
1492                                         SCVAL(nameptr, -1, 0);
1493                                 }
1494                         }
1495                         p += len;
1496                         break;
1497 
1498                 case SMB_FIND_EA_SIZE:
1499                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500                         if(requires_resume_key) {
1501                                 SIVAL(p,0,reskey);
1502                                 p += 4;
1503                         }
1504                         srv_put_dos_date2(p,0,create_date);
1505                         srv_put_dos_date2(p,4,adate);
1506                         srv_put_dos_date2(p,8,mdate);
1507                         SIVAL(p,12,(uint32)file_size);
1508                         SIVAL(p,16,(uint32)allocation_size);
1509                         SSVAL(p,20,mode);
1510                         {
1511                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512                                 SIVAL(p,22,ea_size); /* Extended attributes */
1513                         }
1514                         p += 27;
1515                         nameptr = p - 1;
1516                         len = srvstr_push(base_data, flags2,
1517                                           p, fname, PTR_DIFF(end_data, p),
1518                                           STR_TERMINATE | STR_NOALIGN);
1519                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520                                 if (len > 2) {
1521                                         len -= 2;
1522                                 } else {
1523                                         len = 0;
1524                                 }
1525                         } else {
1526                                 if (len > 1) {
1527                                         len -= 1;
1528                                 } else {
1529                                         len = 0;
1530                                 }
1531                         }
1532                         SCVAL(nameptr,0,len);
1533                         p += len;
1534                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535                         break;
1536 
1537                 case SMB_FIND_EA_LIST:
1538                 {
1539                         struct ea_list *file_list = NULL;
1540                         size_t ea_len = 0;
1541 
1542                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543                         if (!name_list) {
1544                                 return False;
1545                         }
1546                         if(requires_resume_key) {
1547                                 SIVAL(p,0,reskey);
1548                                 p += 4;
1549                         }
1550                         srv_put_dos_date2(p,0,create_date);
1551                         srv_put_dos_date2(p,4,adate);
1552                         srv_put_dos_date2(p,8,mdate);
1553                         SIVAL(p,12,(uint32)file_size);
1554                         SIVAL(p,16,(uint32)allocation_size);
1555                         SSVAL(p,20,mode);
1556                         p += 22; /* p now points to the EA area. */
1557 
1558                         file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559                         name_list = ea_list_union(name_list, file_list, &ea_len);
1560 
1561                         /* We need to determine if this entry will fit in the space available. */
1562                         /* Max string size is 255 bytes. */
1563                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564                                 /* Move the dirptr back to prev_dirpos */
1565                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566                                 *out_of_space = True;
1567                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568                                 return False; /* Not finished - just out of space */
1569                         }
1570 
1571                         /* Push the ea_data followed by the name. */
1572                         p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573                         nameptr = p;
1574                         len = srvstr_push(base_data, flags2,
1575                                           p + 1, fname, PTR_DIFF(end_data, p+1),
1576                                           STR_TERMINATE | STR_NOALIGN);
1577                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578                                 if (len > 2) {
1579                                         len -= 2;
1580                                 } else {
1581                                         len = 0;
1582                                 }
1583                         } else {
1584                                 if (len > 1) {
1585                                         len -= 1;
1586                                 } else {
1587                                         len = 0;
1588                                 }
1589                         }
1590                         SCVAL(nameptr,0,len);
1591                         p += len + 1;
1592                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593                         break;
1594                 }
1595 
1596                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599                         p += 4;
1600                         SIVAL(p,0,reskey); p += 4;
1601                         put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1602                         put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1603                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1604                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1605                         SOFF_T(p,0,file_size); p += 8;
1606                         SOFF_T(p,0,allocation_size); p += 8;
1607                         SIVAL(p,0,nt_extmode); p += 4;
1608                         q = p; p += 4; /* q is placeholder for name length. */
1609                         {
1610                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611                                 SIVAL(p,0,ea_size); /* Extended attributes */
1612                                 p += 4;
1613                         }
1614                         /* Clear the short name buffer. This is
1615                          * IMPORTANT as not doing so will trigger
1616                          * a Win2k client bug. JRA.
1617                          */
1618                         if (!was_8_3 && check_mangled_names) {
1619                                 if (!name_to_8_3(fname,mangled_name,True,
1620                                                    conn->params)) {
1621                                         /* Error - mangle failed ! */
1622                                         memset(mangled_name,'\0',12);
1623                                 }
1624                                 mangled_name[12] = 0;
1625                                 len = srvstr_push(base_data, flags2,
1626                                                   p+2, mangled_name, 24,
1627                                                   STR_UPPER|STR_UNICODE);
1628                                 if (len < 24) {
1629                                         memset(p + 2 + len,'\0',24 - len);
1630                                 }
1631                                 SSVAL(p, 0, len);
1632                         } else {
1633                                 memset(p,'\0',26);
1634                         }
1635                         p += 2 + 24;
1636                         len = srvstr_push(base_data, flags2, p,
1637                                           fname, PTR_DIFF(end_data, p),
1638                                           STR_TERMINATE_ASCII);
1639                         SIVAL(q,0,len);
1640                         p += len;
1641                         SIVAL(p,0,0); /* Ensure any padding is null. */
1642                         len = PTR_DIFF(p, pdata);
1643                         len = (len + 3) & ~3;
1644                         SIVAL(pdata,0,len);
1645                         p = pdata + len;
1646                         break;
1647 
1648                 case SMB_FIND_FILE_DIRECTORY_INFO:
1649                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650                         p += 4;
1651                         SIVAL(p,0,reskey); p += 4;
1652                         put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1653                         put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1654                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1655                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1656                         SOFF_T(p,0,file_size); p += 8;
1657                         SOFF_T(p,0,allocation_size); p += 8;
1658                         SIVAL(p,0,nt_extmode); p += 4;
1659                         len = srvstr_push(base_data, flags2,
1660                                           p + 4, fname, PTR_DIFF(end_data, p+4),
1661                                           STR_TERMINATE_ASCII);
1662                         SIVAL(p,0,len);
1663                         p += 4 + len;
1664                         SIVAL(p,0,0); /* Ensure any padding is null. */
1665                         len = PTR_DIFF(p, pdata);
1666                         len = (len + 3) & ~3;
1667                         SIVAL(pdata,0,len);
1668                         p = pdata + len;
1669                         break;
1670 
1671                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673                         p += 4;
1674                         SIVAL(p,0,reskey); p += 4;
1675                         put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1676                         put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1677                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1678                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1679                         SOFF_T(p,0,file_size); p += 8;
1680                         SOFF_T(p,0,allocation_size); p += 8;
1681                         SIVAL(p,0,nt_extmode); p += 4;
1682                         q = p; p += 4; /* q is placeholder for name length. */
1683                         {
1684                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685                                 SIVAL(p,0,ea_size); /* Extended attributes */
1686                                 p +=4;
1687                         }
1688                         len = srvstr_push(base_data, flags2, p,
1689                                           fname, PTR_DIFF(end_data, p),
1690                                           STR_TERMINATE_ASCII);
1691                         SIVAL(q, 0, len);
1692                         p += len;
1693 
1694                         SIVAL(p,0,0); /* Ensure any padding is null. */
1695                         len = PTR_DIFF(p, pdata);
1696                         len = (len + 3) & ~3;
1697                         SIVAL(pdata,0,len);
1698                         p = pdata + len;
1699                         break;
1700 
1701                 case SMB_FIND_FILE_NAMES_INFO:
1702                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703                         p += 4;
1704                         SIVAL(p,0,reskey); p += 4;
1705                         p += 4;
1706                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707                            acl on a dir (tridge) */
1708                         len = srvstr_push(base_data, flags2, p,
1709                                           fname, PTR_DIFF(end_data, p),
1710                                           STR_TERMINATE_ASCII);
1711                         SIVAL(p, -4, len);
1712                         p += len;
1713                         SIVAL(p,0,0); /* Ensure any padding is null. */
1714                         len = PTR_DIFF(p, pdata);
1715                         len = (len + 3) & ~3;
1716                         SIVAL(pdata,0,len);
1717                         p = pdata + len;
1718                         break;
1719 
1720                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722                         p += 4;
1723                         SIVAL(p,0,reskey); p += 4;
1724                         put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1725                         put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1726                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1727                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1728                         SOFF_T(p,0,file_size); p += 8;
1729                         SOFF_T(p,0,allocation_size); p += 8;
1730                         SIVAL(p,0,nt_extmode); p += 4;
1731                         q = p; p += 4; /* q is placeholder for name length. */
1732                         {
1733                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734                                 SIVAL(p,0,ea_size); /* Extended attributes */
1735                                 p +=4;
1736                         }
1737                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740                         len = srvstr_push(base_data, flags2, p,
1741                                           fname, PTR_DIFF(end_data, p),
1742                                           STR_TERMINATE_ASCII);
1743                         SIVAL(q, 0, len);
1744                         p += len; 
1745                         SIVAL(p,0,0); /* Ensure any padding is null. */
1746                         len = PTR_DIFF(p, pdata);
1747                         len = (len + 3) & ~3;
1748                         SIVAL(pdata,0,len);
1749                         p = pdata + len;
1750                         break;
1751 
1752                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755                         p += 4;
1756                         SIVAL(p,0,reskey); p += 4;
1757                         put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1758                         put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1759                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1760                         put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1761                         SOFF_T(p,0,file_size); p += 8;
1762                         SOFF_T(p,0,allocation_size); p += 8;
1763                         SIVAL(p,0,nt_extmode); p += 4;
1764                         q = p; p += 4; /* q is placeholder for name length */
1765                         {
1766                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767                                 SIVAL(p,0,ea_size); /* Extended attributes */
1768                                 p +=4;
1769                         }
1770                         /* Clear the short name buffer. This is
1771                          * IMPORTANT as not doing so will trigger
1772                          * a Win2k client bug. JRA.
1773                          */
1774                         if (!was_8_3 && check_mangled_names) {
1775                                 if (!name_to_8_3(fname,mangled_name,True,
1776                                                 conn->params)) {
1777                                         /* Error - mangle failed ! */
1778                                         memset(mangled_name,'\0',12);
1779                                 }
1780                                 mangled_name[12] = 0;
1781                                 len = srvstr_push(base_data, flags2,
1782                                                   p+2, mangled_name, 24,
1783                                                   STR_UPPER|STR_UNICODE);
1784                                 SSVAL(p, 0, len);
1785                                 if (len < 24) {
1786                                         memset(p + 2 + len,'\0',24 - len);
1787                                 }
1788                                 SSVAL(p, 0, len);
1789                         } else {
1790                                 memset(p,'\0',26);
1791                         }
1792                         p += 26;
1793                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1794                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796                         len = srvstr_push(base_data, flags2, p,
1797                                           fname, PTR_DIFF(end_data, p),
1798                                           STR_TERMINATE_ASCII);
1799                         SIVAL(q,0,len);
1800                         p += len;
1801                         SIVAL(p,0,0); /* Ensure any padding is null. */
1802                         len = PTR_DIFF(p, pdata);
1803                         len = (len + 3) & ~3;
1804                         SIVAL(pdata,0,len);
1805                         p = pdata + len;
1806                         break;
1807 
1808                 /* CIFS UNIX Extension. */
1809 
1810                 case SMB_FIND_FILE_UNIX:
1811                 case SMB_FIND_FILE_UNIX_INFO2:
1812                         p+= 4;
1813                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1814 
1815                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1816 
1817                         if (info_level == SMB_FIND_FILE_UNIX) {
1818                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819                                 p = store_file_unix_basic(conn, p,
1820                                                         NULL, &sbuf);
1821                                 len = srvstr_push(base_data, flags2, p,
1822                                                   fname, PTR_DIFF(end_data, p),
1823                                                   STR_TERMINATE);
1824                         } else {
1825                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826                                 p = store_file_unix_basic_info2(conn, p,
1827                                                         NULL, &sbuf);
1828                                 nameptr = p;
1829                                 p += 4;
1830                                 len = srvstr_push(base_data, flags2, p, fname,
1831                                                   PTR_DIFF(end_data, p), 0);
1832                                 SIVAL(nameptr, 0, len);
1833                         }
1834 
1835                         p += len;
1836                         SIVAL(p,0,0); /* Ensure any padding is null. */
1837 
1838                         len = PTR_DIFF(p, pdata);
1839                         len = (len + 3) & ~3;
1840                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1841                         p = pdata + len;
1842                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1843 
1844                         break;
1845 
1846                 default:
1847                         TALLOC_FREE(fname);
1848                         return(False);
1849         }
1850 
1851         TALLOC_FREE(fname);
1852         if (PTR_DIFF(p,pdata) > space_remaining) {
1853                 /* Move the dirptr back to prev_dirpos */
1854                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1855                 *out_of_space = True;
1856                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1857                 return False; /* Not finished - just out of space */
1858         }
1859 
1860         /* Setup the last entry pointer, as an offset from base_data */
1861         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1862         /* Advance the data pointer to the next slot */
1863         *ppdata = p;
1864 
1865         return(found);
1866 }
1867 
1868 /****************************************************************************
1869  Reply to a TRANS2_FINDFIRST.
1870 ****************************************************************************/
1871 
1872 static void call_trans2findfirst(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
1873                                  struct smb_request *req,
1874                                  char **pparams, int total_params,
1875                                  char **ppdata, int total_data,
1876                                  unsigned int max_data_bytes)
1877 {
1878         /* We must be careful here that we don't return more than the
1879                 allowed number of data bytes. If this means returning fewer than
1880                 maxentries then so be it. We assume that the redirector has
1881                 enough room for the fixed number of parameter bytes it has
1882                 requested. */
1883         char *params = *pparams;
1884         char *pdata = *ppdata;
1885         char *data_end;
1886         uint32 dirtype;
1887         int maxentries;
1888         uint16 findfirst_flags;
1889         bool close_after_first;
1890         bool close_if_end;
1891         bool requires_resume_key;
1892         int info_level;
1893         char *directory = NULL;
1894         char *mask = NULL;
1895         char *p;
1896         int last_entry_off=0;
1897         int dptr_num = -1;
1898         int numentries = 0;
1899         int i;
1900         bool finished = False;
1901         bool dont_descend = False;
1902         bool out_of_space = False;
1903         int space_remaining;
1904         bool mask_contains_wcard = False;
1905         SMB_STRUCT_STAT sbuf;
1906         struct ea_list *ea_list = NULL;
1907         NTSTATUS ntstatus = NT_STATUS_OK;
1908         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1909         TALLOC_CTX *ctx = talloc_tos();
1910 
1911         if (total_params < 13) {
1912                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913                 return;
1914         }
1915 
1916         dirtype = SVAL(params,0);
1917         maxentries = SVAL(params,2);
1918         findfirst_flags = SVAL(params,4);
1919         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1920         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1921         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1922         info_level = SVAL(params,6);
1923 
1924         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1925 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1926                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1927                 info_level, max_data_bytes));
1928 
1929         if (!maxentries) {
1930                 /* W2K3 seems to treat zero as 1. */
1931                 maxentries = 1;
1932         }
1933 
1934         switch (info_level) {
1935                 case SMB_FIND_INFO_STANDARD:
1936                 case SMB_FIND_EA_SIZE:
1937                 case SMB_FIND_EA_LIST:
1938                 case SMB_FIND_FILE_DIRECTORY_INFO:
1939                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940                 case SMB_FIND_FILE_NAMES_INFO:
1941                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1942                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1943                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1944                         break;
1945                 case SMB_FIND_FILE_UNIX:
1946                 case SMB_FIND_FILE_UNIX_INFO2:
1947                         /* Always use filesystem for UNIX mtime query. */
1948                         ask_sharemode = false;
1949                         if (!lp_unix_extensions()) {
1950                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1951                                 return;
1952                         }
1953                         break;
1954                 default:
1955                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956                         return;
1957         }
1958 
1959         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1960                               params+12, total_params - 12,
1961                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1962         if (!NT_STATUS_IS_OK(ntstatus)) {
1963                 reply_nterror(req, ntstatus);
1964                 return;
1965         }
1966 
1967         ntstatus = resolve_dfspath_wcard(ctx, conn,
1968                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1969                         directory,
1970                         &directory,
1971                         &mask_contains_wcard);
1972         if (!NT_STATUS_IS_OK(ntstatus)) {
1973                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1974                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1975                                         ERRSRV, ERRbadpath);
1976                         return;
1977                 }
1978                 reply_nterror(req, ntstatus);
1979                 return;
1980         }
1981 
1982         ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1983         if (!NT_STATUS_IS_OK(ntstatus)) {
1984                 reply_nterror(req, ntstatus);
1985                 return;
1986         }
1987 
1988         ntstatus = check_name(conn, directory);
1989         if (!NT_STATUS_IS_OK(ntstatus)) {
1990                 reply_nterror(req, ntstatus);
1991                 return;
1992         }
1993 
1994         p = strrchr_m(directory,'/');
1995         if(p == NULL) {
1996                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1997                 if((directory[0] == '.') && (directory[1] == '\0')) {
1998                         mask = talloc_strdup(ctx,"*");
1999                         if (!mask) {
2000                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001                                 return;
2002                         }
2003                         mask_contains_wcard = True;
2004                 }
2005                 directory = talloc_strdup(talloc_tos(), "./");
2006                 if (!directory) {
2007                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2008                         return;
2009                 }
2010         } else {
2011                 *p = 0;
2012         }
2013 
2014         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2015 
2016         if (info_level == SMB_FIND_EA_LIST) {
2017                 uint32 ea_size;
2018 
2019                 if (total_data < 4) {
2020                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2021                         return;
2022                 }
2023 
2024                 ea_size = IVAL(pdata,0);
2025                 if (ea_size != total_data) {
2026                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2029                         return;
2030                 }
2031 
2032                 if (!lp_ea_support(SNUM(conn))) {
2033                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2034                         return;
2035                 }
2036 
2037                 /* Pull out the list of names. */
2038                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2039                 if (!ea_list) {
2040                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041                         return;
2042                 }
2043         }
2044 
2045         *ppdata = (char *)SMB_REALLOC(
2046                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047         if(*ppdata == NULL ) {
2048                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049                 return;
2050         }
2051         pdata = *ppdata;
2052         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2053 
2054         /* Realloc the params space */
2055         *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056         if (*pparams == NULL) {
2057                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058                 return;
2059         }
2060         params = *pparams;
2061 
2062         /* Save the wildcard match and attribs we are using on this directory -
2063                 needed as lanman2 assumes these are being saved between calls */
2064 
2065         ntstatus = dptr_create(conn,
2066                                 directory,
2067                                 False,
2068                                 True,
2069                                 req->smbpid,
2070                                 mask,
2071                                 mask_contains_wcard,
2072                                 dirtype,
2073                                 &conn->dirptr);
2074 
2075         if (!NT_STATUS_IS_OK(ntstatus)) {
2076                 reply_nterror(req, ntstatus);
2077                 return;
2078         }
2079 
2080         dptr_num = dptr_dnum(conn->dirptr);
2081         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2082 
2083         /* Initialize per TRANS2_FIND_FIRST operation data */
2084         dptr_init_search_op(conn->dirptr);
2085 
2086         /* We don't need to check for VOL here as this is returned by
2087                 a different TRANS2 call. */
2088 
2089         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2090         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2091                 dont_descend = True;
2092 
2093         p = pdata;
2094         space_remaining = max_data_bytes;
2095         out_of_space = False;
2096 
2097         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2098                 bool got_exact_match = False;
2099 
2100                 /* this is a heuristic to avoid seeking the dirptr except when
2101                         absolutely necessary. It allows for a filename of about 40 chars */
2102                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2103                         out_of_space = True;
2104                         finished = False;
2105                 } else {
2106                         finished = !get_lanman2_dir_entry(ctx,
2107                                         conn,
2108                                         req->flags2,
2109                                         mask,dirtype,info_level,
2110                                         requires_resume_key,dont_descend,
2111                                         ask_sharemode,
2112                                         &p,pdata,data_end,
2113                                         space_remaining, &out_of_space,
2114                                         &got_exact_match,
2115                                         &last_entry_off, ea_list);
2116                 }
2117 
2118                 if (finished && out_of_space)
2119                         finished = False;
2120 
2121                 if (!finished && !out_of_space)
2122                         numentries++;
2123 
2124                 /*
2125                  * As an optimisation if we know we aren't looking
2126                  * for a wildcard name (ie. the name matches the wildcard exactly)
2127                  * then we can finish on any (first) match.
2128                  * This speeds up large directory searches. JRA.
2129                  */
2130 
2131                 if(got_exact_match)
2132                         finished = True;
2133 
2134                 /* Ensure space_remaining never goes -ve. */
2135                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2136                         space_remaining = 0;
2137                         out_of_space = true;
2138                 } else {
2139                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2140                 }
2141         }
2142 
2143         /* Check if we can close the dirptr */
2144         if(close_after_first || (finished && close_if_end)) {
2145                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2146                 dptr_close(&dptr_num);
2147         }
2148 
2149         /*
2150          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2151          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2152          * the protocol level is less than NT1. Tested with smbclient. JRA.
2153          * This should fix the OS/2 client bug #2335.
2154          */
2155 
2156         if(numentries == 0) {
2157                 dptr_close(&dptr_num);
2158                 if (Protocol < PROTOCOL_NT1) {
2159                         reply_doserror(req, ERRDOS, ERRnofiles);
2160                         return;
2161                 } else {
2162                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2163                                         ERRDOS, ERRbadfile);
2164                         return;
2165                 }
2166         }
2167 
2168         /* At this point pdata points to numentries directory entries. */
2169 
2170         /* Set up the return parameter block */
2171         SSVAL(params,0,dptr_num);
2172         SSVAL(params,2,numentries);
2173         SSVAL(params,4,finished);
2174         SSVAL(params,6,0); /* Never an EA error */
2175         SSVAL(params,8,last_entry_off);
2176 
2177         send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2178                             max_data_bytes);
2179 
2180         if ((! *directory) && dptr_path(dptr_num)) {
2181                 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2182                 if (!directory) {
2183                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2184                 }
2185         }
2186 
2187         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2188                 smb_fn_name(req->cmd),
2189                 mask, directory, dirtype, numentries ) );
2190 
2191         /*
2192          * Force a name mangle here to ensure that the
2193          * mask as an 8.3 name is top of the mangled cache.
2194          * The reasons for this are subtle. Don't remove
2195          * this code unless you know what you are doing
2196          * (see PR#13758). JRA.
2197          */
2198 
2199         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2200                 char mangled_name[13];
2201                 name_to_8_3(mask, mangled_name, True, conn->params);
2202         }
2203 
2204         return;
2205 }
2206 
2207 /****************************************************************************
2208  Reply to a TRANS2_FINDNEXT.
2209 ****************************************************************************/
2210 
2211 static void call_trans2findnext(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
2212                                 struct smb_request *req,
2213                                 char **pparams, int total_params,
2214                                 char **ppdata, int total_data,
2215                                 unsigned int max_data_bytes)
2216 {
2217         /* We must be careful here that we don't return more than the
2218                 allowed number of data bytes. If this means returning fewer than
2219                 maxentries then so be it. We assume that the redirector has
2220                 enough room for the fixed number of parameter bytes it has
2221                 requested. */
2222         char *params = *pparams;
2223         char *pdata = *ppdata;
2224         char *data_end;
2225         int dptr_num;
2226         int maxentries;
2227         uint16 info_level;
2228         uint32 resume_key;
2229         uint16 findnext_flags;
2230         bool close_after_request;
2231         bool close_if_end;
2232         bool requires_resume_key;
2233         bool continue_bit;
2234         bool mask_contains_wcard = False;
2235         char *resume_name = NULL;
2236         const char *mask = NULL;
2237         const char *directory = NULL;
2238         char *p = NULL;
2239         uint16 dirtype;
2240         int numentries = 0;
2241         int i, last_entry_off=0;
2242         bool finished = False;
2243         bool dont_descend = False;
2244         bool out_of_space = False;
2245         int space_remaining;
2246         struct ea_list *ea_list = NULL;
2247         NTSTATUS ntstatus = NT_STATUS_OK;
2248         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2249         TALLOC_CTX *ctx = talloc_tos();
2250 
2251         if (total_params < 13) {
2252                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253                 return;
2254         }
2255 
2256         dptr_num = SVAL(params,0);
2257         maxentries = SVAL(params,2);
2258         info_level = SVAL(params,4);
2259         resume_key = IVAL(params,6);
2260         findnext_flags = SVAL(params,10);
2261         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2262         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2263         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2264         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2265 
2266         srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2267                               params+12,
2268                               total_params - 12, STR_TERMINATE, &ntstatus,
2269                               &mask_contains_wcard);
2270         if (!NT_STATUS_IS_OK(ntstatus)) {
2271                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2272                    complain (it thinks we're asking for the directory above the shared
2273                    path or an invalid name). Catch this as the resume name is only compared, never used in
2274                    a file access. JRA. */
2275                 srvstr_pull_talloc(ctx, params, req->flags2,
2276                                 &resume_name, params+12,
2277                                 total_params - 12,
2278                                 STR_TERMINATE);
2279 
2280                 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2281                         reply_nterror(req, ntstatus);
2282                         return;
2283                 }
2284         }
2285 
2286         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2288 resume_key = %d resume name = %s continue=%d level = %d\n",
2289                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2290                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2291 
2292         if (!maxentries) {
2293                 /* W2K3 seems to treat zero as 1. */
2294                 maxentries = 1;
2295         }
2296 
2297         switch (info_level) {
2298                 case SMB_FIND_INFO_STANDARD:
2299                 case SMB_FIND_EA_SIZE:
2300                 case SMB_FIND_EA_LIST:
2301                 case SMB_FIND_FILE_DIRECTORY_INFO:
2302                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303                 case SMB_FIND_FILE_NAMES_INFO:
2304                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307                         break;
2308                 case SMB_FIND_FILE_UNIX:
2309                 case SMB_FIND_FILE_UNIX_INFO2:
2310                         /* Always use filesystem for UNIX mtime query. */
2311                         ask_sharemode = false;
2312                         if (!lp_unix_extensions()) {
2313                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314                                 return;
2315                         }
2316                         break;
2317                 default:
2318                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319                         return;
2320         }
2321 
2322         if (info_level == SMB_FIND_EA_LIST) {
2323                 uint32 ea_size;
2324 
2325                 if (total_data < 4) {
2326                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2327                         return;
2328                 }
2329 
2330                 ea_size = IVAL(pdata,0);
2331                 if (ea_size != total_data) {
2332                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2334                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335                         return;
2336                 }
2337 
2338                 if (!lp_ea_support(SNUM(conn))) {
2339                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2340                         return;
2341                 }
2342 
2343                 /* Pull out the list of names. */
2344                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2345                 if (!ea_list) {
2346                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347                         return;
2348                 }
2349         }
2350 
2351         *ppdata = (char *)SMB_REALLOC(
2352                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2353         if(*ppdata == NULL) {
2354                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355                 return;
2356         }
2357 
2358         pdata = *ppdata;
2359         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2360 
2361         /* Realloc the params space */
2362         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2363         if(*pparams == NULL ) {
2364                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365                 return;
2366         }
2367 
2368         params = *pparams;
2369 
2370         /* Check that the dptr is valid */
2371         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2372                 reply_doserror(req, ERRDOS, ERRnofiles);
2373                 return;
2374         }
2375 
2376         string_set(&conn->dirpath,dptr_path(dptr_num));
2377 
2378         /* Get the wildcard mask from the dptr */
2379         if((p = dptr_wcard(dptr_num))== NULL) {
2380                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2381                 reply_doserror(req, ERRDOS, ERRnofiles);
2382                 return;
2383         }
2384 
2385         mask = p;
2386         directory = conn->dirpath;
2387 
2388         /* Get the attr mask from the dptr */
2389         dirtype = dptr_attr(dptr_num);
2390 
2391         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392                 dptr_num, mask, dirtype,
2393                 (long)conn->dirptr,
2394                 dptr_TellDir(conn->dirptr)));
2395 
2396         /* Initialize per TRANS2_FIND_NEXT operation data */
2397         dptr_init_search_op(conn->dirptr);
2398 
2399         /* We don't need to check for VOL here as this is returned by
2400                 a different TRANS2 call. */
2401 
2402         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2403         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2404                 dont_descend = True;
2405 
2406         p = pdata;
2407         space_remaining = max_data_bytes;
2408         out_of_space = False;
2409 
2410         /*
2411          * Seek to the correct position. We no longer use the resume key but
2412          * depend on the last file name instead.
2413          */
2414 
2415         if(*resume_name && !continue_bit) {
2416                 SMB_STRUCT_STAT st;
2417 
2418                 long current_pos = 0;
2419                 /*
2420                  * Remember, name_to_8_3 is called by
2421                  * get_lanman2_dir_entry(), so the resume name
2422                  * could be mangled. Ensure we check the unmangled name.
2423                  */
2424 
2425                 if (mangle_is_mangled(resume_name, conn->params)) {
2426                         char *new_resume_name = NULL;
2427                         mangle_lookup_name_from_8_3(ctx,
2428                                                 resume_name,
2429                                                 &new_resume_name,
2430                                                 conn->params);
2431                         if (new_resume_name) {
2432                                 resume_name = new_resume_name;
2433                         }
2434                 }
2435 
2436                 /*
2437                  * Fix for NT redirector problem triggered by resume key indexes
2438                  * changing between directory scans. We now return a resume key of 0
2439                  * and instead look for the filename to continue from (also given
2440                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2441                  * findfirst/findnext (as is usual) then the directory pointer
2442                  * should already be at the correct place.
2443                  */
2444 
2445                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2446         } /* end if resume_name && !continue_bit */
2447 
2448         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2449                 bool got_exact_match = False;
2450 
2451                 /* this is a heuristic to avoid seeking the dirptr except when 
2452                         absolutely necessary. It allows for a filename of about 40 chars */
2453                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454                         out_of_space = True;
2455                         finished = False;
2456                 } else {
2457                         finished = !get_lanman2_dir_entry(ctx,
2458                                                 conn,
2459                                                 req->flags2,
2460                                                 mask,dirtype,info_level,
2461                                                 requires_resume_key,dont_descend,
2462                                                 ask_sharemode,
2463                                                 &p,pdata,data_end,
2464                                                 space_remaining, &out_of_space,
2465                                                 &got_exact_match,
2466                                                 &last_entry_off, ea_list);
2467                 }
2468 
2469                 if (finished && out_of_space)
2470                         finished = False;
2471 
2472                 if (!finished && !out_of_space)
2473                         numentries++;
2474 
2475                 /*
2476                  * As an optimisation if we know we aren't looking
2477                  * for a wildcard name (ie. the name matches the wildcard exactly)
2478                  * then we can finish on any (first) match.
2479                  * This speeds up large directory searches. JRA.
2480                  */
2481 
2482                 if(got_exact_match)
2483                         finished = True;
2484 
2485                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2486         }
2487 
2488         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2489                 smb_fn_name(req->cmd),
2490                 mask, directory, dirtype, numentries ) );
2491 
2492         /* Check if we can close the dirptr */
2493         if(close_after_request || (finished && close_if_end)) {
2494                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2495                 dptr_close(&dptr_num); /* This frees up the saved mask */
2496         }
2497 
2498         /* Set up the return parameter block */
2499         SSVAL(params,0,numentries);
2500         SSVAL(params,2,finished);
2501         SSVAL(params,4,0); /* Never an EA error */
2502         SSVAL(params,6,last_entry_off);
2503 
2504         send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2505                             max_data_bytes);
2506 
2507         return;
2508 }
2509 
2510 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
     /* [<][>][^][v][top][bottom][index][help] */
2511 {
2512         E_md4hash(lp_servicename(SNUM(conn)),objid);
2513         return objid;
2514 }
2515 
2516 static void samba_extended_info_version(struct smb_extended_info *extended_info)
     /* [<][>][^][v][top][bottom][index][help] */
2517 {
2518         SMB_ASSERT(extended_info != NULL);
2519 
2520         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2521         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2522                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2523                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2524 #ifdef SAMBA_VERSION_REVISION
2525         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2526 #endif
2527         extended_info->samba_subversion = 0;
2528 #ifdef SAMBA_VERSION_RC_RELEASE
2529         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2530 #else
2531 #ifdef SAMBA_VERSION_PRE_RELEASE
2532         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2533 #endif
2534 #endif
2535 #ifdef SAMBA_VERSION_VENDOR_PATCH
2536         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2537 #endif
2538         extended_info->samba_gitcommitdate = 0;
2539 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2540         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2541 #endif
2542 
2543         memset(extended_info->samba_version_string, 0,
2544                sizeof(extended_info->samba_version_string));
2545 
2546         snprintf (extended_info->samba_version_string,
2547                   sizeof(extended_info->samba_version_string),
2548                   "%s", samba_version_string());
2549 }
2550 
2551 /****************************************************************************
2552  Reply to a TRANS2_QFSINFO (query filesystem info).
2553 ****************************************************************************/
2554 
2555 static void call_trans2qfsinfo(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
2556                                struct smb_request *req,
2557                                char **pparams, int total_params,
2558                                char **ppdata, int total_data,
2559                                unsigned int max_data_bytes)
2560 {
2561         char *pdata, *end_data;
2562         char *params = *pparams;
2563         uint16 info_level;
2564         int data_len, len;
2565         SMB_STRUCT_STAT st;
2566         const char *vname = volume_label(SNUM(conn));
2567         int snum = SNUM(conn);
2568         char *fstype = lp_fstype(SNUM(conn));
2569         uint32 additional_flags = 0;
2570         
2571         if (total_params < 2) {
2572                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2573                 return;
2574         }
2575 
2576         info_level = SVAL(params,0);
2577 
2578         if (IS_IPC(conn)) {
2579                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580                         DEBUG(0,("call_trans2qfsinfo: not an allowed "
2581                                 "info level (0x%x) on IPC$.\n",
2582                                 (unsigned int)info_level));
2583                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2584                         return;
2585                 }
2586         }
2587 
2588         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2589                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2590                         DEBUG(0,("call_trans2qfsinfo: encryption required "
2591                                 "and info level 0x%x sent.\n",
2592                                 (unsigned int)info_level));
2593                         exit_server_cleanly("encryption required "
2594                                 "on connection");
2595                         return;
2596                 }
2597         }
2598 
2599         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2600 
2601         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2602                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2603                 reply_doserror(req, ERRSRV, ERRinvdevice);
2604                 return;
2605         }
2606 
2607         *ppdata = (char *)SMB_REALLOC(
2608                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609         if (*ppdata == NULL ) {
2610                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2611                 return;
2612         }
2613 
2614         pdata = *ppdata;
2615         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2616         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2617 
2618         switch (info_level) {
2619                 case SMB_INFO_ALLOCATION:
2620                 {
2621                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2622                         data_len = 18;
2623                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2624                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2625                                 return;
2626                         }
2627 
2628                         block_size = lp_block_size(snum);
2629                         if (bsize < block_size) {
2630                                 uint64_t factor = block_size/bsize;
2631                                 bsize = block_size;
2632                                 dsize /= factor;
2633                                 dfree /= factor;
2634                         }
2635                         if (bsize > block_size) {
2636                                 uint64_t factor = bsize/block_size;
2637                                 bsize = block_size;
2638                                 dsize *= factor;
2639                                 dfree *= factor;
2640                         }
2641                         bytes_per_sector = 512;
2642                         sectors_per_unit = bsize/bytes_per_sector;
2643 
2644                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2645 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2646                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2647 
2648                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2649                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2650                         SIVAL(pdata,l1_cUnit,dsize);
2651                         SIVAL(pdata,l1_cUnitAvail,dfree);
2652                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2653                         break;
2654                 }
2655 
2656                 case SMB_INFO_VOLUME:
2657                         /* Return volume name */
2658                         /* 
2659                          * Add volume serial number - hash of a combination of
2660                          * the called hostname and the service name.
2661                          */
2662                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2663                         /*
2664                          * Win2k3 and previous mess this up by sending a name length
2665                          * one byte short. I believe only older clients (OS/2 Win9x) use
2666                          * this call so try fixing this by adding a terminating null to
2667                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2668                          */
2669                         len = srvstr_push(
2670                                 pdata, req->flags2,
2671                                 pdata+l2_vol_szVolLabel, vname,
2672                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2673                                 STR_NOALIGN|STR_TERMINATE);
2674                         SCVAL(pdata,l2_vol_cch,len);
2675                         data_len = l2_vol_szVolLabel + len;
2676                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2677                                 (unsigned)st.st_ctime, len, vname));
2678                         break;
2679 
2680                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2681                 case SMB_FS_ATTRIBUTE_INFORMATION:
2682 
2683                         additional_flags = 0;
2684 #if defined(HAVE_SYS_QUOTAS)
2685                         additional_flags |= FILE_VOLUME_QUOTAS;
2686 #endif
2687 
2688                         if(lp_nt_acl_support(SNUM(conn))) {
2689                                 additional_flags |= FILE_PERSISTENT_ACLS;
2690                         }
2691 
2692                         /* Capabilities are filled in at connection time through STATVFS call */
2693                         additional_flags |= conn->fs_capabilities;
2694                         additional_flags |= lp_parm_int(conn->params->service,
2695                                                         "share", "fake_fscaps",
2696                                                         0);
2697 
2698                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2699                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2700                                 additional_flags); /* FS ATTRIBUTES */
2701 
2702                         SIVAL(pdata,4,255); /* Max filename component length */
2703                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2704                                 and will think we can't do long filenames */
2705                         len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2706                                           PTR_DIFF(end_data, pdata+12),
2707                                           STR_UNICODE);
2708                         SIVAL(pdata,8,len);
2709                         data_len = 12 + len;
2710                         break;
2711 
2712                 case SMB_QUERY_FS_LABEL_INFO:
2713                 case SMB_FS_LABEL_INFORMATION:
2714                         len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2715                                           PTR_DIFF(end_data, pdata+4), 0);
2716                         data_len = 4 + len;
2717                         SIVAL(pdata,0,len);
2718                         break;
2719 
2720                 case SMB_QUERY_FS_VOLUME_INFO:      
2721                 case SMB_FS_VOLUME_INFORMATION:
2722 
2723                         /* 
2724                          * Add volume serial number - hash of a combination of
2725                          * the called hostname and the service name.
2726                          */
2727                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2728                                 (str_checksum(get_local_machine_name())<<16));
2729 
2730                         /* Max label len is 32 characters. */
2731                         len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2732                                           PTR_DIFF(end_data, pdata+18),
2733                                           STR_UNICODE);
2734                         SIVAL(pdata,12,len);
2735                         data_len = 18+len;
2736 
2737                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2738                                 (int)strlen(vname),vname, lp_servicename(snum)));
2739                         break;
2740 
2741                 case SMB_QUERY_FS_SIZE_INFO:
2742                 case SMB_FS_SIZE_INFORMATION:
2743                 {
2744                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2745                         data_len = 24;
2746                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2747                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2748                                 return;
2749                         }
2750                         block_size = lp_block_size(snum);
2751                         if (bsize < block_size) {
2752                                 uint64_t factor = block_size/bsize;
2753                                 bsize = block_size;
2754                                 dsize /= factor;
2755                                 dfree /= factor;
2756                         }
2757                         if (bsize > block_size) {
2758                                 uint64_t factor = bsize/block_size;
2759                                 bsize = block_size;
2760                                 dsize *= factor;
2761                                 dfree *= factor;
2762                         }
2763                         bytes_per_sector = 512;
2764                         sectors_per_unit = bsize/bytes_per_sector;
2765                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2766 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2767                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2768                         SBIG_UINT(pdata,0,dsize);
2769                         SBIG_UINT(pdata,8,dfree);
2770                         SIVAL(pdata,16,sectors_per_unit);
2771                         SIVAL(pdata,20,bytes_per_sector);
2772                         break;
2773                 }
2774 
2775                 case SMB_FS_FULL_SIZE_INFORMATION:
2776                 {
2777                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2778                         data_len = 32;
2779                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2780                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2781                                 return;
2782                         }
2783                         block_size = lp_block_size(snum);
2784                         if (bsize < block_size) {
2785                                 uint64_t factor = block_size/bsize;
2786                                 bsize = block_size;
2787                                 dsize /= factor;
2788                                 dfree /= factor;
2789                         }
2790                         if (bsize > block_size) {
2791                                 uint64_t factor = bsize/block_size;
2792                                 bsize = block_size;
2793                                 dsize *= factor;
2794                                 dfree *= factor;
2795                         }
2796                         bytes_per_sector = 512;
2797                         sectors_per_unit = bsize/bytes_per_sector;
2798                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2799 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2800                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2801                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2802                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2803                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2804                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2805                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2806                         break;
2807                 }
2808 
2809                 case SMB_QUERY_FS_DEVICE_INFO:
2810                 case SMB_FS_DEVICE_INFORMATION:
2811                         data_len = 8;
2812                         SIVAL(pdata,0,0); /* dev type */
2813                         SIVAL(pdata,4,0); /* characteristics */
2814                         break;
2815 
2816 #ifdef HAVE_SYS_QUOTAS
2817                 case SMB_FS_QUOTA_INFORMATION:
2818                 /* 
2819                  * what we have to send --metze:
2820                  *
2821                  * Unknown1:            24 NULL bytes
2822                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2823                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
2824                  * Quota Flags:         2 byte :
2825                  * Unknown3:            6 NULL bytes
2826                  *
2827                  * 48 bytes total
2828                  * 
2829                  * details for Quota Flags:
2830                  * 
2831                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2832                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2833                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2834                  * 0x0001 Enable Quotas: enable quota for this fs
2835                  *
2836                  */
2837                 {
2838                         /* we need to fake up a fsp here,
2839                          * because its not send in this call
2840                          */
2841                         files_struct fsp;
2842                         SMB_NTQUOTA_STRUCT quotas;
2843                         
2844                         ZERO_STRUCT(fsp);
2845                         ZERO_STRUCT(quotas);
2846                         
2847                         fsp.conn = conn;
2848                         fsp.fnum = -1;
2849                         
2850                         /* access check */
2851                         if (conn->server_info->utok.uid != 0) {
2852                                 DEBUG(0,("set_user_quota: access_denied "
2853                                          "service [%s] user [%s]\n",
2854                                          lp_servicename(SNUM(conn)),
2855                                          conn->server_info->unix_name));
2856                                 reply_doserror(req, ERRDOS, ERRnoaccess);
2857                                 return;
2858                         }
2859                         
2860                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2861                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2862                                 reply_doserror(req, ERRSRV, ERRerror);
2863                                 return;
2864                         }
2865 
2866                         data_len = 48;
2867 
2868                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2869                 
2870                         /* Unknown1 24 NULL bytes*/
2871                         SBIG_UINT(pdata,0,(uint64_t)0);
2872                         SBIG_UINT(pdata,8,(uint64_t)0);
2873                         SBIG_UINT(pdata,16,(uint64_t)0);
2874                 
2875                         /* Default Soft Quota 8 bytes */
2876                         SBIG_UINT(pdata,24,quotas.softlim);
2877 
2878                         /* Default Hard Quota 8 bytes */
2879                         SBIG_UINT(pdata,32,quotas.hardlim);
2880         
2881                         /* Quota flag 2 bytes */
2882                         SSVAL(pdata,40,quotas.qflags);
2883                 
2884                         /* Unknown3 6 NULL bytes */
2885                         SSVAL(pdata,42,0);
2886                         SIVAL(pdata,44,0);
2887                         
2888                         break;
2889                 }
2890 #endif /* HAVE_SYS_QUOTAS */
2891                 case SMB_FS_OBJECTID_INFORMATION:
2892                 {
2893                         unsigned char objid[16];
2894                         struct smb_extended_info extended_info;
2895                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2896                         samba_extended_info_version (&extended_info);
2897                         SIVAL(pdata,16,extended_info.samba_magic);
2898                         SIVAL(pdata,20,extended_info.samba_version);
2899                         SIVAL(pdata,24,extended_info.samba_subversion);
2900                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2901                         memcpy(pdata+36,extended_info.samba_version_string,28);
2902                         data_len = 64;
2903                         break;
2904                 }
2905 
2906                 /*
2907                  * Query the version and capabilities of the CIFS UNIX extensions
2908                  * in use.
2909                  */
2910 
2911                 case SMB_QUERY_CIFS_UNIX_INFO:
2912                 {
2913                         bool large_write = lp_min_receive_file_size() &&
2914                                                 !srv_is_signing_active();
2915                         bool large_read = !srv_is_signing_active();
2916                         int encrypt_caps = 0;
2917 
2918                         if (!lp_unix_extensions()) {
2919                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2920                                 return;
2921                         }
2922 
2923                         switch (conn->encrypt_level) {
2924                         case 0:
2925                                 encrypt_caps = 0;
2926                                 break;
2927                         case 1:
2928                         case Auto:
2929                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2930                                 break;
2931                         case Required:
2932                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2933                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2934                                 large_write = false;
2935                                 large_read = false;
2936                                 break;
2937                         }
2938 
2939                         data_len = 12;
2940                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2941                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2942 
2943                         /* We have POSIX ACLs, pathname, encryption, 
2944                          * large read/write, and locking capability. */
2945 
2946                         SBIG_UINT(pdata,4,((uint64_t)(
2947                                         CIFS_UNIX_POSIX_ACLS_CAP|
2948                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2949                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2950                                         CIFS_UNIX_EXTATTR_CAP|
2951                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2952                                         encrypt_caps|
2953                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2954                                         (large_write ?
2955                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2956                         break;
2957                 }
2958 
2959                 case SMB_QUERY_POSIX_FS_INFO:
2960                 {
2961                         int rc;
2962                         vfs_statvfs_struct svfs;
2963 
2964                         if (!lp_unix_extensions()) {
2965                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2966                                 return;
2967                         }
2968 
2969                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2970 
2971                         if (!rc) {
2972                                 data_len = 56;
2973                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2974                                 SIVAL(pdata,4,svfs.BlockSize);
2975                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2976                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2977                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2978                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2979                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2980                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2981                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2982 #ifdef EOPNOTSUPP
2983                         } else if (rc == EOPNOTSUPP) {
2984                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2985                                 return;
2986 #endif /* EOPNOTSUPP */
2987                         } else {
2988                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2989                                 reply_doserror(req, ERRSRV, ERRerror);
2990                                 return;
2991                         }
2992                         break;
2993                 }
2994 
2995                 case SMB_QUERY_POSIX_WHOAMI:
2996                 {
2997                         uint32_t flags = 0;
2998                         uint32_t sid_bytes;
2999                         int i;
3000 
3001                         if (!lp_unix_extensions()) {
3002                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003                                 return;
3004                         }
3005 
3006                         if (max_data_bytes < 40) {
3007                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3008                                 return;
3009                         }
3010 
3011                         /* We ARE guest if global_sid_Builtin_Guests is
3012                          * in our list of SIDs.
3013                          */
3014                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
3015                                                conn->server_info->ptok)) {
3016                                 flags |= SMB_WHOAMI_GUEST;
3017                         }
3018 
3019                         /* We are NOT guest if global_sid_Authenticated_Users
3020                          * is in our list of SIDs.
3021                          */
3022                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
3023                                                conn->server_info->ptok)) {
3024                                 flags &= ~SMB_WHOAMI_GUEST;
3025                         }
3026 
3027                         /* NOTE: 8 bytes for UID/GID, irrespective of native
3028                          * platform size. This matches
3029                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
3030                          */
3031                         data_len = 4 /* flags */
3032                             + 4 /* flag mask */
3033                             + 8 /* uid */
3034                             + 8 /* gid */
3035                             + 4 /* ngroups */
3036                             + 4 /* num_sids */
3037                             + 4 /* SID bytes */
3038                             + 4 /* pad/reserved */
3039                             + (conn->server_info->utok.ngroups * 8)
3040                                 /* groups list */
3041                             + (conn->server_info->ptok->num_sids *
3042                                     SID_MAX_SIZE)
3043                                 /* SID list */;
3044 
3045                         SIVAL(pdata, 0, flags);
3046                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3047                         SBIG_UINT(pdata, 8,
3048                                   (uint64_t)conn->server_info->utok.uid);
3049                         SBIG_UINT(pdata, 16,
3050                                   (uint64_t)conn->server_info->utok.gid);
3051 
3052 
3053                         if (data_len >= max_data_bytes) {
3054                                 /* Potential overflow, skip the GIDs and SIDs. */
3055 
3056                                 SIVAL(pdata, 24, 0); /* num_groups */
3057                                 SIVAL(pdata, 28, 0); /* num_sids */
3058                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3059                                 SIVAL(pdata, 36, 0); /* reserved */
3060 
3061                                 data_len = 40;
3062                                 break;
3063                         }
3064 
3065                         SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3066                         SIVAL(pdata, 28, conn->server_info->num_sids);
3067 
3068                         /* We walk the SID list twice, but this call is fairly
3069                          * infrequent, and I don't expect that it's performance
3070                          * sensitive -- jpeach
3071                          */
3072                         for (i = 0, sid_bytes = 0;
3073                              i < conn->server_info->ptok->num_sids; ++i) {
3074                                 sid_bytes += ndr_size_dom_sid(
3075                                         &conn->server_info->ptok->user_sids[i],
3076                                         NULL, 
3077                                         0);
3078                         }
3079 
3080                         /* SID list byte count */
3081                         SIVAL(pdata, 32, sid_bytes);
3082 
3083                         /* 4 bytes pad/reserved - must be zero */
3084                         SIVAL(pdata, 36, 0);
3085                         data_len = 40;
3086 
3087                         /* GID list */
3088                         for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3089                                 SBIG_UINT(pdata, data_len,
3090                                           (uint64_t)conn->server_info->utok.groups[i]);
3091                                 data_len += 8;
3092                         }
3093 
3094                         /* SID list */
3095                         for (i = 0;
3096                             i < conn->server_info->ptok->num_sids; ++i) {
3097                                 int sid_len = ndr_size_dom_sid(
3098                                         &conn->server_info->ptok->user_sids[i],
3099                                         NULL,
3100                                         0);
3101 
3102                                 sid_linearize(pdata + data_len, sid_len,
3103                                     &conn->server_info->ptok->user_sids[i]);
3104                                 data_len += sid_len;
3105                         }
3106 
3107                         break;
3108                 }
3109 
3110                 case SMB_MAC_QUERY_FS_INFO:
3111                         /*
3112                          * Thursby MAC extension... ONLY on NTFS filesystems
3113                          * once we do streams then we don't need this
3114                          */
3115                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3116                                 data_len = 88;
3117                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
3118                                 break;
3119                         }
3120                         /* drop through */
3121                 default:
3122                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3123                         return;
3124         }
3125 
3126 
3127         send_trans2_replies(conn, req, params, 0, pdata, data_len,
3128                             max_data_bytes);
3129 
3130         DEBUG( 4, ( "%s info_level = %d\n",
3131                     smb_fn_name(req->cmd), info_level) );
3132 
3133         return;
3134 }
3135 
3136 /****************************************************************************
3137  Reply to a TRANS2_SETFSINFO (set filesystem info).
3138 ****************************************************************************/
3139 
3140 static void call_trans2setfsinfo(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
3141                                  struct smb_request *req,
3142                                  char **pparams, int total_params,
3143                                  char **ppdata, int total_data,
3144                                  unsigned int max_data_bytes)
3145 {
3146         char *pdata = *ppdata;
3147         char *params = *pparams;
3148         uint16 info_level;
3149 
3150         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3151 
3152         /*  */
3153         if (total_params < 4) {
3154                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3155                         total_params));
3156                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157                 return;
3158         }
3159 
3160         info_level = SVAL(params,2);
3161 
3162         if (IS_IPC(conn)) {
3163                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3164                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
3165                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
3166                                 "info level (0x%x) on IPC$.\n",
3167                                 (unsigned int)info_level));
3168                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3169                         return;
3170                 }
3171         }
3172 
3173         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3174                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3175                         DEBUG(0,("call_trans2setfsinfo: encryption required "
3176                                 "and info level 0x%x sent.\n",
3177                                 (unsigned int)info_level));
3178                         exit_server_cleanly("encryption required "
3179                                 "on connection");
3180                         return;
3181                 }
3182         }
3183 
3184         switch(info_level) {
3185                 case SMB_SET_CIFS_UNIX_INFO:
3186                         {
3187                                 uint16 client_unix_major;
3188                                 uint16 client_unix_minor;
3189                                 uint32 client_unix_cap_low;
3190                                 uint32 client_unix_cap_high;
3191 
3192                                 if (!lp_unix_extensions()) {
3193                                         reply_nterror(req,
3194                                                       NT_STATUS_INVALID_LEVEL);
3195                                         return;
3196                                 }
3197 
3198                                 /* There should be 12 bytes of capabilities set. */
3199                                 if (total_data < 8) {
3200                                         reply_nterror(
3201                                                 req,
3202                                                 NT_STATUS_INVALID_PARAMETER);
3203                                         return;
3204                                 }
3205                                 client_unix_major = SVAL(pdata,0);
3206                                 client_unix_minor = SVAL(pdata,2);
3207                                 client_unix_cap_low = IVAL(pdata,4);
3208                                 client_unix_cap_high = IVAL(pdata,8);
3209                                 /* Just print these values for now. */
3210                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3211 cap_low = 0x%x, cap_high = 0x%x\n",
3212                                         (unsigned int)client_unix_major,
3213                                         (unsigned int)client_unix_minor,
3214                                         (unsigned int)client_unix_cap_low,
3215                                         (unsigned int)client_unix_cap_high ));
3216 
3217                                 /* Here is where we must switch to posix pathname processing... */
3218                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3219                                         lp_set_posix_pathnames();
3220                                         mangle_change_to_posix();
3221                                 }
3222 
3223                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3224                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3225                                         /* Client that knows how to do posix locks,
3226                                          * but not posix open/mkdir operations. Set a
3227                                          * default type for read/write checks. */
3228 
3229                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3230 
3231                                 }
3232                                 break;
3233                         }
3234 
3235                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3236                         {
3237                                 NTSTATUS status;
3238                                 size_t param_len = 0;
3239                                 size_t data_len = total_data;
3240 
3241                                 if (!lp_unix_extensions()) {
3242                                         reply_nterror(
3243                                                 req,
3244                                                 NT_STATUS_INVALID_LEVEL);
3245                                         return;
3246                                 }
3247 
3248                                 if (lp_smb_encrypt(SNUM(conn)) == false) {
3249                                         reply_nterror(
3250                                                 req,
3251                                                 NT_STATUS_NOT_SUPPORTED);
3252                                         return;
3253                                 }
3254 
3255                                 DEBUG( 4,("call_trans2setfsinfo: "
3256                                         "request transport encryption.\n"));
3257 
3258                                 status = srv_request_encryption_setup(conn,
3259                                                                 (unsigned char **)ppdata,
3260                                                                 &data_len,
3261                                                                 (unsigned char **)pparams,
3262                                                                 &param_len);
3263 
3264                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3265                                                 !NT_STATUS_IS_OK(status)) {
3266                                         reply_nterror(req, status);
3267                                         return;
3268                                 }
3269 
3270                                 send_trans2_replies(conn, req,
3271                                                 *pparams,
3272                                                 param_len,
3273                                                 *ppdata,
3274                                                 data_len,
3275                                                 max_data_bytes);
3276 
3277                                 if (NT_STATUS_IS_OK(status)) {
3278                                         /* Server-side transport
3279                                          * encryption is now *on*. */
3280                                         status = srv_encryption_start(conn);
3281                                         if (!NT_STATUS_IS_OK(status)) {
3282                                                 exit_server_cleanly(
3283                                                         "Failure in setting "
3284                                                         "up encrypted transport");
3285                                         }
3286                                 }
3287                                 return;
3288                         }
3289 
3290                 case SMB_FS_QUOTA_INFORMATION:
3291                         {
3292                                 files_struct *fsp = NULL;
3293                                 SMB_NTQUOTA_STRUCT quotas;
3294         
3295                                 ZERO_STRUCT(quotas);
3296 
3297                                 /* access check */
3298                                 if ((conn->server_info->utok.uid != 0)
3299                                     ||!CAN_WRITE(conn)) {
3300                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3301                                                  lp_servicename(SNUM(conn)),
3302                                                  conn->server_info->unix_name));
3303                                         reply_doserror(req, ERRSRV, ERRaccess);
3304                                         return;
3305                                 }
3306 
3307                                 /* note: normaly there're 48 bytes,
3308                                  * but we didn't use the last 6 bytes for now 
3309                                  * --metze 
3310                                  */
3311                                 fsp = file_fsp(req, SVAL(params,0));
3312 
3313                                 if (!check_fsp_ntquota_handle(conn, req,
3314                                                               fsp)) {
3315                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3316                                         reply_nterror(
3317                                                 req, NT_STATUS_INVALID_HANDLE);
3318                                         return;
3319                                 }
3320 
3321                                 if (total_data < 42) {
3322                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3323                                                 total_data));
3324                                         reply_nterror(
3325                                                 req,
3326                                                 NT_STATUS_INVALID_PARAMETER);
3327                                         return;
3328                                 }
3329                         
3330                                 /* unknown_1 24 NULL bytes in pdata*/
3331                 
3332                                 /* the soft quotas 8 bytes (uint64_t)*/
3333                                 quotas.softlim = (uint64_t)IVAL(pdata,24);
3334 #ifdef LARGE_SMB_OFF_T
3335                                 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3336 #else /* LARGE_SMB_OFF_T */
3337                                 if ((IVAL(pdata,28) != 0)&&
3338                                         ((quotas.softlim != 0xFFFFFFFF)||
3339                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3340                                         /* more than 32 bits? */
3341                                         reply_nterror(
3342                                                 req,
3343                                                 NT_STATUS_INVALID_PARAMETER);
3344                                         return;
3345                                 }
3346 #endif /* LARGE_SMB_OFF_T */
3347                 
3348                                 /* the hard quotas 8 bytes (uint64_t)*/
3349                                 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3350 #ifdef LARGE_SMB_OFF_T
3351                                 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3352 #else /* LARGE_SMB_OFF_T */
3353                                 if ((IVAL(pdata,36) != 0)&&
3354                                         ((quotas.hardlim != 0xFFFFFFFF)||
3355                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3356                                         /* more than 32 bits? */
3357                                         reply_nterror(
3358                                                 req,
3359                                                 NT_STATUS_INVALID_PARAMETER);
3360                                         return;
3361                                 }
3362 #endif /* LARGE_SMB_OFF_T */
3363                 
3364                                 /* quota_flags 2 bytes **/
3365                                 quotas.qflags = SVAL(pdata,40);
3366                 
3367                                 /* unknown_2 6 NULL bytes follow*/
3368                 
3369                                 /* now set the quotas */
3370                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3371                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3372                                         reply_doserror(req, ERRSRV, ERRerror);
3373                                         return;
3374                                 }
3375                         
3376                                 break;
3377                         }
3378                 default:
3379                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3380                                 info_level));
3381                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3382                         return;
3383                         break;
3384         }
3385 
3386         /* 
3387          * sending this reply works fine, 
3388          * but I'm not sure it's the same 
3389          * like windows do...
3390          * --metze
3391          */
3392         reply_outbuf(req, 10, 0);
3393 }
3394 
3395 #if defined(HAVE_POSIX_ACLS)
3396 /****************************************************************************
3397  Utility function to count the number of entries in a POSIX acl.
3398 ****************************************************************************/
3399 
3400 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
     /* [<][>][^][v][top][bottom][index][help] */
3401 {
3402         unsigned int ace_count = 0;
3403         int entry_id = SMB_ACL_FIRST_ENTRY;
3404         SMB_ACL_ENTRY_T entry;
3405 
3406         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3407                 /* get_next... */
3408                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3409                         entry_id = SMB_ACL_NEXT_ENTRY;
3410                 }
3411                 ace_count++;
3412         }
3413         return ace_count;
3414 }
3415 
3416 /****************************************************************************
3417  Utility function to marshall a POSIX acl into wire format.
3418 ****************************************************************************/
3419 
3420 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
     /* [<][>][^][v][top][bottom][index][help] */
3421 {
3422         int entry_id = SMB_ACL_FIRST_ENTRY;
3423         SMB_ACL_ENTRY_T entry;
3424 
3425         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3426                 SMB_ACL_TAG_T tagtype;
3427                 SMB_ACL_PERMSET_T permset;
3428                 unsigned char perms = 0;
3429                 unsigned int own_grp;
3430 
3431                 /* get_next... */
3432                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3433                         entry_id = SMB_ACL_NEXT_ENTRY;
3434                 }
3435 
3436                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3437                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3438                         return False;
3439                 }
3440 
3441                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3442                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3443                         return False;
3444                 }
3445 
3446                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3447                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3448                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3449 
3450                 SCVAL(pdata,1,perms);
3451 
3452                 switch (tagtype) {
3453                         case SMB_ACL_USER_OBJ:
3454                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3455                                 own_grp = (unsigned int)pst->st_uid;
3456                                 SIVAL(pdata,2,own_grp);
3457                                 SIVAL(pdata,6,0);
3458                                 break;
3459                         case SMB_ACL_USER:
3460                                 {
3461                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3462                                         if (!puid) {
3463                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3464                                                 return False;
3465                                         }
3466                                         own_grp = (unsigned int)*puid;
3467                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3468                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3469                                         SIVAL(pdata,2,own_grp);
3470                                         SIVAL(pdata,6,0);
3471                                         break;
3472                                 }
3473                         case SMB_ACL_GROUP_OBJ:
3474                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3475                                 own_grp = (unsigned int)pst->st_gid;
3476                                 SIVAL(pdata,2,own_grp);
3477                                 SIVAL(pdata,6,0);
3478                                 break;
3479                         case SMB_ACL_GROUP:
3480                                 {
3481                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3482                                         if (!pgid) {
3483                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3484                                                 return False;
3485                                         }
3486                                         own_grp = (unsigned int)*pgid;
3487                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3488                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3489                                         SIVAL(pdata,2,own_grp);
3490                                         SIVAL(pdata,6,0);
3491                                         break;
3492                                 }
3493                         case SMB_ACL_MASK:
3494                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3495                                 SIVAL(pdata,2,0xFFFFFFFF);
3496                                 SIVAL(pdata,6,0xFFFFFFFF);
3497                                 break;
3498                         case SMB_ACL_OTHER:
3499                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3500                                 SIVAL(pdata,2,0xFFFFFFFF);
3501                                 SIVAL(pdata,6,0xFFFFFFFF);
3502                                 break;
3503                         default:
3504                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3505                                 return False;
3506                 }
3507                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3508         }
3509 
3510         return True;
3511 }
3512 #endif
3513 
3514 /****************************************************************************
3515  Store the FILE_UNIX_BASIC info.
3516 ****************************************************************************/
3517 
3518 static char *store_file_unix_basic(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
3519                                 char *pdata,
3520                                 files_struct *fsp,
3521                                 const SMB_STRUCT_STAT *psbuf)
3522 {
3523         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3524         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3525 
3526         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
3527         pdata += 8;
3528 
3529         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3530         pdata += 8;
3531 
3532         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3533         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3534         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3535         pdata += 24;
3536 
3537         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3538         SIVAL(pdata,4,0);
3539         pdata += 8;
3540 
3541         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3542         SIVAL(pdata,4,0);
3543         pdata += 8;
3544 
3545         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3546         pdata += 4;
3547 
3548         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3549         SIVAL(pdata,4,0);
3550         pdata += 8;
3551 
3552         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3553         SIVAL(pdata,4,0);
3554         pdata += 8;
3555 
3556         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3557         pdata += 8;
3558                                 
3559         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3560         SIVAL(pdata,4,0);
3561         pdata += 8;
3562 
3563         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3564         SIVAL(pdata,4,0);
3565         pdata += 8;
3566 
3567         return pdata;
3568 }
3569 
3570 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3571  * the chflags(2) (or equivalent) flags.
3572  *
3573  * XXX: this really should be behind the VFS interface. To do this, we would
3574  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3575  * Each VFS module could then implement its own mapping as appropriate for the
3576  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3577  */
3578 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3579         info2_flags_map[] =
3580 {
3581 #ifdef UF_NODUMP
3582     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3583 #endif
3584 
3585 #ifdef UF_IMMUTABLE
3586     { UF_IMMUTABLE, EXT_IMMUTABLE },
3587 #endif
3588 
3589 #ifdef UF_APPEND
3590     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3591 #endif
3592 
3593 #ifdef UF_HIDDEN
3594     { UF_HIDDEN, EXT_HIDDEN },
3595 #endif
3596 
3597     /* Do not remove. We need to guarantee that this array has at least one
3598      * entry to build on HP-UX.
3599      */
3600     { 0, 0 }
3601 
3602 };
3603 
3604 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
     /* [<][>][^][v][top][bottom][index][help] */
3605                                 uint32 *smb_fflags, uint32 *smb_fmask)
3606 {
3607 #ifdef HAVE_STAT_ST_FLAGS
3608         int i;
3609 
3610         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3611             *smb_fmask |= info2_flags_map[i].smb_fflag;
3612             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3613                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3614             }
3615         }
3616 #endif /* HAVE_STAT_ST_FLAGS */
3617 }
3618 
3619 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
     /* [<][>][^][v][top][bottom][index][help] */
3620                                 const uint32 smb_fflags,
3621                                 const uint32 smb_fmask,
3622                                 int *stat_fflags)
3623 {
3624 #ifdef HAVE_STAT_ST_FLAGS
3625         uint32 max_fmask = 0;
3626         int i;
3627 
3628         *stat_fflags = psbuf->st_flags;
3629 
3630         /* For each flags requested in smb_fmask, check the state of the
3631          * corresponding flag in smb_fflags and set or clear the matching
3632          * stat flag.
3633          */
3634 
3635         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3636             max_fmask |= info2_flags_map[i].smb_fflag;
3637             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3638                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3639                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3640                     } else {
3641                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3642                     }
3643             }
3644         }
3645 
3646         /* If smb_fmask is asking to set any bits that are not supported by
3647          * our flag mappings, we should fail.
3648          */
3649         if ((smb_fmask & max_fmask) != smb_fmask) {
3650                 return False;
3651         }
3652 
3653         return True;
3654 #else
3655         return False;
3656 #endif /* HAVE_STAT_ST_FLAGS */
3657 }
3658 
3659 
3660 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3661  * of file flags and birth (create) time.
3662  */
3663 static char *store_file_unix_basic_info2(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
3664                                 char *pdata,
3665                                 files_struct *fsp,
3666                                 const SMB_STRUCT_STAT *psbuf)
3667 {
3668         uint32 file_flags = 0;
3669         uint32 flags_mask = 0;
3670 
3671         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3672 
3673         /* Create (birth) time 64 bit */
3674         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, get_create_timespec(psbuf, False));
3675         pdata += 8;
3676 
3677         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3678         SIVAL(pdata, 0, file_flags); /* flags */
3679         SIVAL(pdata, 4, flags_mask); /* mask */
3680         pdata += 8;
3681 
3682         return pdata;
3683 }
3684 
3685 static NTSTATUS marshall_stream_info(unsigned int num_streams,
     /* [<][>][^][v][top][bottom][index][help] */
3686                                      const struct stream_struct *streams,
3687                                      char *data,
3688                                      unsigned int max_data_bytes,
3689                                      unsigned int *data_size)
3690 {
3691         unsigned int i;
3692         unsigned int ofs = 0;
3693 
3694         for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3695                 unsigned int next_offset;
3696                 size_t namelen;
3697                 smb_ucs2_t *namebuf;
3698 
3699                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3700                                       streams[i].name, &namelen) ||
3701                     namelen <= 2)
3702                 {
3703                         return NT_STATUS_INVALID_PARAMETER;
3704                 }
3705 
3706                 /*
3707                  * name_buf is now null-terminated, we need to marshall as not
3708                  * terminated
3709                  */
3710 
3711                 namelen -= 2;
3712 
3713                 SIVAL(data, ofs+4, namelen);
3714                 SOFF_T(data, ofs+8, streams[i].size);
3715                 SOFF_T(data, ofs+16, streams[i].alloc_size);
3716                 memcpy(data+ofs+24, namebuf, namelen);
3717                 TALLOC_FREE(namebuf);
3718 
3719                 next_offset = ofs + 24 + namelen;
3720 
3721                 if (i == num_streams-1) {
3722                         SIVAL(data, ofs, 0);
3723                 }
3724                 else {
3725                         unsigned int align = ndr_align_size(next_offset, 8);
3726 
3727                         memset(data+next_offset, 0, align);
3728                         next_offset += align;
3729 
3730                         SIVAL(data, ofs, next_offset - ofs);
3731                         ofs = next_offset;
3732                 }
3733 
3734                 ofs = next_offset;
3735         }
3736 
3737         *data_size = ofs;
3738 
3739         return NT_STATUS_OK;
3740 }
3741 
3742 /****************************************************************************
3743  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3744 ****************************************************************************/
3745 
3746 static void call_trans2qpipeinfo(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
3747                                  struct smb_request *req,
3748                                  unsigned int tran_call,
3749                                  char **pparams, int total_params,
3750                                  char **ppdata, int total_data,
3751                                  unsigned int max_data_bytes)
3752 {
3753         char *params = *pparams;
3754         char *pdata = *ppdata;
3755         unsigned int data_size = 0;
3756         unsigned int param_size = 2;
3757         uint16 info_level;
3758         files_struct *fsp;
3759 
3760         if (!params) {
3761                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3762                 return;
3763         }
3764 
3765         if (total_params < 4) {
3766                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767                 return;
3768         }
3769 
3770         fsp = file_fsp(req, SVAL(params,0));
3771         if (!fsp_is_np(fsp)) {
3772                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3773                 return;
3774         }
3775 
3776         info_level = SVAL(params,2);
3777 
3778         *pparams = (char *)SMB_REALLOC(*pparams,2);
3779         if (*pparams == NULL) {
3780                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3781                 return;
3782         }
3783         params = *pparams;
3784         SSVAL(params,0,0);
3785         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3786         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3787         if (*ppdata == NULL ) {
3788                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3789                 return;
3790         }
3791         pdata = *ppdata;
3792 
3793         switch (info_level) {
3794                 case SMB_FILE_STANDARD_INFORMATION:
3795                         memset(pdata,0,24);
3796                         SOFF_T(pdata,0,4096LL);
3797                         SIVAL(pdata,16,1);
3798                         SIVAL(pdata,20,1);
3799                         data_size = 24;
3800                         break;
3801 
3802                 default:
3803                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3804                         return;
3805         }
3806 
3807         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3808                             max_data_bytes);
3809 
3810         return;
3811 }
3812 
3813 /****************************************************************************
3814  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3815  file name or file id).
3816 ****************************************************************************/
3817 
3818 static void call_trans2qfilepathinfo(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
3819                                      struct smb_request *req,
3820                                      unsigned int tran_call,
3821                                      char **pparams, int total_params,
3822                                      char **ppdata, int total_data,
3823                                      unsigned int max_data_bytes)
3824 {
3825         char *params = *pparams;
3826         char *pdata = *ppdata;
3827         char *dstart, *dend;
3828         uint16 info_level;
3829         int mode=0;
3830         int nlink;
3831         SMB_OFF_T file_size=0;
3832         uint64_t allocation_size=0;
3833         unsigned int data_size = 0;
3834         unsigned int param_size = 2;
3835         SMB_STRUCT_STAT sbuf;
3836         char *dos_fname = NULL;
3837         char *fname = NULL;
3838         char *fullpathname;
3839         char *base_name;
3840         char *p;
3841         SMB_OFF_T pos = 0;
3842         bool delete_pending = False;
3843         int len;
3844         time_t create_time, mtime, atime;
3845         struct timespec create_time_ts, mtime_ts, atime_ts;
3846         struct timespec write_time_ts;
3847         files_struct *fsp = NULL;
3848         struct file_id fileid;
3849         struct ea_list *ea_list = NULL;
3850         char *lock_data = NULL;
3851         bool ms_dfs_link = false;
3852         TALLOC_CTX *ctx = talloc_tos();
3853 
3854         if (!params) {
3855                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3856                 return;
3857         }
3858 
3859         ZERO_STRUCT(sbuf);
3860         ZERO_STRUCT(write_time_ts);
3861 
3862         if (tran_call == TRANSACT2_QFILEINFO) {
3863                 if (total_params < 4) {
3864                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3865                         return;
3866                 }
3867 
3868                 if (IS_IPC(conn)) {
3869                         call_trans2qpipeinfo(conn, req, tran_call,
3870                                              pparams, total_params,
3871                                              ppdata, total_data,
3872                                              max_data_bytes);
3873                         return;
3874                 }
3875 
3876                 fsp = file_fsp(req, SVAL(params,0));
3877                 info_level = SVAL(params,2);
3878 
3879                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3880 
3881                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3882                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3883                         return;
3884                 }
3885 
3886                 /* Initial check for valid fsp ptr. */
3887                 if (!check_fsp_open(conn, req, fsp)) {
3888                         return;
3889                 }
3890 
3891                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3892                 if (!fname) {
3893                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3894                         return;
3895                 }
3896 
3897                 if(fsp->fake_file_handle) {
3898                         /*
3899                          * This is actually for the QUOTA_FAKE_FILE --metze
3900                          */
3901 
3902                         /* We know this name is ok, it's already passed the checks. */
3903 
3904                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3905                         /*
3906                          * This is actually a QFILEINFO on a directory
3907                          * handle (returned from an NT SMB). NT5.0 seems
3908                          * to do this call. JRA.
3909                          */
3910 
3911                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3912                                 /* Always do lstat for UNIX calls. */
3913                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3914                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3915                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3916                                         return;
3917                                 }
3918                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3919                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3920                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3921                                 return;
3922                         }
3923 
3924                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3925                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3926                 } else {
3927                         /*
3928                          * Original code - this is an open file.
3929                          */
3930                         if (!check_fsp(conn, req, fsp)) {
3931                                 return;
3932                         }
3933 
3934                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3935                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3936                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3937                                 return;
3938                         }
3939                         pos = fsp->fh->position_information;
3940                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3941                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3942                 }
3943 
3944         } else {
3945                 NTSTATUS status = NT_STATUS_OK;
3946 
3947                 /* qpathinfo */
3948                 if (total_params < 7) {
3949                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3950                         return;
3951                 }
3952 
3953                 info_level = SVAL(params,0);
3954 
3955                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3956 
3957                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3958                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3959                         return;
3960                 }
3961 
3962                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3963                                 total_params - 6,
3964                                 STR_TERMINATE, &status);
3965                 if (!NT_STATUS_IS_OK(status)) {
3966                         reply_nterror(req, status);
3967                         return;
3968                 }
3969 
3970                 status = resolve_dfspath(ctx,
3971                                         conn,
3972                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3973                                         fname,
3974                                         &fname);
3975                 if (!NT_STATUS_IS_OK(status)) {
3976                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3977                                 reply_botherror(req,
3978                                                 NT_STATUS_PATH_NOT_COVERED,
3979                                                 ERRSRV, ERRbadpath);
3980                         }
3981                         reply_nterror(req, status);
3982                         return;
3983                 }
3984 
3985                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3986                 if (!NT_STATUS_IS_OK(status)) {
3987                         reply_nterror(req, status);
3988                         return;
3989                 }
3990                 status = check_name(conn, fname);
3991                 if (!NT_STATUS_IS_OK(status)) {
3992                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3993                         reply_nterror(req, status);
3994                         return;
3995                 }
3996 
3997                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3998                     && is_ntfs_stream_name(fname)) {
3999                         char *base;
4000                         SMB_STRUCT_STAT bsbuf;
4001 
4002                         status = split_ntfs_stream_name(talloc_tos(), fname,
4003                                                         &base, NULL);
4004                         if (!NT_STATUS_IS_OK(status)) {
4005                                 DEBUG(10, ("create_file_unixpath: "
4006                                         "split_ntfs_stream_name failed: %s\n",
4007                                         nt_errstr(status)));
4008                                 reply_nterror(req, status);
4009                                 return;
4010                         }
4011 
4012                         SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4013 
4014                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4015                                 /* Always do lstat for UNIX calls. */
4016                                 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4017                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4018                                         reply_unixerror(req,ERRDOS,ERRbadpath);
4019                                         return;
4020                                 }
4021                         } else {
4022                                 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4023                                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4024                                         reply_unixerror(req,ERRDOS,ERRbadpath);
4025                                         return;
4026                                 }
4027                         }
4028 
4029                         fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4030                         get_file_infos(fileid, &delete_pending, NULL);
4031                         if (delete_pending) {
4032                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4033                                 return;
4034                         }
4035                 }
4036 
4037                 if (INFO_LEVEL_IS_UNIX(info_level)) {
4038                         /* Always do lstat for UNIX calls. */
4039                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4040                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4041                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4042                                 return;
4043                         }
4044 
4045                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4046                         ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4047 
4048                         if (!ms_dfs_link) {
4049                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4050                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4051                                 return;
4052                         }
4053                 }
4054 
4055                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4056                 get_file_infos(fileid, &delete_pending, &write_time_ts);
4057                 if (delete_pending) {
4058                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
4059                         return;
4060                 }
4061         }
4062 
4063         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4064                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4065                 return;
4066         }
4067 
4068         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4069                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4070 
4071         p = strrchr_m(fname,'/');
4072         if (!p)
4073                 base_name = fname;
4074         else
4075                 base_name = p+1;
4076 
4077         if (ms_dfs_link) {
4078                 mode = dos_mode_msdfs(conn,fname,&sbuf);
4079         } else {
4080                 mode = dos_mode(conn,fname,&sbuf);
4081         }
4082         if (!mode)
4083                 mode = FILE_ATTRIBUTE_NORMAL;
4084 
4085         nlink = sbuf.st_nlink;
4086 
4087         if (nlink && (mode&aDIR)) {
4088                 nlink = 1;
4089         }
4090 
4091         if ((nlink > 0) && delete_pending) {
4092                 nlink -= 1;
4093         }
4094 
4095         fullpathname = fname;
4096         if (!(mode & aDIR))
4097                 file_size = get_file_size_stat(&sbuf);
4098 
4099         /* Pull out any data sent here before we realloc. */
4100         switch (info_level) {
4101                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4102                 {
4103                         /* Pull any EA list from the data portion. */
4104                         uint32 ea_size;
4105 
4106                         if (total_data < 4) {
4107                                 reply_nterror(
4108                                         req, NT_STATUS_INVALID_PARAMETER);
4109                                 return;
4110                         }
4111                         ea_size = IVAL(pdata,0);
4112 
4113                         if (total_data > 0 && ea_size != total_data) {
4114                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4115 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4116                                 reply_nterror(
4117                                         req, NT_STATUS_INVALID_PARAMETER);
4118                                 return;
4119                         }
4120 
4121                         if (!lp_ea_support(SNUM(conn))) {
4122                                 reply_doserror(req, ERRDOS,
4123                                                ERReasnotsupported);
4124                                 return;
4125                         }
4126 
4127                         /* Pull out the list of names. */
4128                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4129                         if (!ea_list) {
4130                                 reply_nterror(
4131                                         req, NT_STATUS_INVALID_PARAMETER);
4132                                 return;
4133                         }
4134                         break;
4135                 }
4136 
4137                 case SMB_QUERY_POSIX_LOCK:
4138                 {
4139                         if (fsp == NULL || fsp->fh->fd == -1) {
4140                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4141                                 return;
4142                         }
4143 
4144                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4145                                 reply_nterror(
4146                                         req, NT_STATUS_INVALID_PARAMETER);
4147                                 return;
4148                         }
4149 
4150                         /* Copy the lock range data. */
4151                         lock_data = (char *)TALLOC_MEMDUP(
4152                                 ctx, pdata, total_data);
4153                         if (!lock_data) {
4154                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4155                                 return;
4156                         }
4157                 }
4158                 default:
4159                         break;
4160         }
4161 
4162         *pparams = (char *)SMB_REALLOC(*pparams,2);
4163         if (*pparams == NULL) {
4164                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165                 return;
4166         }
4167         params = *pparams;
4168         SSVAL(params,0,0);
4169         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4170         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4171         if (*ppdata == NULL ) {
4172                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4173                 return;
4174         }
4175         pdata = *ppdata;
4176         dstart = pdata;
4177         dend = dstart + data_size - 1;
4178 
4179         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4180         mtime_ts = get_mtimespec(&sbuf);
4181         atime_ts = get_atimespec(&sbuf);
4182 
4183         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4184 
4185         if (!fsp) {
4186                 /* Do we have this path open ? */
4187                 files_struct *fsp1;
4188                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4189                 fsp1 = file_find_di_first(fileid);
4190                 if (fsp1 && fsp1->initial_allocation_size) {
4191                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4192                 }
4193         }
4194 
4195         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4196                 mtime_ts = write_time_ts;
4197         }
4198 
4199         if (lp_dos_filetime_resolution(SNUM(conn))) {
4200                 dos_filetime_timespec(&create_time_ts);
4201                 dos_filetime_timespec(&mtime_ts);
4202                 dos_filetime_timespec(&atime_ts);
4203         }
4204 
4205         create_time = convert_timespec_to_time_t(create_time_ts);
4206         mtime = convert_timespec_to_time_t(mtime_ts);
4207         atime = convert_timespec_to_time_t(atime_ts);
4208 
4209         /* NT expects the name to be in an exact form of the *full*
4210            filename. See the trans2 torture test */
4211         if (ISDOT(base_name)) {
4212                 dos_fname = talloc_strdup(ctx, "\\");
4213                 if (!dos_fname) {
4214                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4215                         return;
4216                 }
4217         } else {
4218                 dos_fname = talloc_asprintf(ctx,
4219                                 "\\%s",
4220                                 fname);
4221                 if (!dos_fname) {
4222                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4223                         return;
4224                 }
4225                 string_replace(dos_fname, '/', '\\');
4226         }
4227 
4228         switch (info_level) {
4229                 case SMB_INFO_STANDARD:
4230                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4231                         data_size = 22;
4232                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4233                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4234                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4235                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4236                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4237                         SSVAL(pdata,l1_attrFile,mode);
4238                         break;
4239 
4240                 case SMB_INFO_QUERY_EA_SIZE:
4241                 {
4242                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4243                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4244                         data_size = 26;
4245                         srv_put_dos_date2(pdata,0,create_time);
4246                         srv_put_dos_date2(pdata,4,atime);
4247                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4248                         SIVAL(pdata,12,(uint32)file_size);
4249                         SIVAL(pdata,16,(uint32)allocation_size);
4250                         SSVAL(pdata,20,mode);
4251                         SIVAL(pdata,22,ea_size);
4252                         break;
4253                 }
4254 
4255                 case SMB_INFO_IS_NAME_VALID:
4256                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4257                         if (tran_call == TRANSACT2_QFILEINFO) {
4258                                 /* os/2 needs this ? really ?*/
4259                                 reply_doserror(req, ERRDOS, ERRbadfunc);
4260                                 return;
4261                         }
4262                         data_size = 0;
4263                         param_size = 0;
4264                         break;
4265 
4266                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4267                 {
4268                         size_t total_ea_len = 0;
4269                         struct ea_list *ea_file_list = NULL;
4270 
4271                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4272 
4273                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4274                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4275 
4276                         if (!ea_list || (total_ea_len > data_size)) {
4277                                 data_size = 4;
4278                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4279                                 break;
4280                         }
4281 
4282                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4283                         break;
4284                 }
4285 
4286                 case SMB_INFO_QUERY_ALL_EAS:
4287                 {
4288                         /* We have data_size bytes to put EA's into. */
4289                         size_t total_ea_len = 0;
4290 
4291                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4292 
4293                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4294                         if (!ea_list || (total_ea_len > data_size)) {
4295                                 data_size = 4;
4296                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4297                                 break;
4298                         }
4299 
4300                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4301                         break;
4302                 }
4303 
4304                 case SMB_FILE_BASIC_INFORMATION:
4305                 case SMB_QUERY_FILE_BASIC_INFO:
4306 
4307                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4308                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4309                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4310                         } else {
4311                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4312                                 data_size = 40;
4313                                 SIVAL(pdata,36,0);
4314                         }
4315                         put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4316                         put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4317                         put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4318                         put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4319                         SIVAL(pdata,32,mode);
4320 
4321                         DEBUG(5,("SMB_QFBI - "));
4322                         DEBUG(5,("create: %s ", ctime(&create_time)));
4323                         DEBUG(5,("access: %s ", ctime(&atime)));
4324                         DEBUG(5,("write: %s ", ctime(&mtime)));
4325                         DEBUG(5,("change: %s ", ctime(&mtime)));
4326                         DEBUG(5,("mode: %x\n", mode));
4327                         break;
4328 
4329                 case SMB_FILE_STANDARD_INFORMATION:
4330                 case SMB_QUERY_FILE_STANDARD_INFO:
4331 
4332                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4333                         data_size = 24;
4334                         SOFF_T(pdata,0,allocation_size);
4335                         SOFF_T(pdata,8,file_size);
4336                         SIVAL(pdata,16,nlink);
4337                         SCVAL(pdata,20,delete_pending?1:0);
4338                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4339                         SSVAL(pdata,22,0); /* Padding. */
4340                         break;
4341 
4342                 case SMB_FILE_EA_INFORMATION:
4343                 case SMB_QUERY_FILE_EA_INFO:
4344                 {
4345                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4346                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4347                         data_size = 4;
4348                         SIVAL(pdata,0,ea_size);
4349                         break;
4350                 }
4351 
4352                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4353                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4354                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4355                 {
4356                         char mangled_name[13];
4357                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4358                         if (!name_to_8_3(base_name,mangled_name,
4359                                                 True,conn->params)) {
4360                                 reply_nterror(
4361                                         req,
4362                                         NT_STATUS_NO_MEMORY);
4363                         }
4364                         len = srvstr_push(dstart, req->flags2,
4365                                           pdata+4, mangled_name,
4366                                           PTR_DIFF(dend, pdata+4),
4367                                           STR_UNICODE);
4368                         data_size = 4 + len;
4369                         SIVAL(pdata,0,len);
4370                         break;
4371                 }
4372 
4373                 case SMB_QUERY_FILE_NAME_INFO:
4374                         /*
4375                           this must be *exactly* right for ACLs on mapped drives to work
4376                          */
4377                         len = srvstr_push(dstart, req->flags2,
4378                                           pdata+4, dos_fname,
4379                                           PTR_DIFF(dend, pdata+4),
4380                                           STR_UNICODE);
4381                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4382                         data_size = 4 + len;
4383                         SIVAL(pdata,0,len);
4384                         break;
4385 
4386                 case SMB_FILE_ALLOCATION_INFORMATION:
4387                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4388                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4389                         data_size = 8;
4390                         SOFF_T(pdata,0,allocation_size);
4391                         break;
4392 
4393                 case SMB_FILE_END_OF_FILE_INFORMATION:
4394                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4395                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4396                         data_size = 8;
4397                         SOFF_T(pdata,0,file_size);
4398                         break;
4399 
4400                 case SMB_QUERY_FILE_ALL_INFO:
4401                 case SMB_FILE_ALL_INFORMATION:
4402                 {
4403                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4404                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4405                         put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4406                         put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4407                         put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4408                         put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4409                         SIVAL(pdata,32,mode);
4410                         SIVAL(pdata,36,0); /* padding. */
4411                         pdata += 40;
4412                         SOFF_T(pdata,0,allocation_size);
4413                         SOFF_T(pdata,8,file_size);
4414                         SIVAL(pdata,16,nlink);
4415                         SCVAL(pdata,20,delete_pending);
4416                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4417                         SSVAL(pdata,22,0);
4418                         pdata += 24;
4419                         SIVAL(pdata,0,ea_size);
4420                         pdata += 4; /* EA info */
4421                         len = srvstr_push(dstart, req->flags2,
4422                                           pdata+4, dos_fname,
4423                                           PTR_DIFF(dend, pdata+4),
4424                                           STR_UNICODE);
4425                         SIVAL(pdata,0,len);
4426                         pdata += 4 + len;
4427                         data_size = PTR_DIFF(pdata,(*ppdata));
4428                         break;
4429                 }
4430                 case SMB_FILE_INTERNAL_INFORMATION:
4431                         /* This should be an index number - looks like
4432                            dev/ino to me :-) 
4433 
4434                            I think this causes us to fail the IFSKIT
4435                            BasicFileInformationTest. -tpot */
4436 
4437                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4438                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4439                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4440                         data_size = 8;
4441                         break;
4442 
4443                 case SMB_FILE_ACCESS_INFORMATION:
4444                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4445                         if (fsp) {
4446                                 SIVAL(pdata,0,fsp->access_mask);
4447                         } else {
4448                                 /* GENERIC_EXECUTE mapping from Windows */
4449                                 SIVAL(pdata,0,0x12019F);
4450                         }
4451                         data_size = 4;
4452                         break;
4453 
4454                 case SMB_FILE_NAME_INFORMATION:
4455                         /* Pathname with leading '\'. */
4456                         {
4457                                 size_t byte_len;
4458                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4459                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4460                                 SIVAL(pdata,0,byte_len);
4461                                 data_size = 4 + byte_len;
4462                                 break;
4463                         }
4464 
4465                 case SMB_FILE_DISPOSITION_INFORMATION:
4466                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4467                         data_size = 1;
4468                         SCVAL(pdata,0,delete_pending);
4469                         break;
4470 
4471                 case SMB_FILE_POSITION_INFORMATION:
4472                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4473                         data_size = 8;
4474                         SOFF_T(pdata,0,pos);
4475                         break;
4476 
4477                 case SMB_FILE_MODE_INFORMATION:
4478                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4479                         SIVAL(pdata,0,mode);
4480                         data_size = 4;
4481                         break;
4482 
4483                 case SMB_FILE_ALIGNMENT_INFORMATION:
4484                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4485                         SIVAL(pdata,0,0); /* No alignment needed. */
4486                         data_size = 4;
4487                         break;
4488 
4489                 /*
4490                  * NT4 server just returns "invalid query" to this - if we try
4491                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4492                  * want this. JRA.
4493                  */
4494                 /* The first statement above is false - verified using Thursby
4495                  * client against NT4 -- gcolley.
4496                  */
4497                 case SMB_QUERY_FILE_STREAM_INFO:
4498                 case SMB_FILE_STREAM_INFORMATION: {
4499                         unsigned int num_streams;
4500                         struct stream_struct *streams;
4501                         NTSTATUS status;
4502 
4503                         DEBUG(10,("call_trans2qfilepathinfo: "
4504                                   "SMB_FILE_STREAM_INFORMATION\n"));
4505 
4506                         status = SMB_VFS_STREAMINFO(
4507                                 conn, fsp, fname, talloc_tos(),
4508                                 &num_streams, &streams);
4509 
4510                         if (!NT_STATUS_IS_OK(status)) {
4511                                 DEBUG(10, ("could not get stream info: %s\n",
4512                                            nt_errstr(status)));
4513                                 reply_nterror(req, status);
4514                                 return;
4515                         }
4516 
4517                         status = marshall_stream_info(num_streams, streams,
4518                                                       pdata, max_data_bytes,
4519                                                       &data_size);
4520 
4521                         if (!NT_STATUS_IS_OK(status)) {
4522                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4523                                            nt_errstr(status)));
4524                                 reply_nterror(req, status);
4525                                 return;
4526                         }
4527 
4528                         TALLOC_FREE(streams);
4529 
4530                         break;
4531                 }
4532                 case SMB_QUERY_COMPRESSION_INFO:
4533                 case SMB_FILE_COMPRESSION_INFORMATION:
4534                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4535                         SOFF_T(pdata,0,file_size);
4536                         SIVAL(pdata,8,0); /* ??? */
4537                         SIVAL(pdata,12,0); /* ??? */
4538                         data_size = 16;
4539                         break;
4540 
4541                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4542                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4543                         put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4544                         put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4545                         put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4546                         put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4547                         SOFF_T(pdata,32,allocation_size);
4548                         SOFF_T(pdata,40,file_size);
4549                         SIVAL(pdata,48,mode);
4550                         SIVAL(pdata,52,0); /* ??? */
4551                         data_size = 56;
4552                         break;
4553 
4554                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4555                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4556                         SIVAL(pdata,0,mode);
4557                         SIVAL(pdata,4,0);
4558                         data_size = 8;
4559                         break;
4560 
4561                 /*
4562                  * CIFS UNIX Extensions.
4563                  */
4564 
4565                 case SMB_QUERY_FILE_UNIX_BASIC:
4566 
4567                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4568                         data_size = PTR_DIFF(pdata,(*ppdata));
4569 
4570                         {
4571                                 int i;
4572                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4573 
4574                                 for (i=0; i<100; i++)
4575                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4576                                 DEBUG(4,("\n"));
4577                         }
4578 
4579                         break;
4580 
4581                 case SMB_QUERY_FILE_UNIX_INFO2:
4582 
4583                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4584                         data_size = PTR_DIFF(pdata,(*ppdata));
4585 
4586                         {
4587                                 int i;
4588                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4589 
4590                                 for (i=0; i<100; i++)
4591                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4592                                 DEBUG(4,("\n"));
4593                         }
4594 
4595                         break;
4596 
4597                 case SMB_QUERY_FILE_UNIX_LINK:
4598                         {
4599                                 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4600 
4601                                 if (!buffer) {
4602                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4603                                         return;
4604                                 }
4605 
4606                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4607 #ifdef S_ISLNK
4608                                 if(!S_ISLNK(sbuf.st_mode)) {
4609                                         reply_unixerror(req, ERRSRV,
4610                                                         ERRbadlink);
4611                                         return;
4612                                 }
4613 #else
4614                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4615                                 return;
4616 #endif
4617                                 len = SMB_VFS_READLINK(conn,fullpathname,
4618                                                 buffer, PATH_MAX);
4619                                 if (len == -1) {
4620                                         reply_unixerror(req, ERRDOS,
4621                                                         ERRnoaccess);
4622                                         return;
4623                                 }
4624                                 buffer[len] = 0;
4625                                 len = srvstr_push(dstart, req->flags2,
4626                                                   pdata, buffer,
4627                                                   PTR_DIFF(dend, pdata),
4628                                                   STR_TERMINATE);
4629                                 pdata += len;
4630                                 data_size = PTR_DIFF(pdata,(*ppdata));
4631 
4632                                 break;
4633                         }
4634 
4635 #if defined(HAVE_POSIX_ACLS)
4636                 case SMB_QUERY_POSIX_ACL:
4637                         {
4638                                 SMB_ACL_T file_acl = NULL;
4639                                 SMB_ACL_T def_acl = NULL;
4640                                 uint16 num_file_acls = 0;
4641                                 uint16 num_def_acls = 0;
4642 
4643                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4644                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4645                                 } else {
4646                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4647                                 }
4648 
4649                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4650                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4651                                                 fname ));
4652                                         reply_nterror(
4653                                                 req,
4654                                                 NT_STATUS_NOT_IMPLEMENTED);
4655                                         return;
4656                                 }
4657 
4658                                 if (S_ISDIR(sbuf.st_mode)) {
4659                                         if (fsp && fsp->is_directory) {
4660                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4661                                         } else {
4662                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4663                                         }
4664                                         def_acl = free_empty_sys_acl(conn, def_acl);
4665                                 }
4666 
4667                                 num_file_acls = count_acl_entries(conn, file_acl);
4668                                 num_def_acls = count_acl_entries(conn, def_acl);
4669 
4670                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4671                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4672                                                 data_size,
4673                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4674                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4675                                         if (file_acl) {
4676                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4677                                         }
4678                                         if (def_acl) {
4679                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680                                         }
4681                                         reply_nterror(
4682                                                 req,
4683                                                 NT_STATUS_BUFFER_TOO_SMALL);
4684                                         return;
4685                                 }
4686 
4687                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4688                                 SSVAL(pdata,2,num_file_acls);
4689                                 SSVAL(pdata,4,num_def_acls);
4690                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4691                                         if (file_acl) {
4692                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4693                                         }
4694                                         if (def_acl) {
4695                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4696                                         }
4697                                         reply_nterror(
4698                                                 req, NT_STATUS_INTERNAL_ERROR);
4699                                         return;
4700                                 }
4701                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4702                                         if (file_acl) {
4703                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4704                                         }
4705                                         if (def_acl) {
4706                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707                                         }
4708                                         reply_nterror(
4709                                                 req,
4710                                                 NT_STATUS_INTERNAL_ERROR);
4711                                         return;
4712                                 }
4713 
4714                                 if (file_acl) {
4715                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4716                                 }
4717                                 if (def_acl) {
4718                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4719                                 }
4720                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4721                                 break;
4722                         }
4723 #endif
4724 
4725 
4726                 case SMB_QUERY_POSIX_LOCK:
4727                 {
4728                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4729                         uint64_t count;
4730                         uint64_t offset;
4731                         uint32 lock_pid;
4732                         enum brl_type lock_type;
4733 
4734                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4735                                 reply_nterror(
4736                                         req, NT_STATUS_INVALID_PARAMETER);
4737                                 return;
4738                         }
4739 
4740                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4741                                 case POSIX_LOCK_TYPE_READ:
4742                                         lock_type = READ_LOCK;
4743                                         break;
4744                                 case POSIX_LOCK_TYPE_WRITE:
4745                                         lock_type = WRITE_LOCK;
4746                                         break;
4747                                 case POSIX_LOCK_TYPE_UNLOCK:
4748                                 default:
4749                                         /* There's no point in asking for an unlock... */
4750                                         reply_nterror(
4751                                                 req,
4752                                                 NT_STATUS_INVALID_PARAMETER);
4753                                         return;
4754                         }
4755 
4756                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4757 #if defined(HAVE_LONGLONG)
4758                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4759                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4760                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4761                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4762 #else /* HAVE_LONGLONG */
4763                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4764                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4765 #endif /* HAVE_LONGLONG */
4766 
4767                         status = query_lock(fsp,
4768                                         &lock_pid,
4769                                         &count,
4770                                         &offset,
4771                                         &lock_type,
4772                                         POSIX_LOCK);
4773 
4774                         if (ERROR_WAS_LOCK_DENIED(status)) {
4775                                 /* Here we need to report who has it locked... */
4776                                 data_size = POSIX_LOCK_DATA_SIZE;
4777 
4778                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4779                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4780                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4781 #if defined(HAVE_LONGLONG)
4782                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4783                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4784                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4785                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4786 #else /* HAVE_LONGLONG */
4787                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4788                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4789 #endif /* HAVE_LONGLONG */
4790 
4791                         } else if (NT_STATUS_IS_OK(status)) {
4792                                 /* For success we just return a copy of what we sent
4793                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4794                                 data_size = POSIX_LOCK_DATA_SIZE;
4795                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4796                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4797                         } else {
4798                                 reply_nterror(req, status);
4799                                 return;
4800                         }
4801                         break;
4802                 }
4803 
4804                 default:
4805                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4806                         return;
4807         }
4808 
4809         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4810                             max_data_bytes);
4811 
4812         return;
4813 }
4814 
4815 /****************************************************************************
4816  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4817  code.
4818 ****************************************************************************/
4819 
4820 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4821                 connection_struct *conn,
4822                 const char *oldname_in,
4823                 const char *newname_in)
4824 {
4825         SMB_STRUCT_STAT sbuf1, sbuf2;
4826         char *last_component_oldname = NULL;
4827         char *last_component_newname = NULL;
4828         char *oldname = NULL;
4829         char *newname = NULL;
4830         NTSTATUS status = NT_STATUS_OK;
4831 
4832         ZERO_STRUCT(sbuf1);
4833         ZERO_STRUCT(sbuf2);
4834 
4835         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4836                         &last_component_oldname, &sbuf1);
4837         if (!NT_STATUS_IS_OK(status)) {
4838                 return status;
4839         }
4840 
4841         status = check_name(conn, oldname);
4842         if (!NT_STATUS_IS_OK(status)) {
4843                 return status;
4844         }
4845 
4846         /* source must already exist. */
4847         if (!VALID_STAT(sbuf1)) {
4848                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4849         }
4850 
4851         status = unix_convert(ctx, conn, newname_in, False, &newname,
4852                         &last_component_newname, &sbuf2);
4853         if (!NT_STATUS_IS_OK(status)) {
4854                 return status;
4855         }
4856 
4857         status = check_name(conn, newname);
4858         if (!NT_STATUS_IS_OK(status)) {
4859                 return status;
4860         }
4861 
4862         /* Disallow if newname already exists. */
4863         if (VALID_STAT(sbuf2)) {
4864                 return NT_STATUS_OBJECT_NAME_COLLISION;
4865         }
4866 
4867         /* No links from a directory. */
4868         if (S_ISDIR(sbuf1.st_mode)) {
4869                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4870         }
4871 
4872         /* Ensure this is within the share. */
4873         status = check_reduced_name(conn, oldname);
4874         if (!NT_STATUS_IS_OK(status)) {
4875                 return status;
4876         }
4877 
4878         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4879 
4880         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4881                 status = map_nt_error_from_unix(errno);
4882                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4883                                 nt_errstr(status), newname, oldname));
4884         }
4885 
4886         return status;
4887 }
4888 
4889 /****************************************************************************
4890  Deal with setting the time from any of the setfilepathinfo functions.
4891 ****************************************************************************/
4892 
4893 NTSTATUS smb_set_file_time(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
4894                            files_struct *fsp,
4895                            const char *fname,
4896                            const SMB_STRUCT_STAT *psbuf,
4897                            struct smb_file_time *ft,
4898                            bool setting_write_time)
4899 {
4900         struct smb_file_time ft_stat;
4901         uint32 action =
4902                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4903                 |FILE_NOTIFY_CHANGE_LAST_WRITE
4904                 |FILE_NOTIFY_CHANGE_CREATION;
4905 
4906         if (!VALID_STAT(*psbuf)) {
4907                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4908         }
4909 
4910         /* get some defaults (no modifications) if any info is zero or -1. */
4911         if (null_timespec(ft->create_time)) {
4912                 ft->create_time = get_create_timespec(psbuf, lp_fake_dir_create_times(SNUM(conn)));
4913                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4914         }
4915 
4916         if (null_timespec(ft->atime)) {
4917                 ft->atime= get_atimespec(psbuf);
4918                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4919         }
4920 
4921         if (null_timespec(ft->mtime)) {
4922                 ft->mtime = get_mtimespec(psbuf);
4923                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4924         }
4925 
4926         if (!setting_write_time) {
4927                 /* ft->mtime comes from change time, not write time. */
4928                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4929         }
4930 
4931         /* Ensure the resolution is the correct for
4932          * what we can store on this filesystem. */
4933 
4934         round_timespec(conn->ts_res, &ft->create_time);
4935         round_timespec(conn->ts_res, &ft->atime);
4936         round_timespec(conn->ts_res, &ft->mtime);
4937 
4938         DEBUG(5,("smb_set_filetime: actime: %s\n ",
4939                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4940         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4941                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4942         DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4943                 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4944 
4945         if (setting_write_time) {
4946                 /*
4947                  * This was a Windows setfileinfo on an open file.
4948                  * NT does this a lot. We also need to 
4949                  * set the time here, as it can be read by 
4950                  * FindFirst/FindNext and with the patch for bug #2045
4951                  * in smbd/fileio.c it ensures that this timestamp is
4952                  * kept sticky even after a write. We save the request
4953                  * away and will set it on file close and after a write. JRA.
4954                  */
4955 
4956                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4957                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4958 
4959                 if (fsp != NULL) {
4960                         if (fsp->base_fsp) {
4961                                 set_sticky_write_time_fsp(fsp->base_fsp,
4962                                                           ft->mtime);
4963                         } else {
4964                                 set_sticky_write_time_fsp(fsp, ft->mtime);
4965                         }
4966                 } else {
4967                         set_sticky_write_time_path(conn, fname,
4968                                             vfs_file_id_from_sbuf(conn, psbuf),
4969                                             ft->mtime);
4970                 }
4971         }
4972 
4973         ft_stat.create_time = get_create_timespec(psbuf,
4974                                 lp_fake_dir_create_times(SNUM(conn)));
4975         ft_stat.atime= get_atimespec(psbuf);
4976         ft_stat.mtime = get_mtimespec(psbuf);
4977 
4978         round_timespec(conn->ts_res, &ft_stat.create_time);
4979         round_timespec(conn->ts_res, &ft_stat.atime);
4980         round_timespec(conn->ts_res, &ft_stat.mtime);
4981 
4982         if (fsp && fsp->base_fsp) {
4983                 fname = fsp->base_fsp->fsp_name;
4984         }
4985 
4986         if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
4987                         timespec_compare(&ft_stat.atime, &ft->atime) ||
4988                         timespec_compare(&ft_stat.mtime, &ft->mtime)) {
4989                 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4990                 if(file_ntimes(conn, fname, ft)!=0) {
4991                         return map_nt_error_from_unix(errno);
4992                 }
4993         }
4994         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4995 
4996         return NT_STATUS_OK;
4997 }
4998 
4999 /****************************************************************************
5000  Deal with setting the dosmode from any of the setfilepathinfo functions.
5001 ****************************************************************************/
5002 
5003 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5004                                 files_struct *fsp,
5005                                 const char *fname,
5006                                 SMB_STRUCT_STAT *psbuf,
5007                                 uint32 dosmode)
5008 {
5009         if (!VALID_STAT(*psbuf)) {
5010                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5011         }
5012 
5013         if (fsp) {
5014                 if (fsp->base_fsp) {
5015                         fname = fsp->base_fsp->fsp_name;
5016                 } else {
5017                         fname = fsp->fsp_name;
5018                 }
5019         }
5020                 
5021         if (dosmode) {
5022                 if (S_ISDIR(psbuf->st_mode)) {
5023                         dosmode |= aDIR;
5024                 } else {
5025                         dosmode &= ~aDIR;
5026                 }
5027         }
5028 
5029         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5030 
5031         /* check the mode isn't different, before changing it */
5032         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5033 
5034                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5035                                         fname, (unsigned int)dosmode ));
5036 
5037                 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5038                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5039                                                 fname, strerror(errno)));
5040                         return map_nt_error_from_unix(errno);
5041                 }
5042         }
5043         return NT_STATUS_OK;
5044 }
5045 
5046 /****************************************************************************
5047  Deal with setting the size from any of the setfilepathinfo functions.
5048 ****************************************************************************/
5049 
5050 static NTSTATUS smb_set_file_size(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5051                                   struct smb_request *req,
5052                                 files_struct *fsp,
5053                                 const char *fname,
5054                                 SMB_STRUCT_STAT *psbuf,
5055                                 SMB_OFF_T size)
5056 {
5057         NTSTATUS status = NT_STATUS_OK;
5058         files_struct *new_fsp = NULL;
5059 
5060         if (!VALID_STAT(*psbuf)) {
5061                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5062         }
5063 
5064         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5065 
5066         if (size == get_file_size_stat(psbuf)) {
5067                 return NT_STATUS_OK;
5068         }
5069 
5070         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5071                 fname, (double)size ));
5072 
5073         if (fsp && fsp->fh->fd != -1) {
5074                 /* Handle based call. */
5075                 if (vfs_set_filelen(fsp, size) == -1) {
5076                         return map_nt_error_from_unix(errno);
5077                 }
5078                 trigger_write_time_update_immediate(fsp);
5079                 return NT_STATUS_OK;
5080         }
5081 
5082         status = SMB_VFS_CREATE_FILE(
5083                 conn,                                   /* conn */
5084                 req,                                    /* req */
5085                 0,                                      /* root_dir_fid */
5086                 fname,                                  /* fname */
5087                 0,                                      /* create_file_flags */
5088                 FILE_WRITE_ATTRIBUTES,                  /* access_mask */
5089                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5090                     FILE_SHARE_DELETE),
5091                 FILE_OPEN,                              /* create_disposition*/
5092                 0,                                      /* create_options */
5093                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5094                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5095                 0,                                      /* allocation_size */
5096                 NULL,                                   /* sd */
5097                 NULL,                                   /* ea_list */
5098                 &new_fsp,                               /* result */
5099                 NULL,                                   /* pinfo */
5100                 psbuf);                                 /* psbuf */
5101 
5102         if (!NT_STATUS_IS_OK(status)) {
5103                 /* NB. We check for open_was_deferred in the caller. */
5104                 return status;
5105         }
5106 
5107         if (vfs_set_filelen(new_fsp, size) == -1) {
5108                 status = map_nt_error_from_unix(errno);
5109                 close_file(req, new_fsp,NORMAL_CLOSE);
5110                 return status;
5111         }
5112 
5113         trigger_write_time_update_immediate(new_fsp);
5114         close_file(req, new_fsp,NORMAL_CLOSE);
5115         return NT_STATUS_OK;
5116 }
5117 
5118 /****************************************************************************
5119  Deal with SMB_INFO_SET_EA.
5120 ****************************************************************************/
5121 
5122 static NTSTATUS smb_info_set_ea(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5123                                 const char *pdata,
5124                                 int total_data,
5125                                 files_struct *fsp,
5126                                 const char *fname)
5127 {
5128         struct ea_list *ea_list = NULL;
5129         TALLOC_CTX *ctx = NULL;
5130         NTSTATUS status = NT_STATUS_OK;
5131 
5132         if (total_data < 10) {
5133 
5134                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5135                    length. They seem to have no effect. Bug #3212. JRA */
5136 
5137                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5138                         /* We're done. We only get EA info in this call. */
5139                         return NT_STATUS_OK;
5140                 }
5141 
5142                 return NT_STATUS_INVALID_PARAMETER;
5143         }
5144 
5145         if (IVAL(pdata,0) > total_data) {
5146                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5147                         IVAL(pdata,0), (unsigned int)total_data));
5148                 return NT_STATUS_INVALID_PARAMETER;
5149         }
5150 
5151         ctx = talloc_tos();
5152         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5153         if (!ea_list) {
5154                 return NT_STATUS_INVALID_PARAMETER;
5155         }
5156         status = set_ea(conn, fsp, fname, ea_list);
5157 
5158         return status;
5159 }
5160 
5161 /****************************************************************************
5162  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5163 ****************************************************************************/
5164 
5165 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5166                                 const char *pdata,
5167                                 int total_data,
5168                                 files_struct *fsp,
5169                                 const char *fname,
5170                                 SMB_STRUCT_STAT *psbuf)
5171 {
5172         NTSTATUS status = NT_STATUS_OK;
5173         bool delete_on_close;
5174         uint32 dosmode = 0;
5175 
5176         if (total_data < 1) {
5177                 return NT_STATUS_INVALID_PARAMETER;
5178         }
5179 
5180         if (fsp == NULL) {
5181                 return NT_STATUS_INVALID_HANDLE;
5182         }
5183 
5184         delete_on_close = (CVAL(pdata,0) ? True : False);
5185         dosmode = dos_mode(conn, fname, psbuf);
5186 
5187         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5188                 "delete_on_close = %u\n",
5189                 fsp->fsp_name,
5190                 (unsigned int)dosmode,
5191                 (unsigned int)delete_on_close ));
5192 
5193         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5194  
5195         if (!NT_STATUS_IS_OK(status)) {
5196                 return status;
5197         }
5198 
5199         /* The set is across all open files on this dev/inode pair. */
5200         if (!set_delete_on_close(fsp, delete_on_close,
5201                                  &conn->server_info->utok)) {
5202                 return NT_STATUS_ACCESS_DENIED;
5203         }
5204         return NT_STATUS_OK;
5205 }
5206 
5207 /****************************************************************************
5208  Deal with SMB_FILE_POSITION_INFORMATION.
5209 ****************************************************************************/
5210 
5211 static NTSTATUS smb_file_position_information(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5212                                 const char *pdata,
5213                                 int total_data,
5214                                 files_struct *fsp)
5215 {
5216         uint64_t position_information;
5217 
5218         if (total_data < 8) {
5219                 return NT_STATUS_INVALID_PARAMETER;
5220         }
5221 
5222         if (fsp == NULL) {
5223                 /* Ignore on pathname based set. */
5224                 return NT_STATUS_OK;
5225         }
5226 
5227         position_information = (uint64_t)IVAL(pdata,0);
5228 #ifdef LARGE_SMB_OFF_T
5229         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5230 #else /* LARGE_SMB_OFF_T */
5231         if (IVAL(pdata,4) != 0) {
5232                 /* more than 32 bits? */
5233                 return NT_STATUS_INVALID_PARAMETER;
5234         }
5235 #endif /* LARGE_SMB_OFF_T */
5236 
5237         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5238                 fsp->fsp_name, (double)position_information ));
5239         fsp->fh->position_information = position_information;
5240         return NT_STATUS_OK;
5241 }
5242 
5243 /****************************************************************************
5244  Deal with SMB_FILE_MODE_INFORMATION.
5245 ****************************************************************************/
5246 
5247 static NTSTATUS smb_file_mode_information(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5248                                 const char *pdata,
5249                                 int total_data)
5250 {
5251         uint32 mode;
5252 
5253         if (total_data < 4) {
5254                 return NT_STATUS_INVALID_PARAMETER;
5255         }
5256         mode = IVAL(pdata,0);
5257         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5258                 return NT_STATUS_INVALID_PARAMETER;
5259         }
5260         return NT_STATUS_OK;
5261 }
5262 
5263 /****************************************************************************
5264  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5265 ****************************************************************************/
5266 
5267 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5268                                        struct smb_request *req,
5269                                        const char *pdata,
5270                                        int total_data,
5271                                        const char *fname)
5272 {
5273         char *link_target = NULL;
5274         const char *newname = fname;
5275         NTSTATUS status = NT_STATUS_OK;
5276         TALLOC_CTX *ctx = talloc_tos();
5277 
5278         /* Set a symbolic link. */
5279         /* Don't allow this if follow links is false. */
5280 
5281         if (total_data == 0) {
5282                 return NT_STATUS_INVALID_PARAMETER;
5283         }
5284 
5285         if (!lp_symlinks(SNUM(conn))) {
5286                 return NT_STATUS_ACCESS_DENIED;
5287         }
5288 
5289         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5290                     total_data, STR_TERMINATE);
5291 
5292         if (!link_target) {
5293                 return NT_STATUS_INVALID_PARAMETER;
5294         }
5295 
5296         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5297                         newname, link_target ));
5298 
5299         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5300                 return map_nt_error_from_unix(errno);
5301         }
5302 
5303         return NT_STATUS_OK;
5304 }
5305 
5306 /****************************************************************************
5307  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5308 ****************************************************************************/
5309 
5310 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5311                                         struct smb_request *req,
5312                                         const char *pdata, int total_data,
5313                                         const char *fname)
5314 {
5315         char *oldname = NULL;
5316         TALLOC_CTX *ctx = talloc_tos();
5317         NTSTATUS status = NT_STATUS_OK;
5318 
5319         /* Set a hard link. */
5320         if (total_data == 0) {
5321                 return NT_STATUS_INVALID_PARAMETER;
5322         }
5323 
5324         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5325                         total_data, STR_TERMINATE, &status);
5326         if (!NT_STATUS_IS_OK(status)) {
5327                 return status;
5328         }
5329 
5330         status = resolve_dfspath(ctx, conn,
5331                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5332                                 oldname,
5333                                 &oldname);
5334         if (!NT_STATUS_IS_OK(status)) {
5335                 return status;
5336         }
5337 
5338         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5339                 fname, oldname));
5340 
5341         return hardlink_internals(ctx, conn, oldname, fname);
5342 }
5343 
5344 /****************************************************************************
5345  Deal with SMB_FILE_RENAME_INFORMATION.
5346 ****************************************************************************/
5347 
5348 static NTSTATUS smb_file_rename_information(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5349                                             struct smb_request *req,
5350                                             const char *pdata,
5351                                             int total_data,
5352                                             files_struct *fsp,
5353                                             const char *fname)
5354 {
5355         bool overwrite;
5356         uint32 root_fid;
5357         uint32 len;
5358         char *newname = NULL;
5359         char *base_name = NULL;
5360         bool dest_has_wcard = False;
5361         SMB_STRUCT_STAT sbuf;
5362         char *newname_last_component = NULL;
5363         NTSTATUS status = NT_STATUS_OK;
5364         char *p;
5365         TALLOC_CTX *ctx = talloc_tos();
5366 
5367         if (total_data < 13) {
5368                 return NT_STATUS_INVALID_PARAMETER;
5369         }
5370 
5371         ZERO_STRUCT(sbuf);
5372 
5373         overwrite = (CVAL(pdata,0) ? True : False);
5374         root_fid = IVAL(pdata,4);
5375         len = IVAL(pdata,8);
5376 
5377         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5378                 return NT_STATUS_INVALID_PARAMETER;
5379         }
5380 
5381         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5382                               len, 0, &status,
5383                               &dest_has_wcard);
5384         if (!NT_STATUS_IS_OK(status)) {
5385                 return status;
5386         }
5387 
5388         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5389                                 newname));
5390 
5391         status = resolve_dfspath_wcard(ctx, conn,
5392                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5393                                        newname,
5394                                        &newname,
5395                                        &dest_has_wcard);
5396         if (!NT_STATUS_IS_OK(status)) {
5397                 return status;
5398         }
5399 
5400         /* Check the new name has no '/' characters. */
5401         if (strchr_m(newname, '/')) {
5402                 return NT_STATUS_NOT_SUPPORTED;
5403         }
5404 
5405         if (fsp && fsp->base_fsp) {
5406                 /* newname must be a stream name. */
5407                 if (newname[0] != ':') {
5408                         return NT_STATUS_NOT_SUPPORTED;
5409                 }
5410                 base_name = talloc_asprintf(ctx, "%s%s",
5411                                            fsp->base_fsp->fsp_name,
5412                                            newname);
5413                 if (!base_name) {
5414                         return NT_STATUS_NO_MEMORY;
5415                 }
5416         } else {
5417                 /* newname must *not* be a stream name. */
5418                 if (is_ntfs_stream_name(newname)) {
5419                         return NT_STATUS_NOT_SUPPORTED;
5420                 }
5421 
5422                 /* Create the base directory. */
5423                 base_name = talloc_strdup(ctx, fname);
5424                 if (!base_name) {
5425                         return NT_STATUS_NO_MEMORY;
5426                 }
5427                 p = strrchr_m(base_name, '/');
5428                 if (p) {
5429                         p[1] = '\0';
5430                 } else {
5431                         base_name = talloc_strdup(ctx, "./");
5432                         if (!base_name) {
5433                                 return NT_STATUS_NO_MEMORY;
5434                         }
5435                 }
5436                 /* Append the new name. */
5437                 base_name = talloc_asprintf_append(base_name,
5438                                 "%s",
5439                                 newname);
5440                 if (!base_name) {
5441                         return NT_STATUS_NO_MEMORY;
5442                 }
5443 
5444                 status = unix_convert(ctx, conn, newname, False,
5445                                 &newname,
5446                                 &newname_last_component,
5447                                 &sbuf);
5448 
5449                 /* If an error we expect this to be
5450                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5451 
5452                 if (!NT_STATUS_IS_OK(status)
5453                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5454                                         status)) {
5455                         return status;
5456                 }
5457         }
5458 
5459         if (fsp) {
5460                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5461                         fsp->fnum, fsp->fsp_name, base_name ));
5462                 status = rename_internals_fsp(conn, fsp, base_name,
5463                                               newname_last_component, 0,
5464                                               overwrite);
5465         } else {
5466                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5467                         fname, base_name ));
5468                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5469                                         overwrite, False, dest_has_wcard,
5470                                         FILE_WRITE_ATTRIBUTES);
5471         }
5472 
5473         return status;
5474 }
5475 
5476 /****************************************************************************
5477  Deal with SMB_SET_POSIX_ACL.
5478 ****************************************************************************/
5479 
5480 #if defined(HAVE_POSIX_ACLS)
5481 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5482                                 const char *pdata,
5483                                 int total_data,
5484                                 files_struct *fsp,
5485                                 const char *fname,
5486                                 SMB_STRUCT_STAT *psbuf)
5487 {
5488         uint16 posix_acl_version;
5489         uint16 num_file_acls;
5490         uint16 num_def_acls;
5491         bool valid_file_acls = True;
5492         bool valid_def_acls = True;
5493 
5494         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5495                 return NT_STATUS_INVALID_PARAMETER;
5496         }
5497         posix_acl_version = SVAL(pdata,0);
5498         num_file_acls = SVAL(pdata,2);
5499         num_def_acls = SVAL(pdata,4);
5500 
5501         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5502                 valid_file_acls = False;
5503                 num_file_acls = 0;
5504         }
5505 
5506         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5507                 valid_def_acls = False;
5508                 num_def_acls = 0;
5509         }
5510 
5511         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5512                 return NT_STATUS_INVALID_PARAMETER;
5513         }
5514 
5515         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5516                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5517                 return NT_STATUS_INVALID_PARAMETER;
5518         }
5519 
5520         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5521                 fname ? fname : fsp->fsp_name,
5522                 (unsigned int)num_file_acls,
5523                 (unsigned int)num_def_acls));
5524 
5525         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5526                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5527                 return map_nt_error_from_unix(errno);
5528         }
5529 
5530         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5531                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5532                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5533                 return map_nt_error_from_unix(errno);
5534         }
5535         return NT_STATUS_OK;
5536 }
5537 #endif
5538 
5539 /****************************************************************************
5540  Deal with SMB_SET_POSIX_LOCK.
5541 ****************************************************************************/
5542 
5543 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5544                                 struct smb_request *req,
5545                                 const char *pdata,
5546                                 int total_data,
5547                                 files_struct *fsp)
5548 {
5549         uint64_t count;
5550         uint64_t offset;
5551         uint32 lock_pid;
5552         bool blocking_lock = False;
5553         enum brl_type lock_type;
5554 
5555         NTSTATUS status = NT_STATUS_OK;
5556 
5557         if (fsp == NULL || fsp->fh->fd == -1) {
5558                 return NT_STATUS_INVALID_HANDLE;
5559         }
5560 
5561         if (total_data != POSIX_LOCK_DATA_SIZE) {
5562                 return NT_STATUS_INVALID_PARAMETER;
5563         }
5564 
5565         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5566                 case POSIX_LOCK_TYPE_READ:
5567                         lock_type = READ_LOCK;
5568                         break;
5569                 case POSIX_LOCK_TYPE_WRITE:
5570                         /* Return the right POSIX-mappable error code for files opened read-only. */
5571                         if (!fsp->can_write) {
5572                                 return NT_STATUS_INVALID_HANDLE;
5573                         }
5574                         lock_type = WRITE_LOCK;
5575                         break;
5576                 case POSIX_LOCK_TYPE_UNLOCK:
5577                         lock_type = UNLOCK_LOCK;
5578                         break;
5579                 default:
5580                         return NT_STATUS_INVALID_PARAMETER;
5581         }
5582 
5583         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5584                 blocking_lock = False;
5585         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5586                 blocking_lock = True;
5587         } else {
5588                 return NT_STATUS_INVALID_PARAMETER;
5589         }
5590 
5591         if (!lp_blocking_locks(SNUM(conn))) { 
5592                 blocking_lock = False;
5593         }
5594 
5595         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5596 #if defined(HAVE_LONGLONG)
5597         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5598                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5599         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5600                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5601 #else /* HAVE_LONGLONG */
5602         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5603         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5604 #endif /* HAVE_LONGLONG */
5605 
5606         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5607                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5608                 fsp->fsp_name,
5609                 (unsigned int)lock_type,
5610                 (unsigned int)lock_pid,
5611                 (double)count,
5612                 (double)offset ));
5613 
5614         if (lock_type == UNLOCK_LOCK) {
5615                 status = do_unlock(smbd_messaging_context(),
5616                                 fsp,
5617                                 lock_pid,
5618                                 count,
5619                                 offset,
5620                                 POSIX_LOCK);
5621         } else {
5622                 uint32 block_smbpid;
5623 
5624                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5625                                                         fsp,
5626                                                         lock_pid,
5627                                                         count,
5628                                                         offset,
5629                                                         lock_type,
5630                                                         POSIX_LOCK,
5631                                                         blocking_lock,
5632                                                         &status,
5633                                                         &block_smbpid,
5634                                                         NULL);
5635 
5636                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5637                         /*
5638                          * A blocking lock was requested. Package up
5639                          * this smb into a queued request and push it
5640                          * onto the blocking lock queue.
5641                          */
5642                         if(push_blocking_lock_request(br_lck,
5643                                                 req,
5644                                                 fsp,
5645                                                 -1, /* infinite timeout. */
5646                                                 0,
5647                                                 lock_pid,
5648                                                 lock_type,
5649                                                 POSIX_LOCK,
5650                                                 offset,
5651                                                 count,
5652                                                 block_smbpid)) {
5653                                 TALLOC_FREE(br_lck);
5654                                 return status;
5655                         }
5656                 }
5657                 TALLOC_FREE(br_lck);
5658         }
5659 
5660         return status;
5661 }
5662 
5663 /****************************************************************************
5664  Deal with SMB_INFO_STANDARD.
5665 ****************************************************************************/
5666 
5667 static NTSTATUS smb_set_info_standard(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5668                                         const char *pdata,
5669                                         int total_data,
5670                                         files_struct *fsp,
5671                                         const char *fname,
5672                                         const SMB_STRUCT_STAT *psbuf)
5673 {
5674         struct smb_file_time ft;
5675         ZERO_STRUCT(ft);
5676 
5677         if (total_data < 12) {
5678                 return NT_STATUS_INVALID_PARAMETER;
5679         }
5680 
5681         /* create time */
5682         ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
5683 
5684         /* access time */
5685         ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
5686 
5687         /* write time */
5688         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
5689 
5690         DEBUG(10,("smb_set_info_standard: file %s\n",
5691                 fname ? fname : fsp->fsp_name ));
5692 
5693         return smb_set_file_time(conn,
5694                                 fsp,
5695                                 fname,
5696                                 psbuf,
5697                                 &ft,
5698                                 true);
5699 }
5700 
5701 /****************************************************************************
5702  Deal with SMB_SET_FILE_BASIC_INFO.
5703 ****************************************************************************/
5704 
5705 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5706                                         const char *pdata,
5707                                         int total_data,
5708                                         files_struct *fsp,
5709                                         const char *fname,
5710                                         SMB_STRUCT_STAT *psbuf)
5711 {
5712         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5713         struct timespec write_time;
5714         struct timespec changed_time;
5715         struct smb_file_time ft;
5716         uint32 dosmode = 0;
5717         NTSTATUS status = NT_STATUS_OK;
5718         bool setting_write_time = true;
5719 
5720         ZERO_STRUCT(ft);
5721 
5722         if (total_data < 36) {
5723                 return NT_STATUS_INVALID_PARAMETER;
5724         }
5725 
5726         /* Set the attributes */
5727         dosmode = IVAL(pdata,32);
5728         status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5729         if (!NT_STATUS_IS_OK(status)) {
5730                 return status;
5731         }
5732 
5733         /* access time */
5734         ft.atime = interpret_long_date(pdata+8);
5735 
5736         write_time = interpret_long_date(pdata+16);
5737         changed_time = interpret_long_date(pdata+24);
5738 
5739         /* mtime */
5740         ft.mtime = timespec_min(&write_time, &changed_time);
5741 
5742         /* create time */
5743         ft.create_time = interpret_long_date(pdata);
5744 
5745         if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5746             !null_timespec(write_time)) {
5747                 ft.mtime = write_time;
5748         }
5749 
5750         /* Prefer a defined time to an undefined one. */
5751         if (null_timespec(ft.mtime)) {
5752                 if (null_timespec(write_time)) {
5753                         ft.mtime = changed_time;
5754                         setting_write_time = false;
5755                 } else {
5756                         ft.mtime = write_time;
5757                 }
5758         }
5759 
5760         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5761                 fname ? fname : fsp->fsp_name ));
5762 
5763         return smb_set_file_time(conn,
5764                                 fsp,
5765                                 fname,
5766                                 psbuf,
5767                                 &ft,
5768                                 setting_write_time);
5769 }
5770 
5771 /****************************************************************************
5772  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5773 ****************************************************************************/
5774 
5775 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5776                                              struct smb_request *req,
5777                                         const char *pdata,
5778                                         int total_data,
5779                                         files_struct *fsp,
5780                                         const char *fname,
5781                                         SMB_STRUCT_STAT *psbuf)
5782 {
5783         uint64_t allocation_size = 0;
5784         NTSTATUS status = NT_STATUS_OK;
5785         files_struct *new_fsp = NULL;
5786 
5787         if (!VALID_STAT(*psbuf)) {
5788                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789         }
5790 
5791         if (total_data < 8) {
5792                 return NT_STATUS_INVALID_PARAMETER;
5793         }
5794 
5795         allocation_size = (uint64_t)IVAL(pdata,0);
5796 #ifdef LARGE_SMB_OFF_T
5797         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5798 #else /* LARGE_SMB_OFF_T */
5799         if (IVAL(pdata,4) != 0) {
5800                 /* more than 32 bits? */
5801                 return NT_STATUS_INVALID_PARAMETER;
5802         }
5803 #endif /* LARGE_SMB_OFF_T */
5804 
5805         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5806                         fname, (double)allocation_size ));
5807 
5808         if (allocation_size) {
5809                 allocation_size = smb_roundup(conn, allocation_size);
5810         }
5811 
5812         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5813                         fname, (double)allocation_size ));
5814 
5815         if (fsp && fsp->fh->fd != -1) {
5816                 /* Open file handle. */
5817                 /* Only change if needed. */
5818                 if (allocation_size != get_file_size_stat(psbuf)) {
5819                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5820                                 return map_nt_error_from_unix(errno);
5821                         }
5822                 }
5823                 /* But always update the time. */
5824                 /*
5825                  * This is equivalent to a write. Ensure it's seen immediately
5826                  * if there are no pending writes.
5827                  */
5828                 trigger_write_time_update_immediate(fsp);
5829                 return NT_STATUS_OK;
5830         }
5831 
5832         /* Pathname or stat or directory file. */
5833 
5834         status = SMB_VFS_CREATE_FILE(
5835                 conn,                                   /* conn */
5836                 req,                                    /* req */
5837                 0,                                      /* root_dir_fid */
5838                 fname,                                  /* fname */
5839                 0,                                      /* create_file_flags */
5840                 FILE_WRITE_DATA,                        /* access_mask */
5841                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5842                     FILE_SHARE_DELETE),
5843                 FILE_OPEN,                              /* create_disposition*/
5844                 0,                                      /* create_options */
5845                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5846                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5847                 0,                                      /* allocation_size */
5848                 NULL,                                   /* sd */
5849                 NULL,                                   /* ea_list */
5850                 &new_fsp,                               /* result */
5851                 NULL,                                   /* pinfo */
5852                 psbuf);                                 /* psbuf */
5853 
5854         if (!NT_STATUS_IS_OK(status)) {
5855                 /* NB. We check for open_was_deferred in the caller. */
5856                 return status;
5857         }
5858 
5859         /* Only change if needed. */
5860         if (allocation_size != get_file_size_stat(psbuf)) {
5861                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5862                         status = map_nt_error_from_unix(errno);
5863                         close_file(req, new_fsp, NORMAL_CLOSE);
5864                         return status;
5865                 }
5866         }
5867 
5868         /* Changing the allocation size should set the last mod time. */
5869         /*
5870          * This is equivalent to a write. Ensure it's seen immediately
5871          * if there are no pending writes.
5872          */
5873         trigger_write_time_update_immediate(new_fsp);
5874 
5875         close_file(req, new_fsp, NORMAL_CLOSE);
5876         return NT_STATUS_OK;
5877 }
5878 
5879 /****************************************************************************
5880  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5881 ****************************************************************************/
5882 
5883 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5884                                               struct smb_request *req,
5885                                         const char *pdata,
5886                                         int total_data,
5887                                         files_struct *fsp,
5888                                         const char *fname,
5889                                         SMB_STRUCT_STAT *psbuf)
5890 {
5891         SMB_OFF_T size;
5892 
5893         if (total_data < 8) {
5894                 return NT_STATUS_INVALID_PARAMETER;
5895         }
5896 
5897         size = IVAL(pdata,0);
5898 #ifdef LARGE_SMB_OFF_T
5899         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5900 #else /* LARGE_SMB_OFF_T */
5901         if (IVAL(pdata,4) != 0) {
5902                 /* more than 32 bits? */
5903                 return NT_STATUS_INVALID_PARAMETER;
5904         }
5905 #endif /* LARGE_SMB_OFF_T */
5906         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5907                 "file %s to %.0f\n", fname, (double)size ));
5908 
5909         return smb_set_file_size(conn, req,
5910                                 fsp,
5911                                 fname,
5912                                 psbuf,
5913                                 size);
5914 }
5915 
5916 /****************************************************************************
5917  Allow a UNIX info mknod.
5918 ****************************************************************************/
5919 
5920 static NTSTATUS smb_unix_mknod(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
5921                                         const char *pdata,
5922                                         int total_data,
5923                                         const char *fname,
5924                                         SMB_STRUCT_STAT *psbuf)
5925 {
5926         uint32 file_type = IVAL(pdata,56);
5927 #if defined(HAVE_MAKEDEV)
5928         uint32 dev_major = IVAL(pdata,60);
5929         uint32 dev_minor = IVAL(pdata,68);
5930 #endif
5931         SMB_DEV_T dev = (SMB_DEV_T)0;
5932         uint32 raw_unixmode = IVAL(pdata,84);
5933         NTSTATUS status;
5934         mode_t unixmode;
5935 
5936         if (total_data < 100) {
5937                 return NT_STATUS_INVALID_PARAMETER;
5938         }
5939 
5940         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5941         if (!NT_STATUS_IS_OK(status)) {
5942                 return status;
5943         }
5944 
5945 #if defined(HAVE_MAKEDEV)
5946         dev = makedev(dev_major, dev_minor);
5947 #endif
5948 
5949         switch (file_type) {
5950 #if defined(S_IFIFO)
5951                 case UNIX_TYPE_FIFO:
5952                         unixmode |= S_IFIFO;
5953                         break;
5954 #endif
5955 #if defined(S_IFSOCK)
5956                 case UNIX_TYPE_SOCKET:
5957                         unixmode |= S_IFSOCK;
5958                         break;
5959 #endif
5960 #if defined(S_IFCHR)
5961                 case UNIX_TYPE_CHARDEV:
5962                         unixmode |= S_IFCHR;
5963                         break;
5964 #endif
5965 #if defined(S_IFBLK)
5966                 case UNIX_TYPE_BLKDEV:
5967                         unixmode |= S_IFBLK;
5968                         break;
5969 #endif
5970                 default:
5971                         return NT_STATUS_INVALID_PARAMETER;
5972         }
5973 
5974         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5975 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5976 
5977         /* Ok - do the mknod. */
5978         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5979                 return map_nt_error_from_unix(errno);
5980         }
5981 
5982         /* If any of the other "set" calls fail we
5983          * don't want to end up with a half-constructed mknod.
5984          */
5985 
5986         if (lp_inherit_perms(SNUM(conn))) {
5987                 char *parent;
5988                 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5989                         return NT_STATUS_NO_MEMORY;
5990                 }
5991                 inherit_access_posix_acl(conn, parent, fname, unixmode);
5992                 TALLOC_FREE(parent);
5993         }
5994 
5995         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5996                 status = map_nt_error_from_unix(errno);
5997                 SMB_VFS_UNLINK(conn,fname);
5998                 return status;
5999         }
6000         return NT_STATUS_OK;
6001 }
6002 
6003 /****************************************************************************
6004  Deal with SMB_SET_FILE_UNIX_BASIC.
6005 ****************************************************************************/
6006 
6007 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6008                                         struct smb_request *req,
6009                                         const char *pdata,
6010                                         int total_data,
6011                                         files_struct *fsp,
6012                                         const char *fname,
6013                                         SMB_STRUCT_STAT *psbuf)
6014 {
6015         struct smb_file_time ft;
6016         uint32 raw_unixmode;
6017         mode_t unixmode;
6018         SMB_OFF_T size = 0;
6019         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6020         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6021         NTSTATUS status = NT_STATUS_OK;
6022         bool delete_on_fail = False;
6023         enum perm_type ptype;
6024         files_struct *all_fsps = NULL;
6025         bool modify_mtime = true;
6026         struct file_id id;
6027 
6028         ZERO_STRUCT(ft);
6029 
6030         if (total_data < 100) {
6031                 return NT_STATUS_INVALID_PARAMETER;
6032         }
6033 
6034         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6035            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6036                 size=IVAL(pdata,0); /* first 8 Bytes are size */
6037 #ifdef LARGE_SMB_OFF_T
6038                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6039 #else /* LARGE_SMB_OFF_T */
6040                 if (IVAL(pdata,4) != 0) {
6041                         /* more than 32 bits? */
6042                         return NT_STATUS_INVALID_PARAMETER;
6043                 }
6044 #endif /* LARGE_SMB_OFF_T */
6045         }
6046 
6047         ft.atime = interpret_long_date(pdata+24); /* access_time */
6048         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6049         set_owner = (uid_t)IVAL(pdata,40);
6050         set_grp = (gid_t)IVAL(pdata,48);
6051         raw_unixmode = IVAL(pdata,84);
6052 
6053         if (VALID_STAT(*psbuf)) {
6054                 if (S_ISDIR(psbuf->st_mode)) {
6055                         ptype = PERM_EXISTING_DIR;
6056                 } else {
6057                         ptype = PERM_EXISTING_FILE;
6058                 }
6059         } else {
6060                 ptype = PERM_NEW_FILE;
6061         }
6062 
6063         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6064         if (!NT_STATUS_IS_OK(status)) {
6065                 return status;
6066         }
6067 
6068         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6069 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6070                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6071 
6072         if (!VALID_STAT(*psbuf)) {
6073                 /*
6074                  * The only valid use of this is to create character and block
6075                  * devices, and named pipes. This is deprecated (IMHO) and 
6076                  * a new info level should be used for mknod. JRA.
6077                  */
6078 
6079                 status = smb_unix_mknod(conn,
6080                                         pdata,
6081                                         total_data,
6082                                         fname,
6083                                         psbuf);
6084                 if (!NT_STATUS_IS_OK(status)) {
6085                         return status;
6086                 }
6087 
6088                 /* Ensure we don't try and change anything else. */
6089                 raw_unixmode = SMB_MODE_NO_CHANGE;
6090                 size = get_file_size_stat(psbuf);
6091                 ft.atime = get_atimespec(psbuf);
6092                 ft.mtime = get_mtimespec(psbuf);
6093                 /* 
6094                  * We continue here as we might want to change the 
6095                  * owner uid/gid.
6096                  */
6097                 delete_on_fail = True;
6098         }
6099 
6100 #if 1
6101         /* Horrible backwards compatibility hack as an old server bug
6102          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6103          * */
6104 
6105         if (!size) {
6106                 size = get_file_size_stat(psbuf);
6107         }
6108 #endif
6109 
6110         /*
6111          * Deal with the UNIX specific mode set.
6112          */
6113 
6114         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6115                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6116                         (unsigned int)unixmode, fname ));
6117                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6118                         return map_nt_error_from_unix(errno);
6119                 }
6120         }
6121 
6122         /*
6123          * Deal with the UNIX specific uid set.
6124          */
6125 
6126         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6127                 int ret;
6128 
6129                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6130                         (unsigned int)set_owner, fname ));
6131 
6132                 if (S_ISLNK(psbuf->st_mode)) {
6133                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6134                 } else {
6135                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6136                 }
6137 
6138                 if (ret != 0) {
6139                         status = map_nt_error_from_unix(errno);
6140                         if (delete_on_fail) {
6141                                 SMB_VFS_UNLINK(conn,fname);
6142                         }
6143                         return status;
6144                 }
6145         }
6146 
6147         /*
6148          * Deal with the UNIX specific gid set.
6149          */
6150 
6151         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6152                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6153                         (unsigned int)set_owner, fname ));
6154                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6155                         status = map_nt_error_from_unix(errno);
6156                         if (delete_on_fail) {
6157                                 SMB_VFS_UNLINK(conn,fname);
6158                         }
6159                         return status;
6160                 }
6161         }
6162 
6163         /* Deal with any size changes. */
6164 
6165         status = smb_set_file_size(conn, req,
6166                                 fsp,
6167                                 fname,
6168                                 psbuf,
6169                                 size);
6170         if (!NT_STATUS_IS_OK(status)) {
6171                 return status;
6172         }
6173 
6174         /* Deal with any time changes. */
6175         id = vfs_file_id_from_sbuf(conn, psbuf);
6176         for(all_fsps = file_find_di_first(id); all_fsps;
6177                         all_fsps = file_find_di_next(all_fsps)) {
6178                 /*
6179                  * We're setting the time explicitly for UNIX.
6180                  * Cancel any pending changes over all handles.
6181                  */
6182                 all_fsps->update_write_time_on_close = false;
6183                 TALLOC_FREE(all_fsps->update_write_time_event);
6184         }
6185 
6186         /*
6187          * Override the "setting_write_time"
6188          * parameter here as it almost does what
6189          * we need. Just remember if we modified
6190          * mtime and send the notify ourselves.
6191          */
6192         if (null_timespec(ft.mtime)) {
6193                 modify_mtime = false;
6194         }
6195 
6196         status = smb_set_file_time(conn,
6197                                 fsp,
6198                                 fname,
6199                                 psbuf,
6200                                 &ft,
6201                                 false);
6202         if (modify_mtime) {
6203                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6204                         FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6205         }
6206         return status;
6207 }
6208 
6209 /****************************************************************************
6210  Deal with SMB_SET_FILE_UNIX_INFO2.
6211 ****************************************************************************/
6212 
6213 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6214                                         struct smb_request *req,
6215                                         const char *pdata,
6216                                         int total_data,
6217                                         files_struct *fsp,
6218                                         const char *fname,
6219                                         SMB_STRUCT_STAT *psbuf)
6220 {
6221         NTSTATUS status;
6222         uint32 smb_fflags;
6223         uint32 smb_fmask;
6224 
6225         if (total_data < 116) {
6226                 return NT_STATUS_INVALID_PARAMETER;
6227         }
6228 
6229         /* Start by setting all the fields that are common between UNIX_BASIC
6230          * and UNIX_INFO2.
6231          */
6232         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6233                                 fsp, fname, psbuf);
6234         if (!NT_STATUS_IS_OK(status)) {
6235                 return status;
6236         }
6237 
6238         smb_fflags = IVAL(pdata, 108);
6239         smb_fmask = IVAL(pdata, 112);
6240 
6241         /* NB: We should only attempt to alter the file flags if the client
6242          * sends a non-zero mask.
6243          */
6244         if (smb_fmask != 0) {
6245                 int stat_fflags = 0;
6246 
6247                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6248                             &stat_fflags)) {
6249                         /* Client asked to alter a flag we don't understand. */
6250                         return NT_STATUS_INVALID_PARAMETER;
6251                 }
6252 
6253                 if (fsp && fsp->fh->fd != -1) {
6254                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
6255                         return NT_STATUS_NOT_SUPPORTED;
6256                 } else {
6257                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6258                                 return map_nt_error_from_unix(errno);
6259                         }
6260                 }
6261         }
6262 
6263         /* XXX: need to add support for changing the create_time here. You
6264          * can do this for paths on Darwin with setattrlist(2). The right way
6265          * to hook this up is probably by extending the VFS utimes interface.
6266          */
6267 
6268         return NT_STATUS_OK;
6269 }
6270 
6271 /****************************************************************************
6272  Create a directory with POSIX semantics.
6273 ****************************************************************************/
6274 
6275 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6276                                 struct smb_request *req,
6277                                 char **ppdata,
6278                                 int total_data,
6279                                 const char *fname,
6280                                 SMB_STRUCT_STAT *psbuf,
6281                                 int *pdata_return_size)
6282 {
6283         NTSTATUS status = NT_STATUS_OK;
6284         uint32 raw_unixmode = 0;
6285         uint32 mod_unixmode = 0;
6286         mode_t unixmode = (mode_t)0;
6287         files_struct *fsp = NULL;
6288         uint16 info_level_return = 0;
6289         int info;
6290         char *pdata = *ppdata;
6291 
6292         if (total_data < 18) {
6293                 return NT_STATUS_INVALID_PARAMETER;
6294         }
6295 
6296         raw_unixmode = IVAL(pdata,8);
6297         /* Next 4 bytes are not yet defined. */
6298 
6299         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6300         if (!NT_STATUS_IS_OK(status)) {
6301                 return status;
6302         }
6303 
6304         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6305 
6306         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6307                 fname, (unsigned int)unixmode ));
6308 
6309         status = SMB_VFS_CREATE_FILE(
6310                 conn,                                   /* conn */
6311                 req,                                    /* req */
6312                 0,                                      /* root_dir_fid */
6313                 fname,                                  /* fname */
6314                 0,                                      /* create_file_flags */
6315                 FILE_READ_ATTRIBUTES,                   /* access_mask */
6316                 FILE_SHARE_NONE,                        /* share_access */
6317                 FILE_CREATE,                            /* create_disposition*/
6318                 FILE_DIRECTORY_FILE,                    /* create_options */
6319                 mod_unixmode,                           /* file_attributes */
6320                 0,                                      /* oplock_request */
6321                 0,                                      /* allocation_size */
6322                 NULL,                                   /* sd */
6323                 NULL,                                   /* ea_list */
6324                 &fsp,                                   /* result */
6325                 &info,                                  /* pinfo */
6326                 psbuf);                                 /* psbuf */
6327 
6328         if (NT_STATUS_IS_OK(status)) {
6329                 close_file(req, fsp, NORMAL_CLOSE);
6330         }
6331 
6332         info_level_return = SVAL(pdata,16);
6333  
6334         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6335                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6336         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6337                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6338         } else {
6339                 *pdata_return_size = 12;
6340         }
6341 
6342         /* Realloc the data size */
6343         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6344         if (*ppdata == NULL) {
6345                 *pdata_return_size = 0;
6346                 return NT_STATUS_NO_MEMORY;
6347         }
6348         pdata = *ppdata;
6349 
6350         SSVAL(pdata,0,NO_OPLOCK_RETURN);
6351         SSVAL(pdata,2,0); /* No fnum. */
6352         SIVAL(pdata,4,info); /* Was directory created. */
6353 
6354         switch (info_level_return) {
6355                 case SMB_QUERY_FILE_UNIX_BASIC:
6356                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6357                         SSVAL(pdata,10,0); /* Padding. */
6358                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6359                         break;
6360                 case SMB_QUERY_FILE_UNIX_INFO2:
6361                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6362                         SSVAL(pdata,10,0); /* Padding. */
6363                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6364                         break;
6365                 default:
6366                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6367                         SSVAL(pdata,10,0); /* Padding. */
6368                         break;
6369         }
6370 
6371         return status;
6372 }
6373 
6374 /****************************************************************************
6375  Open/Create a file with POSIX semantics.
6376 ****************************************************************************/
6377 
6378 static NTSTATUS smb_posix_open(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6379                                struct smb_request *req,
6380                                 char **ppdata,
6381                                 int total_data,
6382                                 const char *fname,
6383                                 SMB_STRUCT_STAT *psbuf,
6384                                 int *pdata_return_size)
6385 {
6386         bool extended_oplock_granted = False;
6387         char *pdata = *ppdata;
6388         uint32 flags = 0;
6389         uint32 wire_open_mode = 0;
6390         uint32 raw_unixmode = 0;
6391         uint32 mod_unixmode = 0;
6392         uint32 create_disp = 0;
6393         uint32 access_mask = 0;
6394         uint32 create_options = 0;
6395         NTSTATUS status = NT_STATUS_OK;
6396         mode_t unixmode = (mode_t)0;
6397         files_struct *fsp = NULL;
6398         int oplock_request = 0;
6399         int info = 0;
6400         uint16 info_level_return = 0;
6401 
6402         if (total_data < 18) {
6403                 return NT_STATUS_INVALID_PARAMETER;
6404         }
6405 
6406         flags = IVAL(pdata,0);
6407         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6408         if (oplock_request) {
6409                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6410         }
6411 
6412         wire_open_mode = IVAL(pdata,4);
6413 
6414         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6415                 return smb_posix_mkdir(conn, req,
6416                                         ppdata,
6417                                         total_data,
6418                                         fname,
6419                                         psbuf,
6420                                         pdata_return_size);
6421         }
6422 
6423         switch (wire_open_mode & SMB_ACCMODE) {
6424                 case SMB_O_RDONLY:
6425                         access_mask = FILE_READ_DATA;
6426                         break;
6427                 case SMB_O_WRONLY:
6428                         access_mask = FILE_WRITE_DATA;
6429                         break;
6430                 case SMB_O_RDWR:
6431                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6432                         break;
6433                 default:
6434                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6435                                 (unsigned int)wire_open_mode ));
6436                         return NT_STATUS_INVALID_PARAMETER;
6437         }
6438 
6439         wire_open_mode &= ~SMB_ACCMODE;
6440 
6441         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6442                 create_disp = FILE_CREATE;
6443         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6444                 create_disp = FILE_OVERWRITE_IF;
6445         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6446                 create_disp = FILE_OPEN_IF;
6447         } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6448                 create_disp = FILE_OPEN;
6449         } else {
6450                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6451                         (unsigned int)wire_open_mode ));
6452                 return NT_STATUS_INVALID_PARAMETER;
6453         }
6454 
6455         raw_unixmode = IVAL(pdata,8);
6456         /* Next 4 bytes are not yet defined. */
6457 
6458         status = unix_perms_from_wire(conn,
6459                                 psbuf,
6460                                 raw_unixmode,
6461                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6462                                 &unixmode);
6463 
6464         if (!NT_STATUS_IS_OK(status)) {
6465                 return status;
6466         }
6467 
6468         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6469 
6470         if (wire_open_mode & SMB_O_SYNC) {
6471                 create_options |= FILE_WRITE_THROUGH;
6472         }
6473         if (wire_open_mode & SMB_O_APPEND) {
6474                 access_mask |= FILE_APPEND_DATA;
6475         }
6476         if (wire_open_mode & SMB_O_DIRECT) {
6477                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6478         }
6479 
6480         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6481                 fname,
6482                 (unsigned int)wire_open_mode,
6483                 (unsigned int)unixmode ));
6484 
6485         status = SMB_VFS_CREATE_FILE(
6486                 conn,                                   /* conn */
6487                 req,                                    /* req */
6488                 0,                                      /* root_dir_fid */
6489                 fname,                                  /* fname */
6490                 0,                                      /* create_file_flags */
6491                 access_mask,                            /* access_mask */
6492                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6493                     FILE_SHARE_DELETE),
6494                 create_disp,                            /* create_disposition*/
6495                 FILE_NON_DIRECTORY_FILE,                /* create_options */
6496                 mod_unixmode,                           /* file_attributes */
6497                 oplock_request,                         /* oplock_request */
6498                 0,                                      /* allocation_size */
6499                 NULL,                                   /* sd */
6500                 NULL,                                   /* ea_list */
6501                 &fsp,                                   /* result */
6502                 &info,                                  /* pinfo */
6503                 psbuf);                                 /* psbuf */
6504 
6505         if (!NT_STATUS_IS_OK(status)) {
6506                 return status;
6507         }
6508 
6509         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6510                 extended_oplock_granted = True;
6511         }
6512 
6513         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6514                 extended_oplock_granted = True;
6515         }
6516 
6517         info_level_return = SVAL(pdata,16);
6518  
6519         /* Allocate the correct return size. */
6520 
6521         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6522                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6523         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6524                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6525         } else {
6526                 *pdata_return_size = 12;
6527         }
6528 
6529         /* Realloc the data size */
6530         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6531         if (*ppdata == NULL) {
6532                 close_file(req, fsp, ERROR_CLOSE);
6533                 *pdata_return_size = 0;
6534                 return NT_STATUS_NO_MEMORY;
6535         }
6536         pdata = *ppdata;
6537 
6538         if (extended_oplock_granted) {
6539                 if (flags & REQUEST_BATCH_OPLOCK) {
6540                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6541                 } else {
6542                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6543                 }
6544         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6545                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6546         } else {
6547                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6548         }
6549 
6550         SSVAL(pdata,2,fsp->fnum);
6551         SIVAL(pdata,4,info); /* Was file created etc. */
6552 
6553         switch (info_level_return) {
6554                 case SMB_QUERY_FILE_UNIX_BASIC:
6555                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6556                         SSVAL(pdata,10,0); /* padding. */
6557                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6558                         break;
6559                 case SMB_QUERY_FILE_UNIX_INFO2:
6560                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6561                         SSVAL(pdata,10,0); /* padding. */
6562                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6563                         break;
6564                 default:
6565                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6566                         SSVAL(pdata,10,0); /* padding. */
6567                         break;
6568         }
6569         return NT_STATUS_OK;
6570 }
6571 
6572 /****************************************************************************
6573  Delete a file with POSIX semantics.
6574 ****************************************************************************/
6575 
6576 static NTSTATUS smb_posix_unlink(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6577                                  struct smb_request *req,
6578                                 const char *pdata,
6579                                 int total_data,
6580                                 const char *fname,
6581                                 SMB_STRUCT_STAT *psbuf)
6582 {
6583         NTSTATUS status = NT_STATUS_OK;
6584         files_struct *fsp = NULL;
6585         uint16 flags = 0;
6586         char del = 1;
6587         int info = 0;
6588         int create_options = 0;
6589         int i;
6590         struct share_mode_lock *lck = NULL;
6591 
6592         if (total_data < 2) {
6593                 return NT_STATUS_INVALID_PARAMETER;
6594         }
6595 
6596         flags = SVAL(pdata,0);
6597 
6598         if (!VALID_STAT(*psbuf)) {
6599                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6600         }
6601 
6602         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6603                         !VALID_STAT_OF_DIR(*psbuf)) {
6604                 return NT_STATUS_NOT_A_DIRECTORY;
6605         }
6606 
6607         DEBUG(10,("smb_posix_unlink: %s %s\n",
6608                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6609                 fname));
6610 
6611         if (VALID_STAT_OF_DIR(*psbuf)) {
6612                 create_options |= FILE_DIRECTORY_FILE;
6613         }
6614 
6615         status = SMB_VFS_CREATE_FILE(
6616                 conn,                                   /* conn */
6617                 req,                                    /* req */
6618                 0,                                      /* root_dir_fid */
6619                 fname,                                  /* fname */
6620                 0,                                      /* create_file_flags */
6621                 DELETE_ACCESS,                          /* access_mask */
6622                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6623                     FILE_SHARE_DELETE),
6624                 FILE_OPEN,                              /* create_disposition*/
6625                 create_options,                         /* create_options */
6626                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
6627                 0,                                      /* oplock_request */
6628                 0,                                      /* allocation_size */
6629                 NULL,                                   /* sd */
6630                 NULL,                                   /* ea_list */
6631                 &fsp,                                   /* result */
6632                 &info,                                  /* pinfo */
6633                 psbuf);                                 /* psbuf */
6634 
6635         if (!NT_STATUS_IS_OK(status)) {
6636                 return status;
6637         }
6638 
6639         /*
6640          * Don't lie to client. If we can't really delete due to
6641          * non-POSIX opens return SHARING_VIOLATION.
6642          */
6643 
6644         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6645                                   NULL);
6646         if (lck == NULL) {
6647                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6648                         "lock for file %s\n", fsp->fsp_name));
6649                 close_file(req, fsp, NORMAL_CLOSE);
6650                 return NT_STATUS_INVALID_PARAMETER;
6651         }
6652 
6653         /*
6654          * See if others still have the file open. If this is the case, then
6655          * don't delete. If all opens are POSIX delete we can set the delete
6656          * on close disposition.
6657          */
6658         for (i=0; i<lck->num_share_modes; i++) {
6659                 struct share_mode_entry *e = &lck->share_modes[i];
6660                 if (is_valid_share_mode_entry(e)) {
6661                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6662                                 continue;
6663                         }
6664                         /* Fail with sharing violation. */
6665                         close_file(req, fsp, NORMAL_CLOSE);
6666                         TALLOC_FREE(lck);
6667                         return NT_STATUS_SHARING_VIOLATION;
6668                 }
6669         }
6670 
6671         /*
6672          * Set the delete on close.
6673          */
6674         status = smb_set_file_disposition_info(conn,
6675                                                 &del,
6676                                                 1,
6677                                                 fsp,
6678                                                 fname,
6679                                                 psbuf);
6680 
6681         if (!NT_STATUS_IS_OK(status)) {
6682                 close_file(req, fsp, NORMAL_CLOSE);
6683                 TALLOC_FREE(lck);
6684                 return status;
6685         }
6686         TALLOC_FREE(lck);
6687         return close_file(req, fsp, NORMAL_CLOSE);
6688 }
6689 
6690 /****************************************************************************
6691  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6692 ****************************************************************************/
6693 
6694 static void call_trans2setfilepathinfo(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
6695                                        struct smb_request *req,
6696                                        unsigned int tran_call,
6697                                        char **pparams, int total_params,
6698                                        char **ppdata, int total_data,
6699                                        unsigned int max_data_bytes)
6700 {
6701         char *params = *pparams;
6702         char *pdata = *ppdata;
6703         uint16 info_level;
6704         SMB_STRUCT_STAT sbuf;
6705         char *fname = NULL;
6706         files_struct *fsp = NULL;
6707         NTSTATUS status = NT_STATUS_OK;
6708         int data_return_size = 0;
6709         TALLOC_CTX *ctx = talloc_tos();
6710 
6711         if (!params) {
6712                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6713                 return;
6714         }
6715 
6716         ZERO_STRUCT(sbuf);
6717 
6718         if (tran_call == TRANSACT2_SETFILEINFO) {
6719                 if (total_params < 4) {
6720                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6721                         return;
6722                 }
6723 
6724                 fsp = file_fsp(req, SVAL(params,0));
6725                 /* Basic check for non-null fsp. */
6726                 if (!check_fsp_open(conn, req, fsp)) {
6727                         return;
6728                 }
6729                 info_level = SVAL(params,2);
6730 
6731                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6732                 if (!fname) {
6733                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6734                         return;
6735                 }
6736 
6737                 if(fsp->is_directory || fsp->fh->fd == -1) {
6738                         /*
6739                          * This is actually a SETFILEINFO on a directory
6740                          * handle (returned from an NT SMB). NT5.0 seems
6741                          * to do this call. JRA.
6742                          */
6743                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6744                                 /* Always do lstat for UNIX calls. */
6745                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6746                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6747                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6748                                         return;
6749                                 }
6750                         } else {
6751                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6752                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6753                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6754                                         return;
6755                                 }
6756                         }
6757                 } else if (fsp->print_file) {
6758                         /*
6759                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6760                          */
6761                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6762                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6763 
6764                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6765 
6766                                 SSVAL(params,0,0);
6767                                 send_trans2_replies(conn, req, params, 2,
6768                                                     *ppdata, 0,
6769                                                     max_data_bytes);
6770                                 return;
6771                         } else {
6772                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6773                                 return;
6774                         }
6775                 } else {
6776                         /*
6777                          * Original code - this is an open file.
6778                          */
6779                         if (!check_fsp(conn, req, fsp)) {
6780                                 return;
6781                         }
6782 
6783                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6784                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6785                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6786                                 return;
6787                         }
6788                 }
6789         } else {
6790                 /* set path info */
6791                 if (total_params < 7) {
6792                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6793                         return;
6794                 }
6795 
6796                 info_level = SVAL(params,0);
6797                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6798                                 total_params - 6, STR_TERMINATE,
6799                                 &status);
6800                 if (!NT_STATUS_IS_OK(status)) {
6801                         reply_nterror(req, status);
6802                         return;
6803                 }
6804 
6805                 status = resolve_dfspath(ctx, conn,
6806                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6807                                          fname,
6808                                          &fname);
6809                 if (!NT_STATUS_IS_OK(status)) {
6810                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6811                                 reply_botherror(req,
6812                                                 NT_STATUS_PATH_NOT_COVERED,
6813                                                 ERRSRV, ERRbadpath);
6814                                 return;
6815                         }
6816                         reply_nterror(req, status);
6817                         return;
6818                 }
6819 
6820                 status = unix_convert(ctx, conn, fname, False,
6821                                 &fname, NULL, &sbuf);
6822                 if (!NT_STATUS_IS_OK(status)) {
6823                         reply_nterror(req, status);
6824                         return;
6825                 }
6826 
6827                 status = check_name(conn, fname);
6828                 if (!NT_STATUS_IS_OK(status)) {
6829                         reply_nterror(req, status);
6830                         return;
6831                 }
6832 
6833                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6834                         /*
6835                          * For CIFS UNIX extensions the target name may not exist.
6836                          */
6837 
6838                         /* Always do lstat for UNIX calls. */
6839                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6840 
6841                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6842                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6843                         reply_unixerror(req, ERRDOS, ERRbadpath);
6844                         return;
6845                 }
6846         }
6847 
6848         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6849                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6850                 return;
6851         }
6852 
6853         if (!CAN_WRITE(conn)) {
6854                 /* Allow POSIX opens. The open path will deny
6855                  * any non-readonly opens. */
6856                 if (info_level != SMB_POSIX_PATH_OPEN) {
6857                         reply_doserror(req, ERRSRV, ERRaccess);
6858                         return;
6859                 }
6860         }
6861 
6862         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6863                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6864 
6865         /* Realloc the parameter size */
6866         *pparams = (char *)SMB_REALLOC(*pparams,2);
6867         if (*pparams == NULL) {
6868                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6869                 return;
6870         }
6871         params = *pparams;
6872 
6873         SSVAL(params,0,0);
6874 
6875         switch (info_level) {
6876 
6877                 case SMB_INFO_STANDARD:
6878                 {
6879                         status = smb_set_info_standard(conn,
6880                                         pdata,
6881                                         total_data,
6882                                         fsp,
6883                                         fname,
6884                                         &sbuf);
6885                         break;
6886                 }
6887 
6888                 case SMB_INFO_SET_EA:
6889                 {
6890                         status = smb_info_set_ea(conn,
6891                                                 pdata,
6892                                                 total_data,
6893                                                 fsp,
6894                                                 fname);
6895                         break;
6896                 }
6897 
6898                 case SMB_SET_FILE_BASIC_INFO:
6899                 case SMB_FILE_BASIC_INFORMATION:
6900                 {
6901                         status = smb_set_file_basic_info(conn,
6902                                                         pdata,
6903                                                         total_data,
6904                                                         fsp,
6905                                                         fname,
6906                                                         &sbuf);
6907                         break;
6908                 }
6909 
6910                 case SMB_FILE_ALLOCATION_INFORMATION:
6911                 case SMB_SET_FILE_ALLOCATION_INFO:
6912                 {
6913                         status = smb_set_file_allocation_info(conn, req,
6914                                                                 pdata,
6915                                                                 total_data,
6916                                                                 fsp,
6917                                                                 fname,
6918                                                                 &sbuf);
6919                         break;
6920                 }
6921 
6922                 case SMB_FILE_END_OF_FILE_INFORMATION:
6923                 case SMB_SET_FILE_END_OF_FILE_INFO:
6924                 {
6925                         status = smb_set_file_end_of_file_info(conn, req,
6926                                                                 pdata,
6927                                                                 total_data,
6928                                                                 fsp,
6929                                                                 fname,
6930                                                                 &sbuf);
6931                         break;
6932                 }
6933 
6934                 case SMB_FILE_DISPOSITION_INFORMATION:
6935                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6936                 {
6937 #if 0
6938                         /* JRA - We used to just ignore this on a path ? 
6939                          * Shouldn't this be invalid level on a pathname
6940                          * based call ?
6941                          */
6942                         if (tran_call != TRANSACT2_SETFILEINFO) {
6943                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6944                         }
6945 #endif
6946                         status = smb_set_file_disposition_info(conn,
6947                                                 pdata,
6948                                                 total_data,
6949                                                 fsp,
6950                                                 fname,
6951                                                 &sbuf);
6952                         break;
6953                 }
6954 
6955                 case SMB_FILE_POSITION_INFORMATION:
6956                 {
6957                         status = smb_file_position_information(conn,
6958                                                 pdata,
6959                                                 total_data,
6960                                                 fsp);
6961                         break;
6962                 }
6963 
6964                 /* From tridge Samba4 : 
6965                  * MODE_INFORMATION in setfileinfo (I have no
6966                  * idea what "mode information" on a file is - it takes a value of 0,
6967                  * 2, 4 or 6. What could it be?).
6968                  */
6969 
6970                 case SMB_FILE_MODE_INFORMATION:
6971                 {
6972                         status = smb_file_mode_information(conn,
6973                                                 pdata,
6974                                                 total_data);
6975                         break;
6976                 }
6977 
6978                 /*
6979                  * CIFS UNIX extensions.
6980                  */
6981 
6982                 case SMB_SET_FILE_UNIX_BASIC:
6983                 {
6984                         status = smb_set_file_unix_basic(conn, req,
6985                                                         pdata,
6986                                                         total_data,
6987                                                         fsp,
6988                                                         fname,
6989                                                         &sbuf);
6990                         break;
6991                 }
6992 
6993                 case SMB_SET_FILE_UNIX_INFO2:
6994                 {
6995                         status = smb_set_file_unix_info2(conn, req,
6996                                                         pdata,
6997                                                         total_data,
6998                                                         fsp,
6999                                                         fname,
7000                                                         &sbuf);
7001                         break;
7002                 }
7003 
7004                 case SMB_SET_FILE_UNIX_LINK:
7005                 {
7006                         if (tran_call != TRANSACT2_SETPATHINFO) {
7007                                 /* We must have a pathname for this. */
7008                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7009                                 return;
7010                         }
7011                         status = smb_set_file_unix_link(conn, req, pdata,
7012                                                         total_data, fname);
7013                         break;
7014                 }
7015 
7016                 case SMB_SET_FILE_UNIX_HLINK:
7017                 {
7018                         if (tran_call != TRANSACT2_SETPATHINFO) {
7019                                 /* We must have a pathname for this. */
7020                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7021                                 return;
7022                         }
7023                         status = smb_set_file_unix_hlink(conn, req,
7024                                                          pdata, total_data,
7025                                                          fname);
7026                         break;
7027                 }
7028 
7029                 case SMB_FILE_RENAME_INFORMATION:
7030                 {
7031                         status = smb_file_rename_information(conn, req,
7032                                                              pdata, total_data,
7033                                                              fsp, fname);
7034                         break;
7035                 }
7036 
7037 #if defined(HAVE_POSIX_ACLS)
7038                 case SMB_SET_POSIX_ACL:
7039                 {
7040                         status = smb_set_posix_acl(conn,
7041                                                 pdata,
7042                                                 total_data,
7043                                                 fsp,
7044                                                 fname,
7045                                                 &sbuf);
7046                         break;
7047                 }
7048 #endif
7049 
7050                 case SMB_SET_POSIX_LOCK:
7051                 {
7052                         if (tran_call != TRANSACT2_SETFILEINFO) {
7053                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7054                                 return;
7055                         }
7056                         status = smb_set_posix_lock(conn, req,
7057                                                     pdata, total_data, fsp);
7058                         break;
7059                 }
7060 
7061                 case SMB_POSIX_PATH_OPEN:
7062                 {
7063                         if (tran_call != TRANSACT2_SETPATHINFO) {
7064                                 /* We must have a pathname for this. */
7065                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7066                                 return;
7067                         }
7068 
7069                         status = smb_posix_open(conn, req,
7070                                                 ppdata,
7071                                                 total_data,
7072                                                 fname,
7073                                                 &sbuf,
7074                                                 &data_return_size);
7075                         break;
7076                 }
7077 
7078                 case SMB_POSIX_PATH_UNLINK:
7079                 {
7080                         if (tran_call != TRANSACT2_SETPATHINFO) {
7081                                 /* We must have a pathname for this. */
7082                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7083                                 return;
7084                         }
7085 
7086                         status = smb_posix_unlink(conn, req,
7087                                                 pdata,
7088                                                 total_data,
7089                                                 fname,
7090                                                 &sbuf);
7091                         break;
7092                 }
7093 
7094                 default:
7095                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7096                         return;
7097         }
7098 
7099         
7100         if (!NT_STATUS_IS_OK(status)) {
7101                 if (open_was_deferred(req->mid)) {
7102                         /* We have re-scheduled this call. */
7103                         return;
7104                 }
7105                 if (blocking_lock_was_deferred(req->mid)) {
7106                         /* We have re-scheduled this call. */
7107                         return;
7108                 }
7109                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7110                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7111                                         ERRSRV, ERRbadpath);
7112                         return;
7113                 }
7114                 if (info_level == SMB_POSIX_PATH_OPEN) {
7115                         reply_openerror(req, status);
7116                         return;
7117                 }
7118 
7119                 reply_nterror(req, status);
7120                 return;
7121         }
7122 
7123         SSVAL(params,0,0);
7124         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7125                             max_data_bytes);
7126   
7127         return;
7128 }
7129 
7130 /****************************************************************************
7131  Reply to a TRANS2_MKDIR (make directory with extended attributes).
7132 ****************************************************************************/
7133 
7134 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
7135                              char **pparams, int total_params,
7136                              char **ppdata, int total_data,
7137                              unsigned int max_data_bytes)
7138 {
7139         char *params = *pparams;
7140         char *pdata = *ppdata;
7141         char *directory = NULL;
7142         SMB_STRUCT_STAT sbuf;
7143         NTSTATUS status = NT_STATUS_OK;
7144         struct ea_list *ea_list = NULL;
7145         TALLOC_CTX *ctx = talloc_tos();
7146 
7147         if (!CAN_WRITE(conn)) {
7148                 reply_doserror(req, ERRSRV, ERRaccess);
7149                 return;
7150         }
7151 
7152         if (total_params < 5) {
7153                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7154                 return;
7155         }
7156 
7157         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7158                         total_params - 4, STR_TERMINATE,
7159                         &status);
7160         if (!NT_STATUS_IS_OK(status)) {
7161                 reply_nterror(req, status);
7162                 return;
7163         }
7164 
7165         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7166 
7167         status = resolve_dfspath(ctx,
7168                                 conn,
7169                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
7170                                 directory,
7171                                 &directory);
7172         if (!NT_STATUS_IS_OK(status)) {
7173                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7174                         reply_botherror(req,
7175                                         NT_STATUS_PATH_NOT_COVERED,
7176                                         ERRSRV, ERRbadpath);
7177                 }
7178                 reply_nterror(req, status);
7179                 return;
7180         }
7181 
7182         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7183         if (!NT_STATUS_IS_OK(status)) {
7184                 reply_nterror(req, status);
7185                 return;
7186         }
7187 
7188         status = check_name(conn, directory);
7189         if (!NT_STATUS_IS_OK(status)) {
7190                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7191                 reply_nterror(req, status);
7192                 return;
7193         }
7194 
7195         /* Any data in this call is an EA list. */
7196         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7197                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7198                 return;
7199         }
7200 
7201         /*
7202          * OS/2 workplace shell seems to send SET_EA requests of "null"
7203          * length (4 bytes containing IVAL 4).
7204          * They seem to have no effect. Bug #3212. JRA.
7205          */
7206 
7207         if (total_data != 4) {
7208                 if (total_data < 10) {
7209                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7210                         return;
7211                 }
7212 
7213                 if (IVAL(pdata,0) > total_data) {
7214                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7215                                 IVAL(pdata,0), (unsigned int)total_data));
7216                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7217                         return;
7218                 }
7219 
7220                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7221                                        total_data - 4);
7222                 if (!ea_list) {
7223                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7224                         return;
7225                 }
7226         }
7227         /* If total_data == 4 Windows doesn't care what values
7228          * are placed in that field, it just ignores them.
7229          * The System i QNTC IBM SMB client puts bad values here,
7230          * so ignore them. */
7231 
7232         status = create_directory(conn, req, directory);
7233 
7234         if (!NT_STATUS_IS_OK(status)) {
7235                 reply_nterror(req, status);
7236                 return;
7237         }
7238   
7239         /* Try and set any given EA. */
7240         if (ea_list) {
7241                 status = set_ea(conn, NULL, directory, ea_list);
7242                 if (!NT_STATUS_IS_OK(status)) {
7243                         reply_nterror(req, status);
7244                         return;
7245                 }
7246         }
7247 
7248         /* Realloc the parameter and data sizes */
7249         *pparams = (char *)SMB_REALLOC(*pparams,2);
7250         if(*pparams == NULL) {
7251                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7252                 return;
7253         }
7254         params = *pparams;
7255 
7256         SSVAL(params,0,0);
7257 
7258         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7259   
7260         return;
7261 }
7262 
7263 /****************************************************************************
7264  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7265  We don't actually do this - we just send a null response.
7266 ****************************************************************************/
7267 
7268 static void call_trans2findnotifyfirst(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
7269                                        struct smb_request *req,
7270                                        char **pparams, int total_params,
7271                                        char **ppdata, int total_data,
7272                                        unsigned int max_data_bytes)
7273 {
7274         char *params = *pparams;
7275         uint16 info_level;
7276 
7277         if (total_params < 6) {
7278                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7279                 return;
7280         }
7281 
7282         info_level = SVAL(params,4);
7283         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7284 
7285         switch (info_level) {
7286                 case 1:
7287                 case 2:
7288                         break;
7289                 default:
7290                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7291                         return;
7292         }
7293 
7294         /* Realloc the parameter and data sizes */
7295         *pparams = (char *)SMB_REALLOC(*pparams,6);
7296         if (*pparams == NULL) {
7297                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7298                 return;
7299         }
7300         params = *pparams;
7301 
7302         SSVAL(params,0,fnf_handle);
7303         SSVAL(params,2,0); /* No changes */
7304         SSVAL(params,4,0); /* No EA errors */
7305 
7306         fnf_handle++;
7307 
7308         if(fnf_handle == 0)
7309                 fnf_handle = 257;
7310 
7311         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7312   
7313         return;
7314 }
7315 
7316 /****************************************************************************
7317  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
7318  changes). Currently this does nothing.
7319 ****************************************************************************/
7320 
7321 static void call_trans2findnotifynext(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
7322                                       struct smb_request *req,
7323                                       char **pparams, int total_params,
7324                                       char **ppdata, int total_data,
7325                                       unsigned int max_data_bytes)
7326 {
7327         char *params = *pparams;
7328 
7329         DEBUG(3,("call_trans2findnotifynext\n"));
7330 
7331         /* Realloc the parameter and data sizes */
7332         *pparams = (char *)SMB_REALLOC(*pparams,4);
7333         if (*pparams == NULL) {
7334                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7335                 return;
7336         }
7337         params = *pparams;
7338 
7339         SSVAL(params,0,0); /* No changes */
7340         SSVAL(params,2,0); /* No EA errors */
7341 
7342         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7343   
7344         return;
7345 }
7346 
7347 /****************************************************************************
7348  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7349 ****************************************************************************/
7350 
7351 static void call_trans2getdfsreferral(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
7352                                       struct smb_request *req,
7353                                       char **pparams, int total_params,
7354                                       char **ppdata, int total_data,
7355                                       unsigned int max_data_bytes)
7356 {
7357         char *params = *pparams;
7358         char *pathname = NULL;
7359         int reply_size = 0;
7360         int max_referral_level;
7361         NTSTATUS status = NT_STATUS_OK;
7362         TALLOC_CTX *ctx = talloc_tos();
7363 
7364         DEBUG(10,("call_trans2getdfsreferral\n"));
7365 
7366         if (total_params < 3) {
7367                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7368                 return;
7369         }
7370 
7371         max_referral_level = SVAL(params,0);
7372 
7373         if(!lp_host_msdfs()) {
7374                 reply_doserror(req, ERRDOS, ERRbadfunc);
7375                 return;
7376         }
7377 
7378         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7379                     total_params - 2, STR_TERMINATE);
7380         if (!pathname) {
7381                 reply_nterror(req, NT_STATUS_NOT_FOUND);
7382                 return;
7383         }
7384         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7385                                             ppdata,&status)) < 0) {
7386                 reply_nterror(req, status);
7387                 return;
7388         }
7389 
7390         SSVAL(req->inbuf, smb_flg2,
7391               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7392         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7393 
7394         return;
7395 }
7396 
7397 #define LMCAT_SPL       0x53
7398 #define LMFUNC_GETJOBID 0x60
7399 
7400 /****************************************************************************
7401  Reply to a TRANS2_IOCTL - used for OS/2 printing.
7402 ****************************************************************************/
7403 
7404 static void call_trans2ioctl(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
7405                              struct smb_request *req,
7406                              char **pparams, int total_params,
7407                              char **ppdata, int total_data,
7408                              unsigned int max_data_bytes)
7409 {
7410         char *pdata = *ppdata;
7411         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7412 
7413         /* check for an invalid fid before proceeding */
7414 
7415         if (!fsp) {
7416                 reply_doserror(req, ERRDOS, ERRbadfid);
7417                 return;
7418         }
7419 
7420         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7421             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7422                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7423                 if (*ppdata == NULL) {
7424                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7425                         return;
7426                 }
7427                 pdata = *ppdata;
7428 
7429                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7430                         CAN ACCEPT THIS IN UNICODE. JRA. */
7431 
7432                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
7433                 srvstr_push(pdata, req->flags2, pdata + 2,
7434                             global_myname(), 15,
7435                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7436                 srvstr_push(pdata, req->flags2, pdata+18,
7437                             lp_servicename(SNUM(conn)), 13,
7438                             STR_ASCII|STR_TERMINATE); /* Service name */
7439                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7440                                     max_data_bytes);
7441                 return;
7442         }
7443 
7444         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7445         reply_doserror(req, ERRSRV, ERRerror);
7446 }
7447 
7448 /****************************************************************************
7449  Reply to a SMBfindclose (stop trans2 directory search).
7450 ****************************************************************************/
7451 
7452 void reply_findclose(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
7453 {
7454         int dptr_num;
7455 
7456         START_PROFILE(SMBfindclose);
7457 
7458         if (req->wct < 1) {
7459                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7460                 END_PROFILE(SMBfindclose);
7461                 return;
7462         }
7463 
7464         dptr_num = SVALS(req->vwv+0, 0);
7465 
7466         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7467 
7468         dptr_close(&dptr_num);
7469 
7470         reply_outbuf(req, 0, 0);
7471 
7472         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7473 
7474         END_PROFILE(SMBfindclose);
7475         return;
7476 }
7477 
7478 /****************************************************************************
7479  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7480 ****************************************************************************/
7481 
7482 void reply_findnclose(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
7483 {
7484         int dptr_num;
7485 
7486         START_PROFILE(SMBfindnclose);
7487 
7488         if (req->wct < 1) {
7489                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7490                 END_PROFILE(SMBfindnclose);
7491                 return;
7492         }
7493         
7494         dptr_num = SVAL(req->vwv+0, 0);
7495 
7496         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7497 
7498         /* We never give out valid handles for a 
7499            findnotifyfirst - so any dptr_num is ok here. 
7500            Just ignore it. */
7501 
7502         reply_outbuf(req, 0, 0);
7503 
7504         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7505 
7506         END_PROFILE(SMBfindnclose);
7507         return;
7508 }
7509 
7510 static void handle_trans2(connection_struct *conn, struct smb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
7511                           struct trans_state *state)
7512 {
7513         if (Protocol >= PROTOCOL_NT1) {
7514                 req->flags2 |= 0x40; /* IS_LONG_NAME */
7515                 SSVAL(req->inbuf,smb_flg2,req->flags2);
7516         }
7517 
7518         if (conn->encrypt_level == Required && !req->encrypted) {
7519                 if (state->call != TRANSACT2_QFSINFO &&
7520                                 state->call != TRANSACT2_SETFSINFO) {
7521                         DEBUG(0,("handle_trans2: encryption required "
7522                                 "with call 0x%x\n",
7523                                 (unsigned int)state->call));
7524                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7525                         return;
7526                 }
7527         }
7528 
7529         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7530 
7531         /* Now we must call the relevant TRANS2 function */
7532         switch(state->call)  {
7533         case TRANSACT2_OPEN:
7534         {
7535                 START_PROFILE(Trans2_open);
7536                 call_trans2open(conn, req,
7537                                 &state->param, state->total_param,
7538                                 &state->data, state->total_data,
7539                                 state->max_data_return);
7540                 END_PROFILE(Trans2_open);
7541                 break;
7542         }
7543 
7544         case TRANSACT2_FINDFIRST:
7545         {
7546                 START_PROFILE(Trans2_findfirst);
7547                 call_trans2findfirst(conn, req,
7548                                      &state->param, state->total_param,
7549                                      &state->data, state->total_data,
7550                                      state->max_data_return);
7551                 END_PROFILE(Trans2_findfirst);
7552                 break;
7553         }
7554 
7555         case TRANSACT2_FINDNEXT:
7556         {
7557                 START_PROFILE(Trans2_findnext);
7558                 call_trans2findnext(conn, req,
7559                                     &state->param, state->total_param,
7560                                     &state->data, state->total_data,
7561                                     state->max_data_return);
7562                 END_PROFILE(Trans2_findnext);
7563                 break;
7564         }
7565 
7566         case TRANSACT2_QFSINFO:
7567         {
7568                 START_PROFILE(Trans2_qfsinfo);
7569                 call_trans2qfsinfo(conn, req,
7570                                    &state->param, state->total_param,
7571                                    &state->data, state->total_data,
7572                                    state->max_data_return);
7573                 END_PROFILE(Trans2_qfsinfo);
7574             break;
7575         }
7576 
7577         case TRANSACT2_SETFSINFO:
7578         {
7579                 START_PROFILE(Trans2_setfsinfo);
7580                 call_trans2setfsinfo(conn, req,
7581                                      &state->param, state->total_param,
7582                                      &state->data, state->total_data,
7583                                      state->max_data_return);
7584                 END_PROFILE(Trans2_setfsinfo);
7585                 break;
7586         }
7587 
7588         case TRANSACT2_QPATHINFO:
7589         case TRANSACT2_QFILEINFO:
7590         {
7591                 START_PROFILE(Trans2_qpathinfo);
7592                 call_trans2qfilepathinfo(conn, req, state->call,
7593                                          &state->param, state->total_param,
7594                                          &state->data, state->total_data,
7595                                          state->max_data_return);
7596                 END_PROFILE(Trans2_qpathinfo);
7597                 break;
7598         }
7599 
7600         case TRANSACT2_SETPATHINFO:
7601         case TRANSACT2_SETFILEINFO:
7602         {
7603                 START_PROFILE(Trans2_setpathinfo);
7604                 call_trans2setfilepathinfo(conn, req, state->call,
7605                                            &state->param, state->total_param,
7606                                            &state->data, state->total_data,
7607                                            state->max_data_return);
7608                 END_PROFILE(Trans2_setpathinfo);
7609                 break;
7610         }
7611 
7612         case TRANSACT2_FINDNOTIFYFIRST:
7613         {
7614                 START_PROFILE(Trans2_findnotifyfirst);
7615                 call_trans2findnotifyfirst(conn, req,
7616                                            &state->param, state->total_param,
7617                                            &state->data, state->total_data,
7618                                            state->max_data_return);
7619                 END_PROFILE(Trans2_findnotifyfirst);
7620                 break;
7621         }
7622 
7623         case TRANSACT2_FINDNOTIFYNEXT:
7624         {
7625                 START_PROFILE(Trans2_findnotifynext);
7626                 call_trans2findnotifynext(conn, req,
7627                                           &state->param, state->total_param,
7628                                           &state->data, state->total_data,
7629                                           state->max_data_return);
7630                 END_PROFILE(Trans2_findnotifynext);
7631                 break;
7632         }
7633 
7634         case TRANSACT2_MKDIR:
7635         {
7636                 START_PROFILE(Trans2_mkdir);
7637                 call_trans2mkdir(conn, req,
7638                                  &state->param, state->total_param,
7639                                  &state->data, state->total_data,
7640                                  state->max_data_return);
7641                 END_PROFILE(Trans2_mkdir);
7642                 break;
7643         }
7644 
7645         case TRANSACT2_GET_DFS_REFERRAL:
7646         {
7647                 START_PROFILE(Trans2_get_dfs_referral);
7648                 call_trans2getdfsreferral(conn, req,
7649                                           &state->param, state->total_param,
7650                                           &state->data, state->total_data,
7651                                           state->max_data_return);
7652                 END_PROFILE(Trans2_get_dfs_referral);
7653                 break;
7654         }
7655 
7656         case TRANSACT2_IOCTL:
7657         {
7658                 START_PROFILE(Trans2_ioctl);
7659                 call_trans2ioctl(conn, req,
7660                                  &state->param, state->total_param,
7661                                  &state->data, state->total_data,
7662                                  state->max_data_return);
7663                 END_PROFILE(Trans2_ioctl);
7664                 break;
7665         }
7666 
7667         default:
7668                 /* Error in request */
7669                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7670                 reply_doserror(req, ERRSRV,ERRerror);
7671         }
7672 }
7673 
7674 /****************************************************************************
7675  Reply to a SMBtrans2.
7676  ****************************************************************************/
7677 
7678 void reply_trans2(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
7679 {
7680         connection_struct *conn = req->conn;
7681         unsigned int dsoff;
7682         unsigned int dscnt;
7683         unsigned int psoff;
7684         unsigned int pscnt;
7685         unsigned int tran_call;
7686         struct trans_state *state;
7687         NTSTATUS result;
7688 
7689         START_PROFILE(SMBtrans2);
7690 
7691         if (req->wct < 14) {
7692                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7693                 END_PROFILE(SMBtrans2);
7694                 return;
7695         }
7696 
7697         dsoff = SVAL(req->vwv+12, 0);
7698         dscnt = SVAL(req->vwv+11, 0);
7699         psoff = SVAL(req->vwv+10, 0);
7700         pscnt = SVAL(req->vwv+9, 0);
7701         tran_call = SVAL(req->vwv+14, 0);
7702 
7703         result = allow_new_trans(conn->pending_trans, req->mid);
7704         if (!NT_STATUS_IS_OK(result)) {
7705                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7706                           nt_errstr(result)));
7707                 reply_nterror(req, result);
7708                 END_PROFILE(SMBtrans2);
7709                 return;
7710         }
7711 
7712         if (IS_IPC(conn)) {
7713                 switch (tran_call) {
7714                 /* List the allowed trans2 calls on IPC$ */
7715                 case TRANSACT2_OPEN:
7716                 case TRANSACT2_GET_DFS_REFERRAL:
7717                 case TRANSACT2_QFILEINFO:
7718                 case TRANSACT2_QFSINFO:
7719                 case TRANSACT2_SETFSINFO:
7720                         break;
7721                 default:
7722                         reply_doserror(req, ERRSRV, ERRaccess);
7723                         END_PROFILE(SMBtrans2);
7724                         return;
7725                 }
7726         }
7727 
7728         if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7729                 DEBUG(0, ("talloc failed\n"));
7730                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7731                 END_PROFILE(SMBtrans2);
7732                 return;
7733         }
7734 
7735         state->cmd = SMBtrans2;
7736 
7737         state->mid = req->mid;
7738         state->vuid = req->vuid;
7739         state->setup_count = SVAL(req->vwv+13, 0);
7740         state->setup = NULL;
7741         state->total_param = SVAL(req->vwv+0, 0);
7742         state->param = NULL;
7743         state->total_data =  SVAL(req->vwv+1, 0);
7744         state->data = NULL;
7745         state->max_param_return = SVAL(req->vwv+2, 0);
7746         state->max_data_return  = SVAL(req->vwv+3, 0);
7747         state->max_setup_return = SVAL(req->vwv+4, 0);
7748         state->close_on_completion = BITSETW(req->vwv+5, 0);
7749         state->one_way = BITSETW(req->vwv+5, 1);
7750 
7751         state->call = tran_call;
7752 
7753         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7754            is so as a sanity check */
7755         if (state->setup_count != 1) {
7756                 /*
7757                  * Need to have rc=0 for ioctl to get job id for OS/2.
7758                  *  Network printing will fail if function is not successful.
7759                  *  Similar function in reply.c will be used if protocol
7760                  *  is LANMAN1.0 instead of LM1.2X002.
7761                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7762                  *  outbuf doesn't have to be set(only job id is used).
7763                  */
7764                 if ( (state->setup_count == 4)
7765                      && (tran_call == TRANSACT2_IOCTL)
7766                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7767                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7768                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7769                 } else {
7770                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7771                         DEBUG(2,("Transaction is %d\n",tran_call));
7772                         TALLOC_FREE(state);
7773                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7774                         END_PROFILE(SMBtrans2);
7775                         return;
7776                 }
7777         }
7778 
7779         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7780                 goto bad_param;
7781 
7782         if (state->total_data) {
7783 
7784                 if (trans_oob(state->total_data, 0, dscnt)
7785                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7786                         goto bad_param;
7787                 }
7788 
7789                 /* Can't use talloc here, the core routines do realloc on the
7790                  * params and data. */
7791                 state->data = (char *)SMB_MALLOC(state->total_data);
7792                 if (state->data == NULL) {
7793                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7794                                  "bytes !\n", (unsigned int)state->total_data));
7795                         TALLOC_FREE(state);
7796                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7797                         END_PROFILE(SMBtrans2);
7798                         return;
7799                 }
7800 
7801                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7802         }
7803 
7804         if (state->total_param) {
7805 
7806                 if (trans_oob(state->total_param, 0, pscnt)
7807                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7808                         goto bad_param;
7809                 }
7810 
7811                 /* Can't use talloc here, the core routines do realloc on the
7812                  * params and data. */
7813                 state->param = (char *)SMB_MALLOC(state->total_param);
7814                 if (state->param == NULL) {
7815                         DEBUG(0,("reply_trans: param malloc fail for %u "
7816                                  "bytes !\n", (unsigned int)state->total_param));
7817                         SAFE_FREE(state->data);
7818                         TALLOC_FREE(state);
7819                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7820                         END_PROFILE(SMBtrans2);
7821                         return;
7822                 } 
7823 
7824                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7825         }
7826 
7827         state->received_data  = dscnt;
7828         state->received_param = pscnt;
7829 
7830         if ((state->received_param == state->total_param) &&
7831             (state->received_data == state->total_data)) {
7832 
7833                 handle_trans2(conn, req, state);
7834 
7835                 SAFE_FREE(state->data);
7836                 SAFE_FREE(state->param);
7837                 TALLOC_FREE(state);
7838                 END_PROFILE(SMBtrans2);
7839                 return;
7840         }
7841 
7842         DLIST_ADD(conn->pending_trans, state);
7843 
7844         /* We need to send an interim response then receive the rest
7845            of the parameter/data bytes */
7846         reply_outbuf(req, 0, 0);
7847         show_msg((char *)req->outbuf);
7848         END_PROFILE(SMBtrans2);
7849         return;
7850 
7851   bad_param:
7852 
7853         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7854         SAFE_FREE(state->data);
7855         SAFE_FREE(state->param);
7856         TALLOC_FREE(state);
7857         END_PROFILE(SMBtrans2);
7858         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7859 }
7860 
7861 
7862 /****************************************************************************
7863  Reply to a SMBtranss2
7864  ****************************************************************************/
7865 
7866 void reply_transs2(struct smb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
7867 {
7868         connection_struct *conn = req->conn;
7869         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7870         struct trans_state *state;
7871 
7872         START_PROFILE(SMBtranss2);
7873 
7874         show_msg((char *)req->inbuf);
7875 
7876         if (req->wct < 8) {
7877                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7878                 END_PROFILE(SMBtranss2);
7879                 return;
7880         }
7881 
7882         for (state = conn->pending_trans; state != NULL;
7883              state = state->next) {
7884                 if (state->mid == req->mid) {
7885                         break;
7886                 }
7887         }
7888 
7889         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7890                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7891                 END_PROFILE(SMBtranss2);
7892                 return;
7893         }
7894 
7895         /* Revise state->total_param and state->total_data in case they have
7896            changed downwards */
7897 
7898         if (SVAL(req->vwv+0, 0) < state->total_param)
7899                 state->total_param = SVAL(req->vwv+0, 0);
7900         if (SVAL(req->vwv+1, 0) < state->total_data)
7901                 state->total_data = SVAL(req->vwv+1, 0);
7902 
7903         pcnt = SVAL(req->vwv+2, 0);
7904         poff = SVAL(req->vwv+3, 0);
7905         pdisp = SVAL(req->vwv+4, 0);
7906 
7907         dcnt = SVAL(req->vwv+5, 0);
7908         doff = SVAL(req->vwv+6, 0);
7909         ddisp = SVAL(req->vwv+7, 0);
7910 
7911         state->received_param += pcnt;
7912         state->received_data += dcnt;
7913                 
7914         if ((state->received_data > state->total_data) ||
7915             (state->received_param > state->total_param))
7916                 goto bad_param;
7917 
7918         if (pcnt) {
7919                 if (trans_oob(state->total_param, pdisp, pcnt)
7920                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7921                         goto bad_param;
7922                 }
7923                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7924         }
7925 
7926         if (dcnt) {
7927                 if (trans_oob(state->total_data, ddisp, dcnt)
7928                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7929                         goto bad_param;
7930                 }
7931                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7932         }
7933 
7934         if ((state->received_param < state->total_param) ||
7935             (state->received_data < state->total_data)) {
7936                 END_PROFILE(SMBtranss2);
7937                 return;
7938         }
7939 
7940         handle_trans2(conn, req, state);
7941 
7942         DLIST_REMOVE(conn->pending_trans, state);
7943         SAFE_FREE(state->data);
7944         SAFE_FREE(state->param);
7945         TALLOC_FREE(state);
7946 
7947         END_PROFILE(SMBtranss2);
7948         return;
7949 
7950   bad_param:
7951 
7952         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7953         DLIST_REMOVE(conn->pending_trans, state);
7954         SAFE_FREE(state->data);
7955         SAFE_FREE(state->param);
7956         TALLOC_FREE(state);
7957         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7958         END_PROFILE(SMBtranss2);
7959         return;
7960 }

/* [<][>][^][v][top][bottom][index][help] */