00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 extern int max_send;
00030 extern enum protocol_types Protocol;
00031 extern int smb_read_error;
00032 extern uint32 global_client_caps;
00033 extern struct current_user current_user;
00034
00035 #define get_file_size(sbuf) ((sbuf).st_size)
00036 #define DIR_ENTRY_SAFETY_MARGIN 4096
00037
00038 static char *store_file_unix_basic(connection_struct *conn,
00039 char *pdata,
00040 files_struct *fsp,
00041 const SMB_STRUCT_STAT *psbuf);
00042
00043 static char *store_file_unix_basic_info2(connection_struct *conn,
00044 char *pdata,
00045 files_struct *fsp,
00046 const SMB_STRUCT_STAT *psbuf);
00047
00048
00049
00050
00051
00052
00053 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
00054 {
00055 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
00056
00057
00058 enum remote_arch_types ra_type = get_remote_arch();
00059 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
00060 val = SMB_ROUNDUP(val,rval);
00061 }
00062 return val;
00063 }
00064
00065
00066
00067
00068
00069
00070 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
00071 {
00072 SMB_BIG_UINT ret;
00073
00074 if(S_ISDIR(sbuf->st_mode)) {
00075 return 0;
00076 }
00077
00078 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
00079 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
00080 #else
00081 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
00082 #endif
00083
00084 if (fsp && fsp->initial_allocation_size)
00085 ret = MAX(ret,fsp->initial_allocation_size);
00086
00087 return smb_roundup(conn, ret);
00088 }
00089
00090
00091
00092
00093
00094 static const char *prohibited_ea_names[] = {
00095 SAMBA_POSIX_INHERITANCE_EA_NAME,
00096 SAMBA_XATTR_DOS_ATTRIB,
00097 NULL
00098 };
00099
00100
00101
00102
00103
00104 static BOOL samba_private_attr_name(const char *unix_ea_name)
00105 {
00106 int i;
00107
00108 for (i = 0; prohibited_ea_names[i]; i++) {
00109 if (strequal( prohibited_ea_names[i], unix_ea_name))
00110 return True;
00111 }
00112 return False;
00113 }
00114
00115
00116
00117
00118
00119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
00120 const char *fname, char *ea_name, struct ea_struct *pea)
00121 {
00122
00123 size_t attr_size = 256;
00124 char *val = NULL;
00125 ssize_t sizeret;
00126
00127 again:
00128
00129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
00130 if (!val) {
00131 return False;
00132 }
00133
00134 if (fsp && fsp->fh->fd != -1) {
00135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
00136 } else {
00137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
00138 }
00139
00140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
00141 attr_size = 65536;
00142 goto again;
00143 }
00144
00145 if (sizeret == -1) {
00146 return False;
00147 }
00148
00149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
00150 dump_data(10, val, sizeret);
00151
00152 pea->flags = 0;
00153 if (strnequal(ea_name, "user.", 5)) {
00154 pea->name = &ea_name[5];
00155 } else {
00156 pea->name = ea_name;
00157 }
00158 pea->value.data = (unsigned char *)val;
00159 pea->value.length = (size_t)sizeret;
00160 return True;
00161 }
00162
00163
00164
00165
00166
00167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
00168 const char *fname, size_t *pea_total_len)
00169 {
00170
00171 size_t ea_namelist_size = 1024;
00172 char *ea_namelist;
00173 char *p;
00174 ssize_t sizeret;
00175 int i;
00176 struct ea_list *ea_list_head = NULL;
00177
00178 *pea_total_len = 0;
00179
00180 if (!lp_ea_support(SNUM(conn))) {
00181 return NULL;
00182 }
00183
00184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
00185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
00186
00187 if (!ea_namelist) {
00188 return NULL;
00189 }
00190
00191 if (fsp && fsp->fh->fd != -1) {
00192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
00193 } else {
00194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
00195 }
00196
00197 if (sizeret == -1 && errno == ERANGE) {
00198 ea_namelist_size *= 2;
00199 } else {
00200 break;
00201 }
00202 }
00203
00204 if (sizeret == -1)
00205 return NULL;
00206
00207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
00208
00209 if (sizeret) {
00210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
00211 struct ea_list *listp;
00212
00213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
00214 continue;
00215
00216 listp = TALLOC_P(mem_ctx, struct ea_list);
00217 if (!listp)
00218 return NULL;
00219
00220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
00221 return NULL;
00222 }
00223
00224 {
00225 fstring dos_ea_name;
00226 push_ascii_fstring(dos_ea_name, listp->ea.name);
00227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
00228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
00229 (unsigned int)*pea_total_len, dos_ea_name,
00230 (unsigned int)listp->ea.value.length ));
00231 }
00232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
00233 }
00234
00235 if (*pea_total_len) {
00236 *pea_total_len += 4;
00237 }
00238 }
00239
00240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
00241 return ea_list_head;
00242 }
00243
00244
00245
00246
00247
00248
00249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
00250 connection_struct *conn, struct ea_list *ea_list)
00251 {
00252 unsigned int ret_data_size = 4;
00253 char *p = pdata;
00254
00255 SMB_ASSERT(total_data_size >= 4);
00256
00257 if (!lp_ea_support(SNUM(conn))) {
00258 SIVAL(pdata,4,0);
00259 return 4;
00260 }
00261
00262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
00263 size_t dos_namelen;
00264 fstring dos_ea_name;
00265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
00266 dos_namelen = strlen(dos_ea_name);
00267 if (dos_namelen > 255 || dos_namelen == 0) {
00268 break;
00269 }
00270 if (ea_list->ea.value.length > 65535) {
00271 break;
00272 }
00273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
00274 break;
00275 }
00276
00277
00278 SCVAL(p,0,ea_list->ea.flags);
00279 SCVAL(p,1,dos_namelen);
00280 SSVAL(p,2,ea_list->ea.value.length);
00281 fstrcpy(p+4, dos_ea_name);
00282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
00283
00284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
00285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
00286 }
00287
00288 ret_data_size = PTR_DIFF(p, pdata);
00289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
00290 SIVAL(pdata,0,ret_data_size);
00291 return ret_data_size;
00292 }
00293
00294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
00295 {
00296 size_t total_ea_len = 0;
00297 TALLOC_CTX *mem_ctx = NULL;
00298
00299 if (!lp_ea_support(SNUM(conn))) {
00300 return 0;
00301 }
00302 mem_ctx = talloc_init("estimate_ea_size");
00303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
00304 talloc_destroy(mem_ctx);
00305 return total_ea_len;
00306 }
00307
00308
00309
00310
00311
00312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
00313 {
00314 size_t total_ea_len;
00315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
00316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
00317
00318 for (; ea_list; ea_list = ea_list->next) {
00319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
00320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
00321 &unix_ea_name[5], ea_list->ea.name));
00322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
00323 break;
00324 }
00325 }
00326 talloc_destroy(mem_ctx);
00327 }
00328
00329
00330
00331
00332
00333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
00334 {
00335 if (!lp_ea_support(SNUM(conn))) {
00336 return NT_STATUS_EAS_NOT_SUPPORTED;
00337 }
00338
00339 for (;ea_list; ea_list = ea_list->next) {
00340 int ret;
00341 fstring unix_ea_name;
00342
00343 fstrcpy(unix_ea_name, "user.");
00344 fstrcat(unix_ea_name, ea_list->ea.name);
00345
00346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
00347
00348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
00349
00350 if (samba_private_attr_name(unix_ea_name)) {
00351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
00352 return NT_STATUS_ACCESS_DENIED;
00353 }
00354
00355 if (ea_list->ea.value.length == 0) {
00356
00357 if (fsp && (fsp->fh->fd != -1)) {
00358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
00359 unix_ea_name, fsp->fsp_name));
00360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
00361 } else {
00362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
00363 unix_ea_name, fname));
00364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
00365 }
00366 #ifdef ENOATTR
00367
00368 if (ret == -1 && errno == ENOATTR) {
00369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
00370 unix_ea_name));
00371 ret = 0;
00372 }
00373 #endif
00374 } else {
00375 if (fsp && (fsp->fh->fd != -1)) {
00376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
00377 unix_ea_name, fsp->fsp_name));
00378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
00379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
00380 } else {
00381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
00382 unix_ea_name, fname));
00383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
00384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
00385 }
00386 }
00387
00388 if (ret == -1) {
00389 #ifdef ENOTSUP
00390 if (errno == ENOTSUP) {
00391 return NT_STATUS_EAS_NOT_SUPPORTED;
00392 }
00393 #endif
00394 return map_nt_error_from_unix(errno);
00395 }
00396
00397 }
00398 return NT_STATUS_OK;
00399 }
00400
00401
00402
00403
00404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
00405 {
00406 struct ea_list *ea_list_head = NULL;
00407 size_t offset = 0;
00408
00409 while (offset + 2 < data_size) {
00410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
00411 unsigned int namelen = CVAL(pdata,offset);
00412
00413 offset++;
00414
00415
00416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
00417 (offset > data_size) || (namelen > data_size) ||
00418 (offset + namelen >= data_size)) {
00419 break;
00420 }
00421
00422 if (pdata[offset + namelen] != '\0') {
00423 return NULL;
00424 }
00425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
00426 if (!eal->ea.name) {
00427 return NULL;
00428 }
00429
00430 offset += (namelen + 1);
00431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
00432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
00433 }
00434
00435 return ea_list_head;
00436 }
00437
00438
00439
00440
00441
00442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
00443 {
00444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
00445 uint16 val_len;
00446 unsigned int namelen;
00447
00448 if (!eal) {
00449 return NULL;
00450 }
00451
00452 if (data_size < 6) {
00453 return NULL;
00454 }
00455
00456 eal->ea.flags = CVAL(pdata,0);
00457 namelen = CVAL(pdata,1);
00458 val_len = SVAL(pdata,2);
00459
00460 if (4 + namelen + 1 + val_len > data_size) {
00461 return NULL;
00462 }
00463
00464
00465 if (pdata[namelen + 4] != '\0') {
00466 return NULL;
00467 }
00468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
00469 if (!eal->ea.name) {
00470 return NULL;
00471 }
00472
00473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
00474 if (!eal->ea.value.data) {
00475 return NULL;
00476 }
00477
00478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
00479
00480
00481 eal->ea.value.data[val_len] = '\0';
00482
00483 eal->ea.value.length--;
00484
00485 if (pbytes_used) {
00486 *pbytes_used = 4 + namelen + 1 + val_len;
00487 }
00488
00489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
00490 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
00491
00492 return eal;
00493 }
00494
00495
00496
00497
00498
00499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
00500 {
00501 struct ea_list *ea_list_head = NULL;
00502 size_t offset = 0;
00503 size_t bytes_used = 0;
00504
00505 while (offset < data_size) {
00506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
00507
00508 if (!eal) {
00509 return NULL;
00510 }
00511
00512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
00513 offset += bytes_used;
00514 }
00515
00516 return ea_list_head;
00517 }
00518
00519
00520
00521
00522
00523 static size_t ea_list_size(struct ea_list *ealist)
00524 {
00525 fstring dos_ea_name;
00526 struct ea_list *listp;
00527 size_t ret = 0;
00528
00529 for (listp = ealist; listp; listp = listp->next) {
00530 push_ascii_fstring(dos_ea_name, listp->ea.name);
00531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
00532 }
00533
00534 if (ret) {
00535 ret += 4;
00536 }
00537
00538 return ret;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
00548 {
00549 struct ea_list *nlistp, *flistp;
00550
00551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
00552 for (flistp = file_list; flistp; flistp = flistp->next) {
00553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
00554 break;
00555 }
00556 }
00557
00558 if (flistp) {
00559
00560 nlistp->ea.flags = flistp->ea.flags;
00561 nlistp->ea.value = flistp->ea.value;
00562 } else {
00563
00564 nlistp->ea.flags = 0;
00565 ZERO_STRUCT(nlistp->ea.value);
00566 }
00567 }
00568
00569 *total_ea_len = ea_list_size(name_list);
00570 return name_list;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580 int send_trans2_replies(char *outbuf,
00581 int bufsize,
00582 const char *params,
00583 int paramsize,
00584 const char *pdata,
00585 int datasize,
00586 int max_data_bytes)
00587 {
00588
00589
00590
00591
00592
00593
00594 int data_to_send = datasize;
00595 int params_to_send = paramsize;
00596 int useable_space;
00597 const char *pp = params;
00598 const char *pd = pdata;
00599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
00600 int alignment_offset = 1;
00601 int data_alignment_offset = 0;
00602
00603
00604
00605 set_message(outbuf,10,0,True);
00606
00607
00608
00609
00610
00611
00612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
00613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
00614 max_data_bytes, datasize ));
00615 datasize = data_to_send = max_data_bytes;
00616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
00617 }
00618
00619
00620
00621 if(params_to_send == 0 && data_to_send == 0) {
00622 show_msg(outbuf);
00623 if (!send_smb(smbd_server_fd(),outbuf))
00624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
00625 return 0;
00626 }
00627
00628
00629
00630
00631
00632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
00633 data_alignment_offset = 4 - (params_to_send % 4);
00634
00635
00636
00637
00638
00639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
00640
00641
00642
00643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
00644
00645 while (params_to_send || data_to_send) {
00646
00647
00648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
00659
00660 set_message(outbuf, 10, total_sent_thistime, True);
00661
00662
00663 SSVAL(outbuf,smb_tprcnt,paramsize);
00664 SSVAL(outbuf,smb_tdrcnt,datasize);
00665
00666
00667
00668
00669
00670 params_sent_thistime = MIN(params_to_send,useable_space);
00671 data_sent_thistime = useable_space - params_sent_thistime;
00672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
00673
00674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
00675
00676
00677
00678
00679
00680
00681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
00682
00683 if(params_sent_thistime == 0)
00684 SSVAL(outbuf,smb_prdisp,0);
00685 else
00686
00687 SSVAL(outbuf,smb_prdisp,pp - params);
00688
00689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
00690 if(data_sent_thistime == 0) {
00691 SSVAL(outbuf,smb_droff,0);
00692 SSVAL(outbuf,smb_drdisp, 0);
00693 } else {
00694
00695
00696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
00697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
00698 SSVAL(outbuf,smb_drdisp, pd - pdata);
00699 }
00700
00701
00702
00703 if(params_sent_thistime)
00704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
00705
00706
00707 if(data_sent_thistime)
00708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
00709 data_alignment_offset,pd,data_sent_thistime);
00710
00711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
00712 params_sent_thistime, data_sent_thistime, useable_space));
00713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
00714 params_to_send, data_to_send, paramsize, datasize));
00715
00716
00717 show_msg(outbuf);
00718 if (!send_smb(smbd_server_fd(),outbuf))
00719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
00720
00721 pp += params_sent_thistime;
00722 pd += data_sent_thistime;
00723
00724 params_to_send -= params_sent_thistime;
00725 data_to_send -= data_sent_thistime;
00726
00727
00728 if(params_to_send < 0 || data_to_send < 0) {
00729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
00730 params_to_send, data_to_send));
00731 return -1;
00732 }
00733 }
00734
00735 return 0;
00736 }
00737
00738
00739
00740
00741
00742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
00743 char **pparams, int total_params, char **ppdata, int total_data,
00744 unsigned int max_data_bytes)
00745 {
00746 char *params = *pparams;
00747 char *pdata = *ppdata;
00748 int deny_mode;
00749 int32 open_attr;
00750 BOOL oplock_request;
00751 #if 0
00752 BOOL return_additional_info;
00753 int16 open_sattr;
00754 time_t open_time;
00755 #endif
00756 int open_ofun;
00757 uint32 open_size;
00758 char *pname;
00759 pstring fname;
00760 SMB_OFF_T size=0;
00761 int fattr=0,mtime=0;
00762 SMB_INO_T inode = 0;
00763 SMB_STRUCT_STAT sbuf;
00764 int smb_action = 0;
00765 files_struct *fsp;
00766 struct ea_list *ea_list = NULL;
00767 uint16 flags = 0;
00768 NTSTATUS status;
00769 uint32 access_mask;
00770 uint32 share_mode;
00771 uint32 create_disposition;
00772 uint32 create_options = 0;
00773
00774
00775
00776
00777
00778 if (total_params < 29) {
00779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00780 }
00781
00782 flags = SVAL(params, 0);
00783 deny_mode = SVAL(params, 2);
00784 open_attr = SVAL(params,6);
00785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
00786 if (oplock_request) {
00787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
00788 }
00789
00790 #if 0
00791 return_additional_info = BITSETW(params,0);
00792 open_sattr = SVAL(params, 4);
00793 open_time = make_unix_date3(params+8);
00794 #endif
00795 open_ofun = SVAL(params,12);
00796 open_size = IVAL(params,14);
00797 pname = ¶ms[28];
00798
00799 if (IS_IPC(conn)) {
00800 return(ERROR_DOS(ERRSRV,ERRaccess));
00801 }
00802
00803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
00804 if (!NT_STATUS_IS_OK(status)) {
00805 return ERROR_NT(status);
00806 }
00807
00808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
00809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
00810 (unsigned int)open_ofun, open_size));
00811
00812
00813
00814 status = unix_convert(conn, fname, False, NULL, &sbuf);
00815 if (!NT_STATUS_IS_OK(status)) {
00816 return ERROR_NT(status);
00817 }
00818
00819 status = check_name(conn, fname);
00820 if (!NT_STATUS_IS_OK(status)) {
00821 return ERROR_NT(status);
00822 }
00823
00824 if (open_ofun == 0) {
00825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
00826 }
00827
00828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
00829 &access_mask,
00830 &share_mode,
00831 &create_disposition,
00832 &create_options)) {
00833 return ERROR_DOS(ERRDOS, ERRbadaccess);
00834 }
00835
00836
00837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
00838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
00839 }
00840
00841 if (total_data != 4) {
00842 if (total_data < 10) {
00843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00844 }
00845
00846 if (IVAL(pdata,0) > total_data) {
00847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
00848 IVAL(pdata,0), (unsigned int)total_data));
00849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00850 }
00851
00852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
00853 total_data - 4);
00854 if (!ea_list) {
00855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00856 }
00857 } else if (IVAL(pdata,0) != 4) {
00858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00859 }
00860
00861 status = open_file_ntcreate(conn,fname,&sbuf,
00862 access_mask,
00863 share_mode,
00864 create_disposition,
00865 create_options,
00866 open_attr,
00867 oplock_request,
00868 &smb_action, &fsp);
00869
00870 if (!NT_STATUS_IS_OK(status)) {
00871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
00872
00873 return -1;
00874 }
00875 return ERROR_OPEN(status);
00876 }
00877
00878 size = get_file_size(sbuf);
00879 fattr = dos_mode(conn,fname,&sbuf);
00880 mtime = sbuf.st_mtime;
00881 inode = sbuf.st_ino;
00882 if (fattr & aDIR) {
00883 close_file(fsp,ERROR_CLOSE);
00884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
00885 }
00886
00887
00888
00889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
00890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
00891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
00892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
00893 if (fsp->is_directory) {
00894 close_file(fsp,ERROR_CLOSE);
00895
00896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
00897 }
00898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
00899 close_file(fsp,ERROR_CLOSE);
00900 return ERROR_NT(NT_STATUS_DISK_FULL);
00901 }
00902
00903
00904
00905 size = fsp->initial_allocation_size;
00906 } else {
00907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
00908 }
00909 }
00910
00911 if (ea_list && smb_action == FILE_WAS_CREATED) {
00912 status = set_ea(conn, fsp, fname, ea_list);
00913 if (!NT_STATUS_IS_OK(status)) {
00914 close_file(fsp,ERROR_CLOSE);
00915 return ERROR_NT(status);
00916 }
00917 }
00918
00919
00920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
00921 if(*pparams == NULL ) {
00922 return ERROR_NT(NT_STATUS_NO_MEMORY);
00923 }
00924 params = *pparams;
00925
00926 SSVAL(params,0,fsp->fnum);
00927 SSVAL(params,2,fattr);
00928 srv_put_dos_date2(params,4, mtime);
00929 SIVAL(params,8, (uint32)size);
00930 SSVAL(params,12,deny_mode);
00931 SSVAL(params,14,0);
00932 SSVAL(params,16,0);
00933
00934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
00935 smb_action |= EXTENDED_OPLOCK_GRANTED;
00936 }
00937
00938 SSVAL(params,18,smb_action);
00939
00940
00941
00942
00943 SIVAL(params,20,inode);
00944 SSVAL(params,24,0);
00945 if (flags & 8) {
00946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
00947 SIVAL(params, 26, ea_size);
00948 } else {
00949 SIVAL(params, 26, 0);
00950 }
00951
00952
00953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
00954
00955 return -1;
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
00966 {
00967 if (mask[0] == '.' && mask[1] == 0)
00968 return False;
00969 if (conn->case_sensitive)
00970 return strcmp(str,mask)==0;
00971 if (StrCaseCmp(str,mask) != 0) {
00972 return False;
00973 }
00974 if (dptr_has_wild(conn->dirptr)) {
00975 return False;
00976 }
00977 return True;
00978 }
00979
00980
00981
00982
00983
00984 static uint32 unix_filetype(mode_t mode)
00985 {
00986 if(S_ISREG(mode))
00987 return UNIX_TYPE_FILE;
00988 else if(S_ISDIR(mode))
00989 return UNIX_TYPE_DIR;
00990 #ifdef S_ISLNK
00991 else if(S_ISLNK(mode))
00992 return UNIX_TYPE_SYMLINK;
00993 #endif
00994 #ifdef S_ISCHR
00995 else if(S_ISCHR(mode))
00996 return UNIX_TYPE_CHARDEV;
00997 #endif
00998 #ifdef S_ISBLK
00999 else if(S_ISBLK(mode))
01000 return UNIX_TYPE_BLKDEV;
01001 #endif
01002 #ifdef S_ISFIFO
01003 else if(S_ISFIFO(mode))
01004 return UNIX_TYPE_FIFO;
01005 #endif
01006 #ifdef S_ISSOCK
01007 else if(S_ISSOCK(mode))
01008 return UNIX_TYPE_SOCKET;
01009 #endif
01010
01011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
01012 return UNIX_TYPE_UNKNOWN;
01013 }
01014
01015
01016
01017
01018
01019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
01020
01021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
01022 SMB_STRUCT_STAT *psbuf,
01023 uint32 perms,
01024 enum perm_type ptype,
01025 mode_t *ret_perms)
01026 {
01027 mode_t ret = 0;
01028
01029 if (perms == SMB_MODE_NO_CHANGE) {
01030 if (!VALID_STAT(*psbuf)) {
01031 return NT_STATUS_INVALID_PARAMETER;
01032 } else {
01033 *ret_perms = psbuf->st_mode;
01034 return NT_STATUS_OK;
01035 }
01036 }
01037
01038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
01039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
01040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
01041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
01042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
01043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
01044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
01045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
01046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
01047 #ifdef S_ISVTX
01048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
01049 #endif
01050 #ifdef S_ISGID
01051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
01052 #endif
01053 #ifdef S_ISUID
01054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
01055 #endif
01056
01057 switch (ptype) {
01058 case PERM_NEW_FILE:
01059
01060 ret &= lp_create_mask(SNUM(conn));
01061
01062 ret |= lp_force_create_mode(SNUM(conn));
01063 break;
01064 case PERM_NEW_DIR:
01065 ret &= lp_dir_mask(SNUM(conn));
01066
01067 ret |= lp_force_dir_mode(SNUM(conn));
01068 break;
01069 case PERM_EXISTING_FILE:
01070
01071 ret &= lp_security_mask(SNUM(conn));
01072
01073 ret |= lp_force_security_mode(SNUM(conn));
01074 break;
01075 case PERM_EXISTING_DIR:
01076
01077 ret &= lp_dir_security_mask(SNUM(conn));
01078
01079 ret |= lp_force_dir_security_mode(SNUM(conn));
01080 break;
01081 }
01082
01083 *ret_perms = ret;
01084 return NT_STATUS_OK;
01085 }
01086
01087
01088
01089
01090
01091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
01092 void *inbuf, char *outbuf,
01093 char *path_mask,uint32 dirtype,int info_level,
01094 int requires_resume_key,
01095 BOOL dont_descend,char **ppdata,
01096 char *base_data, char *end_data, int space_remaining,
01097 BOOL *out_of_space, BOOL *got_exact_match,
01098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
01099 {
01100 const char *dname;
01101 BOOL found = False;
01102 SMB_STRUCT_STAT sbuf;
01103 pstring mask;
01104 pstring pathreal;
01105 pstring fname;
01106 char *p, *q, *pdata = *ppdata;
01107 uint32 reskey=0;
01108 long prev_dirpos=0;
01109 uint32 mode=0;
01110 SMB_OFF_T file_size = 0;
01111 SMB_BIG_UINT allocation_size = 0;
01112 uint32 len;
01113 struct timespec mdate_ts, adate_ts, create_date_ts;
01114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
01115 char *nameptr;
01116 char *last_entry_ptr;
01117 BOOL was_8_3;
01118 uint32 nt_extmode;
01119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
01120 BOOL check_mangled_names = lp_manglednames(conn->params);
01121
01122 *fname = 0;
01123 *out_of_space = False;
01124 *got_exact_match = False;
01125
01126 ZERO_STRUCT(mdate_ts);
01127 ZERO_STRUCT(adate_ts);
01128 ZERO_STRUCT(create_date_ts);
01129
01130 if (!conn->dirptr)
01131 return(False);
01132
01133 p = strrchr_m(path_mask,'/');
01134 if(p != NULL) {
01135 if(p[1] == '\0')
01136 pstrcpy(mask,"*.*");
01137 else
01138 pstrcpy(mask, p+1);
01139 } else
01140 pstrcpy(mask, path_mask);
01141
01142
01143 while (!found) {
01144 BOOL got_match;
01145 BOOL ms_dfs_link = False;
01146
01147
01148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
01149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
01150
01151
01152
01153
01154
01155
01156
01157
01158 reskey = 0;
01159
01160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
01161 (long)conn->dirptr,curr_dirpos));
01162
01163 if (!dname)
01164 return(False);
01165
01166 pstrcpy(fname,dname);
01167
01168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
01169 got_match = mask_match(fname, mask, conn->case_sensitive);
01170
01171 if(!got_match && check_mangled_names &&
01172 !mangle_is_8_3(fname, False, conn->params)) {
01173
01174
01175
01176
01177
01178
01179
01180
01181 pstring newname;
01182 pstrcpy( newname, fname);
01183 mangle_map( newname, True, False, conn->params);
01184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
01185 got_match = mask_match(newname, mask, conn->case_sensitive);
01186 }
01187
01188 if(got_match) {
01189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
01190 if (dont_descend && !isdots)
01191 continue;
01192
01193 pstrcpy(pathreal,conn->dirpath);
01194 if(needslash)
01195 pstrcat(pathreal,"/");
01196 pstrcat(pathreal,dname);
01197
01198 if (INFO_LEVEL_IS_UNIX(info_level)) {
01199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
01200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
01201 pathreal,strerror(errno)));
01202 continue;
01203 }
01204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
01205 pstring link_target;
01206
01207
01208
01209
01210 if(lp_host_msdfs() &&
01211 lp_msdfs_root(SNUM(conn)) &&
01212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
01213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
01214 "as a directory\n",
01215 pathreal));
01216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
01217
01218 } else {
01219
01220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
01221 pathreal,strerror(errno)));
01222 continue;
01223 }
01224 }
01225
01226 if (ms_dfs_link) {
01227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
01228 } else {
01229 mode = dos_mode(conn,pathreal,&sbuf);
01230 }
01231
01232 if (!dir_check_ftype(conn,mode,dirtype)) {
01233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
01234 continue;
01235 }
01236
01237 if (!(mode & aDIR))
01238 file_size = get_file_size(sbuf);
01239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
01240
01241 mdate_ts = get_mtimespec(&sbuf);
01242 adate_ts = get_atimespec(&sbuf);
01243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
01244
01245 if (lp_dos_filetime_resolution(SNUM(conn))) {
01246 dos_filetime_timespec(&create_date_ts);
01247 dos_filetime_timespec(&mdate_ts);
01248 dos_filetime_timespec(&adate_ts);
01249 }
01250
01251 create_date = convert_timespec_to_time_t(create_date_ts);
01252 mdate = convert_timespec_to_time_t(mdate_ts);
01253 adate = convert_timespec_to_time_t(adate_ts);
01254
01255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
01256
01257 found = True;
01258
01259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
01260 }
01261 }
01262
01263 mangle_map(fname,False,True,conn->params);
01264
01265 p = pdata;
01266 last_entry_ptr = p;
01267
01268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
01269
01270 switch (info_level) {
01271 case SMB_FIND_INFO_STANDARD:
01272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
01273 if(requires_resume_key) {
01274 SIVAL(p,0,reskey);
01275 p += 4;
01276 }
01277 srv_put_dos_date2(p,0,create_date);
01278 srv_put_dos_date2(p,4,adate);
01279 srv_put_dos_date2(p,8,mdate);
01280 SIVAL(p,12,(uint32)file_size);
01281 SIVAL(p,16,(uint32)allocation_size);
01282 SSVAL(p,20,mode);
01283 p += 23;
01284 nameptr = p;
01285 p += align_string(outbuf, p, 0);
01286 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
01287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
01288 if (len > 2) {
01289 SCVAL(nameptr, -1, len - 2);
01290 } else {
01291 SCVAL(nameptr, -1, 0);
01292 }
01293 } else {
01294 if (len > 1) {
01295 SCVAL(nameptr, -1, len - 1);
01296 } else {
01297 SCVAL(nameptr, -1, 0);
01298 }
01299 }
01300 p += len;
01301 break;
01302
01303 case SMB_FIND_EA_SIZE:
01304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
01305 if(requires_resume_key) {
01306 SIVAL(p,0,reskey);
01307 p += 4;
01308 }
01309 srv_put_dos_date2(p,0,create_date);
01310 srv_put_dos_date2(p,4,adate);
01311 srv_put_dos_date2(p,8,mdate);
01312 SIVAL(p,12,(uint32)file_size);
01313 SIVAL(p,16,(uint32)allocation_size);
01314 SSVAL(p,20,mode);
01315 {
01316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
01317 SIVAL(p,22,ea_size);
01318 }
01319 p += 27;
01320 nameptr = p - 1;
01321 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE | STR_NOALIGN);
01322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
01323 if (len > 2) {
01324 len -= 2;
01325 } else {
01326 len = 0;
01327 }
01328 } else {
01329 if (len > 1) {
01330 len -= 1;
01331 } else {
01332 len = 0;
01333 }
01334 }
01335 SCVAL(nameptr,0,len);
01336 p += len;
01337 SCVAL(p,0,0); p += 1;
01338 break;
01339
01340 case SMB_FIND_EA_LIST:
01341 {
01342 struct ea_list *file_list = NULL;
01343 size_t ea_len = 0;
01344
01345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
01346 if (!name_list) {
01347 return False;
01348 }
01349 if(requires_resume_key) {
01350 SIVAL(p,0,reskey);
01351 p += 4;
01352 }
01353 srv_put_dos_date2(p,0,create_date);
01354 srv_put_dos_date2(p,4,adate);
01355 srv_put_dos_date2(p,8,mdate);
01356 SIVAL(p,12,(uint32)file_size);
01357 SIVAL(p,16,(uint32)allocation_size);
01358 SSVAL(p,20,mode);
01359 p += 22;
01360
01361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
01362 name_list = ea_list_union(name_list, file_list, &ea_len);
01363
01364
01365
01366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
01367
01368 dptr_SeekDir(conn->dirptr, prev_dirpos);
01369 *out_of_space = True;
01370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
01371 return False;
01372 }
01373
01374
01375 p += fill_ea_buffer(ea_ctx, p, space_remaining - (p - pdata), conn, name_list);
01376 nameptr = p;
01377 len = srvstr_push(outbuf, p + 1, fname, PTR_DIFF(end_data, p+1), STR_TERMINATE | STR_NOALIGN);
01378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
01379 if (len > 2) {
01380 len -= 2;
01381 } else {
01382 len = 0;
01383 }
01384 } else {
01385 if (len > 1) {
01386 len -= 1;
01387 } else {
01388 len = 0;
01389 }
01390 }
01391 SCVAL(nameptr,0,len);
01392 p += len + 1;
01393 SCVAL(p,0,0); p += 1;
01394 break;
01395 }
01396
01397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
01398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
01399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
01400 p += 4;
01401 SIVAL(p,0,reskey); p += 4;
01402 put_long_date_timespec(p,create_date_ts); p += 8;
01403 put_long_date_timespec(p,adate_ts); p += 8;
01404 put_long_date_timespec(p,mdate_ts); p += 8;
01405 put_long_date_timespec(p,mdate_ts); p += 8;
01406 SOFF_T(p,0,file_size); p += 8;
01407 SOFF_T(p,0,allocation_size); p += 8;
01408 SIVAL(p,0,nt_extmode); p += 4;
01409 q = p; p += 4;
01410 {
01411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
01412 SIVAL(p,0,ea_size);
01413 p += 4;
01414 }
01415
01416
01417
01418
01419 if (!was_8_3 && check_mangled_names) {
01420 pstring mangled_name;
01421 pstrcpy(mangled_name, fname);
01422 mangle_map(mangled_name,True,True,
01423 conn->params);
01424 mangled_name[12] = 0;
01425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
01426 if (len < 24) {
01427 memset(p + 2 + len,'\0',24 - len);
01428 }
01429 SSVAL(p, 0, len);
01430 } else {
01431 memset(p,'\0',26);
01432 }
01433 p += 2 + 24;
01434 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
01435 SIVAL(q,0,len);
01436 p += len;
01437 SIVAL(p,0,0);
01438 len = PTR_DIFF(p, pdata);
01439 len = (len + 3) & ~3;
01440 SIVAL(pdata,0,len);
01441 p = pdata + len;
01442 break;
01443
01444 case SMB_FIND_FILE_DIRECTORY_INFO:
01445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
01446 p += 4;
01447 SIVAL(p,0,reskey); p += 4;
01448 put_long_date_timespec(p,create_date_ts); p += 8;
01449 put_long_date_timespec(p,adate_ts); p += 8;
01450 put_long_date_timespec(p,mdate_ts); p += 8;
01451 put_long_date_timespec(p,mdate_ts); p += 8;
01452 SOFF_T(p,0,file_size); p += 8;
01453 SOFF_T(p,0,allocation_size); p += 8;
01454 SIVAL(p,0,nt_extmode); p += 4;
01455 len = srvstr_push(outbuf, p + 4, fname, PTR_DIFF(end_data, p+4), STR_TERMINATE_ASCII);
01456 SIVAL(p,0,len);
01457 p += 4 + len;
01458 SIVAL(p,0,0);
01459 len = PTR_DIFF(p, pdata);
01460 len = (len + 3) & ~3;
01461 SIVAL(pdata,0,len);
01462 p = pdata + len;
01463 break;
01464
01465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
01466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
01467 p += 4;
01468 SIVAL(p,0,reskey); p += 4;
01469 put_long_date_timespec(p,create_date_ts); p += 8;
01470 put_long_date_timespec(p,adate_ts); p += 8;
01471 put_long_date_timespec(p,mdate_ts); p += 8;
01472 put_long_date_timespec(p,mdate_ts); p += 8;
01473 SOFF_T(p,0,file_size); p += 8;
01474 SOFF_T(p,0,allocation_size); p += 8;
01475 SIVAL(p,0,nt_extmode); p += 4;
01476 q = p; p += 4;
01477 {
01478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
01479 SIVAL(p,0,ea_size);
01480 p +=4;
01481 }
01482 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
01483 SIVAL(q, 0, len);
01484 p += len;
01485
01486 SIVAL(p,0,0);
01487 len = PTR_DIFF(p, pdata);
01488 len = (len + 3) & ~3;
01489 SIVAL(pdata,0,len);
01490 p = pdata + len;
01491 break;
01492
01493 case SMB_FIND_FILE_NAMES_INFO:
01494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
01495 p += 4;
01496 SIVAL(p,0,reskey); p += 4;
01497 p += 4;
01498
01499
01500 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
01501 SIVAL(p, -4, len);
01502 p += len;
01503 SIVAL(p,0,0);
01504 len = PTR_DIFF(p, pdata);
01505 len = (len + 3) & ~3;
01506 SIVAL(pdata,0,len);
01507 p = pdata + len;
01508 break;
01509
01510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
01511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
01512 p += 4;
01513 SIVAL(p,0,reskey); p += 4;
01514 put_long_date_timespec(p,create_date_ts); p += 8;
01515 put_long_date_timespec(p,adate_ts); p += 8;
01516 put_long_date_timespec(p,mdate_ts); p += 8;
01517 put_long_date_timespec(p,mdate_ts); p += 8;
01518 SOFF_T(p,0,file_size); p += 8;
01519 SOFF_T(p,0,allocation_size); p += 8;
01520 SIVAL(p,0,nt_extmode); p += 4;
01521 q = p; p += 4;
01522 {
01523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
01524 SIVAL(p,0,ea_size);
01525 p +=4;
01526 }
01527 SIVAL(p,0,0); p += 4;
01528 SIVAL(p,0,sbuf.st_ino); p += 4;
01529 SIVAL(p,0,sbuf.st_dev); p += 4;
01530 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
01531 SIVAL(q, 0, len);
01532 p += len;
01533 SIVAL(p,0,0);
01534 len = PTR_DIFF(p, pdata);
01535 len = (len + 3) & ~3;
01536 SIVAL(pdata,0,len);
01537 p = pdata + len;
01538 break;
01539
01540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
01541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
01542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
01543 p += 4;
01544 SIVAL(p,0,reskey); p += 4;
01545 put_long_date_timespec(p,create_date_ts); p += 8;
01546 put_long_date_timespec(p,adate_ts); p += 8;
01547 put_long_date_timespec(p,mdate_ts); p += 8;
01548 put_long_date_timespec(p,mdate_ts); p += 8;
01549 SOFF_T(p,0,file_size); p += 8;
01550 SOFF_T(p,0,allocation_size); p += 8;
01551 SIVAL(p,0,nt_extmode); p += 4;
01552 q = p; p += 4;
01553 {
01554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
01555 SIVAL(p,0,ea_size);
01556 p +=4;
01557 }
01558
01559
01560
01561
01562 if (!was_8_3 && check_mangled_names) {
01563 pstring mangled_name;
01564 pstrcpy(mangled_name, fname);
01565 mangle_map(mangled_name,True,True,
01566 conn->params);
01567 mangled_name[12] = 0;
01568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
01569 SSVAL(p, 0, len);
01570 if (len < 24) {
01571 memset(p + 2 + len,'\0',24 - len);
01572 }
01573 SSVAL(p, 0, len);
01574 } else {
01575 memset(p,'\0',26);
01576 }
01577 p += 26;
01578 SSVAL(p,0,0); p += 2;
01579 SIVAL(p,0,sbuf.st_ino); p += 4;
01580 SIVAL(p,0,sbuf.st_dev); p += 4;
01581 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
01582 SIVAL(q,0,len);
01583 p += len;
01584 SIVAL(p,0,0);
01585 len = PTR_DIFF(p, pdata);
01586 len = (len + 3) & ~3;
01587 SIVAL(pdata,0,len);
01588 p = pdata + len;
01589 break;
01590
01591
01592
01593 case SMB_FIND_FILE_UNIX:
01594 case SMB_FIND_FILE_UNIX_INFO2:
01595 p+= 4;
01596 SIVAL(p,0,reskey); p+= 4;
01597
01598
01599
01600 if (info_level == SMB_FIND_FILE_UNIX) {
01601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
01602 p = store_file_unix_basic(conn, p,
01603 NULL, &sbuf);
01604 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
01605 } else {
01606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
01607 p = store_file_unix_basic_info2(conn, p,
01608 NULL, &sbuf);
01609 nameptr = p;
01610 p += 4;
01611 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), 0);
01612 SIVAL(nameptr, 0, len);
01613 }
01614
01615 p += len;
01616 SIVAL(p,0,0);
01617
01618 len = PTR_DIFF(p, pdata);
01619 len = (len + 3) & ~3;
01620 SIVAL(pdata,0,len);
01621 p = pdata + len;
01622
01623
01624 break;
01625
01626 default:
01627 return(False);
01628 }
01629
01630
01631 if (PTR_DIFF(p,pdata) > space_remaining) {
01632
01633 dptr_SeekDir(conn->dirptr, prev_dirpos);
01634 *out_of_space = True;
01635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
01636 return False;
01637 }
01638
01639
01640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
01641
01642 *ppdata = p;
01643
01644 return(found);
01645 }
01646
01647
01648
01649
01650
01651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
01652 char **pparams, int total_params, char **ppdata, int total_data,
01653 unsigned int max_data_bytes)
01654 {
01655
01656
01657
01658
01659
01660 char *params = *pparams;
01661 char *pdata = *ppdata;
01662 char *data_end;
01663 uint32 dirtype;
01664 int maxentries;
01665 uint16 findfirst_flags;
01666 BOOL close_after_first;
01667 BOOL close_if_end;
01668 BOOL requires_resume_key;
01669 int info_level;
01670 pstring directory;
01671 pstring mask;
01672 char *p;
01673 int last_entry_off=0;
01674 int dptr_num = -1;
01675 int numentries = 0;
01676 int i;
01677 BOOL finished = False;
01678 BOOL dont_descend = False;
01679 BOOL out_of_space = False;
01680 int space_remaining;
01681 BOOL mask_contains_wcard = False;
01682 SMB_STRUCT_STAT sbuf;
01683 TALLOC_CTX *ea_ctx = NULL;
01684 struct ea_list *ea_list = NULL;
01685 NTSTATUS ntstatus = NT_STATUS_OK;
01686
01687 if (total_params < 13) {
01688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01689 }
01690
01691 dirtype = SVAL(params,0);
01692 maxentries = SVAL(params,2);
01693 findfirst_flags = SVAL(params,4);
01694 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
01695 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
01696 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
01697 info_level = SVAL(params,6);
01698
01699 *directory = *mask = 0;
01700
01701 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
01702 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
01703 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
01704 info_level, max_data_bytes));
01705
01706 if (!maxentries) {
01707
01708 maxentries = 1;
01709 }
01710
01711 switch (info_level) {
01712 case SMB_FIND_INFO_STANDARD:
01713 case SMB_FIND_EA_SIZE:
01714 case SMB_FIND_EA_LIST:
01715 case SMB_FIND_FILE_DIRECTORY_INFO:
01716 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
01717 case SMB_FIND_FILE_NAMES_INFO:
01718 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
01719 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
01720 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
01721 break;
01722 case SMB_FIND_FILE_UNIX:
01723 case SMB_FIND_FILE_UNIX_INFO2:
01724 if (!lp_unix_extensions()) {
01725 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
01726 }
01727 break;
01728 default:
01729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
01730 }
01731
01732 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
01733 if (!NT_STATUS_IS_OK(ntstatus)) {
01734 return ERROR_NT(ntstatus);
01735 }
01736
01737 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
01738 if (!NT_STATUS_IS_OK(ntstatus)) {
01739 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
01740 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01741 }
01742 return ERROR_NT(ntstatus);
01743 }
01744
01745 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
01746 if (!NT_STATUS_IS_OK(ntstatus)) {
01747 return ERROR_NT(ntstatus);
01748 }
01749 ntstatus = check_name(conn, directory);
01750 if (!NT_STATUS_IS_OK(ntstatus)) {
01751 return ERROR_NT(ntstatus);
01752 }
01753
01754 p = strrchr_m(directory,'/');
01755 if(p == NULL) {
01756
01757 if((directory[0] == '.') && (directory[1] == '\0')) {
01758 pstrcpy(mask,"*");
01759 mask_contains_wcard = True;
01760 } else {
01761 pstrcpy(mask,directory);
01762 }
01763 pstrcpy(directory,"./");
01764 } else {
01765 pstrcpy(mask,p+1);
01766 *p = 0;
01767 }
01768
01769 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
01770
01771 if (info_level == SMB_FIND_EA_LIST) {
01772 uint32 ea_size;
01773
01774 if (total_data < 4) {
01775 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01776 }
01777
01778 ea_size = IVAL(pdata,0);
01779 if (ea_size != total_data) {
01780 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
01781 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
01782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01783 }
01784
01785 if (!lp_ea_support(SNUM(conn))) {
01786 return ERROR_DOS(ERRDOS,ERReasnotsupported);
01787 }
01788
01789 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
01790 return ERROR_NT(NT_STATUS_NO_MEMORY);
01791 }
01792
01793
01794 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
01795 if (!ea_list) {
01796 talloc_destroy(ea_ctx);
01797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01798 }
01799 }
01800
01801 *ppdata = (char *)SMB_REALLOC(
01802 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
01803 if(*ppdata == NULL ) {
01804 talloc_destroy(ea_ctx);
01805 return ERROR_NT(NT_STATUS_NO_MEMORY);
01806 }
01807 pdata = *ppdata;
01808 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
01809
01810
01811 *pparams = (char *)SMB_REALLOC(*pparams, 10);
01812 if (*pparams == NULL) {
01813 talloc_destroy(ea_ctx);
01814 return ERROR_NT(NT_STATUS_NO_MEMORY);
01815 }
01816 params = *pparams;
01817
01818
01819
01820
01821 ntstatus = dptr_create(conn,
01822 directory,
01823 False,
01824 True,
01825 SVAL(inbuf,smb_pid),
01826 mask,
01827 mask_contains_wcard,
01828 dirtype,
01829 &conn->dirptr);
01830
01831 if (!NT_STATUS_IS_OK(ntstatus)) {
01832 talloc_destroy(ea_ctx);
01833 return ERROR_NT(ntstatus);
01834 }
01835
01836 dptr_num = dptr_dnum(conn->dirptr);
01837 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
01838
01839
01840
01841
01842 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
01843 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
01844 dont_descend = True;
01845
01846 p = pdata;
01847 space_remaining = max_data_bytes;
01848 out_of_space = False;
01849
01850 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
01851 BOOL got_exact_match = False;
01852
01853
01854
01855 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
01856 out_of_space = True;
01857 finished = False;
01858 } else {
01859 finished = !get_lanman2_dir_entry(conn,
01860 inbuf, outbuf,
01861 mask,dirtype,info_level,
01862 requires_resume_key,dont_descend,
01863 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
01864 &last_entry_off, ea_list, ea_ctx);
01865 }
01866
01867 if (finished && out_of_space)
01868 finished = False;
01869
01870 if (!finished && !out_of_space)
01871 numentries++;
01872
01873
01874
01875
01876
01877
01878
01879
01880 if(got_exact_match)
01881 finished = True;
01882
01883 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
01884 }
01885
01886 talloc_destroy(ea_ctx);
01887
01888
01889 if(close_after_first || (finished && close_if_end)) {
01890 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
01891 dptr_close(&dptr_num);
01892 }
01893
01894
01895
01896
01897
01898
01899
01900
01901 if(numentries == 0) {
01902 dptr_close(&dptr_num);
01903 if (Protocol < PROTOCOL_NT1) {
01904 return ERROR_DOS(ERRDOS,ERRnofiles);
01905 } else {
01906 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
01907 }
01908 }
01909
01910
01911
01912
01913 SSVAL(params,0,dptr_num);
01914 SSVAL(params,2,numentries);
01915 SSVAL(params,4,finished);
01916 SSVAL(params,6,0);
01917 SSVAL(params,8,last_entry_off);
01918
01919 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
01920
01921 if ((! *directory) && dptr_path(dptr_num))
01922 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
01923
01924 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
01925 smb_fn_name(CVAL(inbuf,smb_com)),
01926 mask, directory, dirtype, numentries ) );
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
01937 mangle_map(mask, True, True, conn->params);
01938
01939 return(-1);
01940 }
01941
01942
01943
01944
01945
01946 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
01947 char **pparams, int total_params, char **ppdata, int total_data,
01948 unsigned int max_data_bytes)
01949 {
01950
01951
01952
01953
01954
01955 char *params = *pparams;
01956 char *pdata = *ppdata;
01957 char *data_end;
01958 int dptr_num;
01959 int maxentries;
01960 uint16 info_level;
01961 uint32 resume_key;
01962 uint16 findnext_flags;
01963 BOOL close_after_request;
01964 BOOL close_if_end;
01965 BOOL requires_resume_key;
01966 BOOL continue_bit;
01967 BOOL mask_contains_wcard = False;
01968 pstring resume_name;
01969 pstring mask;
01970 pstring directory;
01971 char *p;
01972 uint16 dirtype;
01973 int numentries = 0;
01974 int i, last_entry_off=0;
01975 BOOL finished = False;
01976 BOOL dont_descend = False;
01977 BOOL out_of_space = False;
01978 int space_remaining;
01979 TALLOC_CTX *ea_ctx = NULL;
01980 struct ea_list *ea_list = NULL;
01981 NTSTATUS ntstatus = NT_STATUS_OK;
01982
01983 if (total_params < 13) {
01984 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01985 }
01986
01987 dptr_num = SVAL(params,0);
01988 maxentries = SVAL(params,2);
01989 info_level = SVAL(params,4);
01990 resume_key = IVAL(params,6);
01991 findnext_flags = SVAL(params,10);
01992 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
01993 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
01994 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
01995 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
01996
01997 *mask = *directory = *resume_name = 0;
01998
01999 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
02000 if (!NT_STATUS_IS_OK(ntstatus)) {
02001
02002
02003
02004
02005 srvstr_pull(inbuf, resume_name, params+12,
02006 sizeof(resume_name), total_params - 12,
02007 STR_TERMINATE);
02008
02009 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
02010 return ERROR_NT(ntstatus);
02011 }
02012 }
02013
02014 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
02015 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
02016 resume_key = %d resume name = %s continue=%d level = %d\n",
02017 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
02018 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
02019
02020 if (!maxentries) {
02021
02022 maxentries = 1;
02023 }
02024
02025 switch (info_level) {
02026 case SMB_FIND_INFO_STANDARD:
02027 case SMB_FIND_EA_SIZE:
02028 case SMB_FIND_EA_LIST:
02029 case SMB_FIND_FILE_DIRECTORY_INFO:
02030 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
02031 case SMB_FIND_FILE_NAMES_INFO:
02032 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
02033 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
02034 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
02035 break;
02036 case SMB_FIND_FILE_UNIX:
02037 case SMB_FIND_FILE_UNIX_INFO2:
02038 if (!lp_unix_extensions()) {
02039 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02040 }
02041 break;
02042 default:
02043 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02044 }
02045
02046 if (info_level == SMB_FIND_EA_LIST) {
02047 uint32 ea_size;
02048
02049 if (total_data < 4) {
02050 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02051 }
02052
02053 ea_size = IVAL(pdata,0);
02054 if (ea_size != total_data) {
02055 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
02056 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
02057 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02058 }
02059
02060 if (!lp_ea_support(SNUM(conn))) {
02061 return ERROR_DOS(ERRDOS,ERReasnotsupported);
02062 }
02063
02064 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
02065 return ERROR_NT(NT_STATUS_NO_MEMORY);
02066 }
02067
02068
02069 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
02070 if (!ea_list) {
02071 talloc_destroy(ea_ctx);
02072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02073 }
02074 }
02075
02076 *ppdata = (char *)SMB_REALLOC(
02077 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
02078 if(*ppdata == NULL) {
02079 talloc_destroy(ea_ctx);
02080 return ERROR_NT(NT_STATUS_NO_MEMORY);
02081 }
02082
02083 pdata = *ppdata;
02084 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
02085
02086
02087 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
02088 if(*pparams == NULL ) {
02089 talloc_destroy(ea_ctx);
02090 return ERROR_NT(NT_STATUS_NO_MEMORY);
02091 }
02092
02093 params = *pparams;
02094
02095
02096 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
02097 talloc_destroy(ea_ctx);
02098 return ERROR_DOS(ERRDOS,ERRnofiles);
02099 }
02100
02101 string_set(&conn->dirpath,dptr_path(dptr_num));
02102
02103
02104 if((p = dptr_wcard(dptr_num))== NULL) {
02105 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
02106 talloc_destroy(ea_ctx);
02107 return ERROR_DOS(ERRDOS,ERRnofiles);
02108 }
02109
02110 pstrcpy(mask, p);
02111 pstrcpy(directory,conn->dirpath);
02112
02113
02114 dirtype = dptr_attr(dptr_num);
02115
02116 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
02117 dptr_num, mask, dirtype,
02118 (long)conn->dirptr,
02119 dptr_TellDir(conn->dirptr)));
02120
02121
02122
02123
02124 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
02125 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
02126 dont_descend = True;
02127
02128 p = pdata;
02129 space_remaining = max_data_bytes;
02130 out_of_space = False;
02131
02132
02133
02134
02135
02136
02137 if(*resume_name && !continue_bit) {
02138 SMB_STRUCT_STAT st;
02139
02140 long current_pos = 0;
02141
02142
02143
02144
02145
02146
02147 if (mangle_is_mangled(resume_name, conn->params)) {
02148 mangle_check_cache(resume_name, sizeof(resume_name)-1,
02149 conn->params);
02150 }
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
02162 }
02163
02164 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
02165 BOOL got_exact_match = False;
02166
02167
02168
02169 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
02170 out_of_space = True;
02171 finished = False;
02172 } else {
02173 finished = !get_lanman2_dir_entry(conn,
02174 inbuf, outbuf,
02175 mask,dirtype,info_level,
02176 requires_resume_key,dont_descend,
02177 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
02178 &last_entry_off, ea_list, ea_ctx);
02179 }
02180
02181 if (finished && out_of_space)
02182 finished = False;
02183
02184 if (!finished && !out_of_space)
02185 numentries++;
02186
02187
02188
02189
02190
02191
02192
02193
02194 if(got_exact_match)
02195 finished = True;
02196
02197 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
02198 }
02199
02200 talloc_destroy(ea_ctx);
02201
02202
02203 if(close_after_request || (finished && close_if_end)) {
02204 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
02205 dptr_close(&dptr_num);
02206 }
02207
02208
02209 SSVAL(params,0,numentries);
02210 SSVAL(params,2,finished);
02211 SSVAL(params,4,0);
02212 SSVAL(params,6,last_entry_off);
02213
02214 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
02215
02216 if ((! *directory) && dptr_path(dptr_num))
02217 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
02218
02219 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
02220 smb_fn_name(CVAL(inbuf,smb_com)),
02221 mask, directory, dirtype, numentries ) );
02222
02223 return(-1);
02224 }
02225
02226 static void samba_extended_info_version(struct smb_extended_info *extended_info)
02227 {
02228 SMB_ASSERT(extended_info != NULL);
02229
02230 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
02231 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
02232 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
02233 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
02234 #ifdef SAMBA_VERSION_REVISION
02235 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
02236 #endif
02237 extended_info->samba_subversion = 0;
02238 #ifdef SAMBA_VERSION_RC_RELEASE
02239 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
02240 #else
02241 #ifdef SAMBA_VERSION_PRE_RELEASE
02242 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
02243 #endif
02244 #endif
02245 #ifdef SAMBA_VERSION_VENDOR_PATCH
02246 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
02247 #endif
02248 extended_info->samba_subversion = 0;
02249 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
02250 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
02251 #endif
02252
02253 memset(extended_info->samba_version_string, 0,
02254 sizeof(extended_info->samba_version_string));
02255
02256 snprintf (extended_info->samba_version_string,
02257 sizeof(extended_info->samba_version_string),
02258 "%s", samba_version_string());
02259 }
02260
02261
02262
02263
02264
02265 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
02266 char **pparams, int total_params, char **ppdata, int total_data,
02267 unsigned int max_data_bytes)
02268 {
02269 char *pdata;
02270 char *params = *pparams;
02271 uint16 info_level;
02272 int data_len, len;
02273 SMB_STRUCT_STAT st;
02274 const char *vname = volume_label(SNUM(conn));
02275 int snum = SNUM(conn);
02276 char *fstype = lp_fstype(SNUM(conn));
02277 int quota_flag = 0;
02278
02279 if (total_params < 2) {
02280 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02281 }
02282
02283 info_level = SVAL(params,0);
02284
02285 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
02286
02287 if(SMB_VFS_STAT(conn,".",&st)!=0) {
02288 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
02289 return ERROR_DOS(ERRSRV,ERRinvdevice);
02290 }
02291
02292 *ppdata = (char *)SMB_REALLOC(
02293 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
02294 if (*ppdata == NULL ) {
02295 return ERROR_NT(NT_STATUS_NO_MEMORY);
02296 }
02297
02298 pdata = *ppdata;
02299 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
02300
02301 switch (info_level) {
02302 case SMB_INFO_ALLOCATION:
02303 {
02304 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
02305 data_len = 18;
02306 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
02307 return(UNIXERROR(ERRHRD,ERRgeneral));
02308 }
02309
02310 block_size = lp_block_size(snum);
02311 if (bsize < block_size) {
02312 SMB_BIG_UINT factor = block_size/bsize;
02313 bsize = block_size;
02314 dsize /= factor;
02315 dfree /= factor;
02316 }
02317 if (bsize > block_size) {
02318 SMB_BIG_UINT factor = bsize/block_size;
02319 bsize = block_size;
02320 dsize *= factor;
02321 dfree *= factor;
02322 }
02323 bytes_per_sector = 512;
02324 sectors_per_unit = bsize/bytes_per_sector;
02325
02326 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
02327 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
02328 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
02329
02330 SIVAL(pdata,l1_idFileSystem,st.st_dev);
02331 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
02332 SIVAL(pdata,l1_cUnit,dsize);
02333 SIVAL(pdata,l1_cUnitAvail,dfree);
02334 SSVAL(pdata,l1_cbSector,bytes_per_sector);
02335 break;
02336 }
02337
02338 case SMB_INFO_VOLUME:
02339
02340
02341
02342
02343
02344 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
02345
02346
02347
02348
02349
02350
02351 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, max_data_bytes - l2_vol_szVolLabel, STR_NOALIGN|STR_TERMINATE);
02352 SCVAL(pdata,l2_vol_cch,len);
02353 data_len = l2_vol_szVolLabel + len;
02354 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
02355 (unsigned)st.st_ctime, len, vname));
02356 break;
02357
02358 case SMB_QUERY_FS_ATTRIBUTE_INFO:
02359 case SMB_FS_ATTRIBUTE_INFORMATION:
02360
02361
02362 #if defined(HAVE_SYS_QUOTAS)
02363 quota_flag = FILE_VOLUME_QUOTAS;
02364 #endif
02365
02366 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
02367 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
02368 FILE_UNICODE_ON_DISK|
02369 quota_flag);
02370
02371 SIVAL(pdata,4,255);
02372
02373
02374 len = srvstr_push(outbuf, pdata+12, fstype, max_data_bytes - 12, STR_UNICODE);
02375 SIVAL(pdata,8,len);
02376 data_len = 12 + len;
02377 break;
02378
02379 case SMB_QUERY_FS_LABEL_INFO:
02380 case SMB_FS_LABEL_INFORMATION:
02381 len = srvstr_push(outbuf, pdata+4, vname, max_data_bytes - 4, 0);
02382 data_len = 4 + len;
02383 SIVAL(pdata,0,len);
02384 break;
02385
02386 case SMB_QUERY_FS_VOLUME_INFO:
02387 case SMB_FS_VOLUME_INFORMATION:
02388
02389
02390
02391
02392
02393 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
02394 (str_checksum(get_local_machine_name())<<16));
02395
02396
02397 len = srvstr_push(outbuf, pdata+18, vname, max_data_bytes - 18, STR_UNICODE);
02398 SIVAL(pdata,12,len);
02399 data_len = 18+len;
02400
02401 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
02402 (int)strlen(vname),vname, lp_servicename(snum)));
02403 break;
02404
02405 case SMB_QUERY_FS_SIZE_INFO:
02406 case SMB_FS_SIZE_INFORMATION:
02407 {
02408 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
02409 data_len = 24;
02410 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
02411 return(UNIXERROR(ERRHRD,ERRgeneral));
02412 }
02413 block_size = lp_block_size(snum);
02414 if (bsize < block_size) {
02415 SMB_BIG_UINT factor = block_size/bsize;
02416 bsize = block_size;
02417 dsize /= factor;
02418 dfree /= factor;
02419 }
02420 if (bsize > block_size) {
02421 SMB_BIG_UINT factor = bsize/block_size;
02422 bsize = block_size;
02423 dsize *= factor;
02424 dfree *= factor;
02425 }
02426 bytes_per_sector = 512;
02427 sectors_per_unit = bsize/bytes_per_sector;
02428 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
02429 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
02430 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
02431 SBIG_UINT(pdata,0,dsize);
02432 SBIG_UINT(pdata,8,dfree);
02433 SIVAL(pdata,16,sectors_per_unit);
02434 SIVAL(pdata,20,bytes_per_sector);
02435 break;
02436 }
02437
02438 case SMB_FS_FULL_SIZE_INFORMATION:
02439 {
02440 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
02441 data_len = 32;
02442 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
02443 return(UNIXERROR(ERRHRD,ERRgeneral));
02444 }
02445 block_size = lp_block_size(snum);
02446 if (bsize < block_size) {
02447 SMB_BIG_UINT factor = block_size/bsize;
02448 bsize = block_size;
02449 dsize /= factor;
02450 dfree /= factor;
02451 }
02452 if (bsize > block_size) {
02453 SMB_BIG_UINT factor = bsize/block_size;
02454 bsize = block_size;
02455 dsize *= factor;
02456 dfree *= factor;
02457 }
02458 bytes_per_sector = 512;
02459 sectors_per_unit = bsize/bytes_per_sector;
02460 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
02461 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
02462 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
02463 SBIG_UINT(pdata,0,dsize);
02464 SBIG_UINT(pdata,8,dfree);
02465 SBIG_UINT(pdata,16,dfree);
02466 SIVAL(pdata,24,sectors_per_unit);
02467 SIVAL(pdata,28,bytes_per_sector);
02468 break;
02469 }
02470
02471 case SMB_QUERY_FS_DEVICE_INFO:
02472 case SMB_FS_DEVICE_INFORMATION:
02473 data_len = 8;
02474 SIVAL(pdata,0,0);
02475 SIVAL(pdata,4,0);
02476 break;
02477
02478 #ifdef HAVE_SYS_QUOTAS
02479 case SMB_FS_QUOTA_INFORMATION:
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499 {
02500
02501
02502
02503 files_struct fsp;
02504 SMB_NTQUOTA_STRUCT quotas;
02505
02506 ZERO_STRUCT(fsp);
02507 ZERO_STRUCT(quotas);
02508
02509 fsp.conn = conn;
02510 fsp.fnum = -1;
02511
02512
02513 if (current_user.ut.uid != 0) {
02514 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
02515 lp_servicename(SNUM(conn)),conn->user));
02516 return ERROR_DOS(ERRDOS,ERRnoaccess);
02517 }
02518
02519 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
02520 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
02521 return ERROR_DOS(ERRSRV,ERRerror);
02522 }
02523
02524 data_len = 48;
02525
02526 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
02527
02528
02529 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
02530 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
02531 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
02532
02533
02534 SBIG_UINT(pdata,24,quotas.softlim);
02535
02536
02537 SBIG_UINT(pdata,32,quotas.hardlim);
02538
02539
02540 SSVAL(pdata,40,quotas.qflags);
02541
02542
02543 SSVAL(pdata,42,0);
02544 SIVAL(pdata,44,0);
02545
02546 break;
02547 }
02548 #endif
02549 case SMB_FS_OBJECTID_INFORMATION:
02550 {
02551
02552
02553
02554 struct smb_extended_info extended_info;
02555 samba_extended_info_version (&extended_info);
02556 SIVAL(pdata,16,extended_info.samba_magic);
02557 SIVAL(pdata,20,extended_info.samba_version);
02558 SIVAL(pdata,24,extended_info.samba_subversion);
02559 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
02560 memcpy(pdata+36,extended_info.samba_version_string,28);
02561 data_len = 64;
02562 break;
02563 }
02564
02565
02566
02567
02568
02569
02570 case SMB_QUERY_CIFS_UNIX_INFO:
02571 if (!lp_unix_extensions()) {
02572 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02573 }
02574 data_len = 12;
02575 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
02576 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
02577
02578 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
02579 CIFS_UNIX_POSIX_ACLS_CAP|
02580 CIFS_UNIX_POSIX_PATHNAMES_CAP|
02581 CIFS_UNIX_FCNTL_LOCKS_CAP|
02582 CIFS_UNIX_EXTATTR_CAP|
02583 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
02584 break;
02585
02586 case SMB_QUERY_POSIX_FS_INFO:
02587 {
02588 int rc;
02589 vfs_statvfs_struct svfs;
02590
02591 if (!lp_unix_extensions()) {
02592 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02593 }
02594
02595 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
02596
02597 if (!rc) {
02598 data_len = 56;
02599 SIVAL(pdata,0,svfs.OptimalTransferSize);
02600 SIVAL(pdata,4,svfs.BlockSize);
02601 SBIG_UINT(pdata,8,svfs.TotalBlocks);
02602 SBIG_UINT(pdata,16,svfs.BlocksAvail);
02603 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
02604 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
02605 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
02606 SBIG_UINT(pdata,48,svfs.FsIdentifier);
02607 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
02608 #ifdef EOPNOTSUPP
02609 } else if (rc == EOPNOTSUPP) {
02610 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02611 #endif
02612 } else {
02613 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
02614 return ERROR_DOS(ERRSRV,ERRerror);
02615 }
02616 break;
02617 }
02618
02619 case SMB_QUERY_POSIX_WHOAMI:
02620 {
02621 uint32_t flags = 0;
02622 uint32_t sid_bytes;
02623 int i;
02624
02625 if (!lp_unix_extensions()) {
02626 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02627 }
02628
02629 if (max_data_bytes < 40) {
02630 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
02631 }
02632
02633
02634
02635
02636 if (nt_token_check_sid(&global_sid_Builtin_Guests,
02637 current_user.nt_user_token)) {
02638 flags |= SMB_WHOAMI_GUEST;
02639 }
02640
02641
02642
02643
02644 if (nt_token_check_sid(&global_sid_Authenticated_Users,
02645 current_user.nt_user_token)) {
02646 flags &= ~SMB_WHOAMI_GUEST;
02647 }
02648
02649
02650
02651
02652
02653 data_len = 4
02654 + 4
02655 + 8
02656 + 8
02657 + 4
02658 + 4
02659 + 4
02660 + 4
02661 + (current_user.ut.ngroups * 8)
02662
02663 + (current_user.nt_user_token->num_sids *
02664 SID_MAX_SIZE)
02665 ;
02666
02667 SIVAL(pdata, 0, flags);
02668 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
02669 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
02670 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
02671
02672
02673 if (data_len >= max_data_bytes) {
02674
02675
02676 SIVAL(pdata, 24, 0);
02677 SIVAL(pdata, 28, 0);
02678 SIVAL(pdata, 32, 0);
02679 SIVAL(pdata, 36, 0);
02680
02681 data_len = 40;
02682 break;
02683 }
02684
02685 SIVAL(pdata, 24, current_user.ut.ngroups);
02686 SIVAL(pdata, 28,
02687 current_user.nt_user_token->num_sids);
02688
02689
02690
02691
02692
02693 for (i = 0, sid_bytes = 0;
02694 i < current_user.nt_user_token->num_sids; ++i) {
02695 sid_bytes +=
02696 sid_size(¤t_user.nt_user_token->user_sids[i]);
02697 }
02698
02699
02700 SIVAL(pdata, 32, sid_bytes);
02701
02702
02703 SIVAL(pdata, 36, 0);
02704 data_len = 40;
02705
02706
02707 for (i = 0; i < current_user.ut.ngroups; ++i) {
02708 SBIG_UINT(pdata, data_len,
02709 (SMB_BIG_UINT)current_user.ut.groups[i]);
02710 data_len += 8;
02711 }
02712
02713
02714 for (i = 0;
02715 i < current_user.nt_user_token->num_sids; ++i) {
02716 int sid_len =
02717 sid_size(¤t_user.nt_user_token->user_sids[i]);
02718
02719 sid_linearize(pdata + data_len, sid_len,
02720 ¤t_user.nt_user_token->user_sids[i]);
02721 data_len += sid_len;
02722 }
02723
02724 break;
02725 }
02726
02727 case SMB_MAC_QUERY_FS_INFO:
02728
02729
02730
02731
02732 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
02733 data_len = 88;
02734 SIVAL(pdata,84,0x100);
02735 break;
02736 }
02737
02738 default:
02739 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02740 }
02741
02742
02743 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
02744
02745 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
02746
02747 return -1;
02748 }
02749
02750
02751
02752
02753
02754 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
02755 char **pparams, int total_params, char **ppdata, int total_data,
02756 unsigned int max_data_bytes)
02757 {
02758 char *pdata = *ppdata;
02759 char *params = *pparams;
02760 uint16 info_level;
02761 int outsize;
02762
02763 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
02764
02765
02766 if (total_params < 4) {
02767 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
02768 total_params));
02769 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02770 }
02771
02772 info_level = SVAL(params,2);
02773
02774 switch(info_level) {
02775 case SMB_SET_CIFS_UNIX_INFO:
02776 {
02777 uint16 client_unix_major;
02778 uint16 client_unix_minor;
02779 uint32 client_unix_cap_low;
02780 uint32 client_unix_cap_high;
02781
02782 if (!lp_unix_extensions()) {
02783 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02784 }
02785
02786
02787 if (total_data < 8) {
02788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02789 }
02790 client_unix_major = SVAL(pdata,0);
02791 client_unix_minor = SVAL(pdata,2);
02792 client_unix_cap_low = IVAL(pdata,4);
02793 client_unix_cap_high = IVAL(pdata,8);
02794
02795 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
02796 cap_low = 0x%x, cap_high = 0x%x\n",
02797 (unsigned int)client_unix_major,
02798 (unsigned int)client_unix_minor,
02799 (unsigned int)client_unix_cap_low,
02800 (unsigned int)client_unix_cap_high ));
02801
02802
02803 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
02804 lp_set_posix_pathnames();
02805 mangle_change_to_posix();
02806 }
02807
02808 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
02809 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
02810
02811
02812
02813
02814 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
02815
02816 }
02817 break;
02818 }
02819 case SMB_FS_QUOTA_INFORMATION:
02820 {
02821 files_struct *fsp = NULL;
02822 SMB_NTQUOTA_STRUCT quotas;
02823
02824 ZERO_STRUCT(quotas);
02825
02826
02827 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
02828 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
02829 lp_servicename(SNUM(conn)),conn->user));
02830 return ERROR_DOS(ERRSRV,ERRaccess);
02831 }
02832
02833
02834
02835
02836
02837 fsp = file_fsp(params,0);
02838 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
02839 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
02840 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
02841 }
02842
02843 if (total_data < 42) {
02844 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
02845 total_data));
02846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02847 }
02848
02849
02850
02851
02852 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
02853 #ifdef LARGE_SMB_OFF_T
02854 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
02855 #else
02856 if ((IVAL(pdata,28) != 0)&&
02857 ((quotas.softlim != 0xFFFFFFFF)||
02858 (IVAL(pdata,28)!=0xFFFFFFFF))) {
02859
02860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02861 }
02862 #endif
02863
02864
02865 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
02866 #ifdef LARGE_SMB_OFF_T
02867 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
02868 #else
02869 if ((IVAL(pdata,36) != 0)&&
02870 ((quotas.hardlim != 0xFFFFFFFF)||
02871 (IVAL(pdata,36)!=0xFFFFFFFF))) {
02872
02873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02874 }
02875 #endif
02876
02877
02878 quotas.qflags = SVAL(pdata,40);
02879
02880
02881
02882
02883 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
02884 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
02885 return ERROR_DOS(ERRSRV,ERRerror);
02886 }
02887
02888 break;
02889 }
02890 default:
02891 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
02892 info_level));
02893 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
02894 break;
02895 }
02896
02897
02898
02899
02900
02901
02902
02903 outsize = set_message(outbuf,10,0,True);
02904
02905 return outsize;
02906 }
02907
02908 #if defined(HAVE_POSIX_ACLS)
02909
02910
02911
02912
02913 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
02914 {
02915 unsigned int ace_count = 0;
02916 int entry_id = SMB_ACL_FIRST_ENTRY;
02917 SMB_ACL_ENTRY_T entry;
02918
02919 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
02920
02921 if (entry_id == SMB_ACL_FIRST_ENTRY) {
02922 entry_id = SMB_ACL_NEXT_ENTRY;
02923 }
02924 ace_count++;
02925 }
02926 return ace_count;
02927 }
02928
02929
02930
02931
02932
02933 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
02934 {
02935 int entry_id = SMB_ACL_FIRST_ENTRY;
02936 SMB_ACL_ENTRY_T entry;
02937
02938 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
02939 SMB_ACL_TAG_T tagtype;
02940 SMB_ACL_PERMSET_T permset;
02941 unsigned char perms = 0;
02942 unsigned int own_grp;
02943
02944
02945 if (entry_id == SMB_ACL_FIRST_ENTRY) {
02946 entry_id = SMB_ACL_NEXT_ENTRY;
02947 }
02948
02949 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
02950 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
02951 return False;
02952 }
02953
02954 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
02955 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
02956 return False;
02957 }
02958
02959 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
02960 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
02961 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
02962
02963 SCVAL(pdata,1,perms);
02964
02965 switch (tagtype) {
02966 case SMB_ACL_USER_OBJ:
02967 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
02968 own_grp = (unsigned int)pst->st_uid;
02969 SIVAL(pdata,2,own_grp);
02970 SIVAL(pdata,6,0);
02971 break;
02972 case SMB_ACL_USER:
02973 {
02974 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
02975 if (!puid) {
02976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
02977 }
02978 own_grp = (unsigned int)*puid;
02979 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
02980 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
02981 SIVAL(pdata,2,own_grp);
02982 SIVAL(pdata,6,0);
02983 break;
02984 }
02985 case SMB_ACL_GROUP_OBJ:
02986 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
02987 own_grp = (unsigned int)pst->st_gid;
02988 SIVAL(pdata,2,own_grp);
02989 SIVAL(pdata,6,0);
02990 break;
02991 case SMB_ACL_GROUP:
02992 {
02993 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
02994 if (!pgid) {
02995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
02996 }
02997 own_grp = (unsigned int)*pgid;
02998 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
02999 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
03000 SIVAL(pdata,2,own_grp);
03001 SIVAL(pdata,6,0);
03002 break;
03003 }
03004 case SMB_ACL_MASK:
03005 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
03006 SIVAL(pdata,2,0xFFFFFFFF);
03007 SIVAL(pdata,6,0xFFFFFFFF);
03008 break;
03009 case SMB_ACL_OTHER:
03010 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
03011 SIVAL(pdata,2,0xFFFFFFFF);
03012 SIVAL(pdata,6,0xFFFFFFFF);
03013 break;
03014 default:
03015 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
03016 return False;
03017 }
03018 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
03019 }
03020
03021 return True;
03022 }
03023 #endif
03024
03025
03026
03027
03028
03029 static char *store_file_unix_basic(connection_struct *conn,
03030 char *pdata,
03031 files_struct *fsp,
03032 const SMB_STRUCT_STAT *psbuf)
03033 {
03034 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
03035 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
03036
03037 SOFF_T(pdata,0,get_file_size(*psbuf));
03038 pdata += 8;
03039
03040 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf));
03041 pdata += 8;
03042
03043 put_long_date_timespec(pdata,get_ctimespec(psbuf));
03044 put_long_date_timespec(pdata+8,get_atimespec(psbuf));
03045 put_long_date_timespec(pdata+16,get_mtimespec(psbuf));
03046 pdata += 24;
03047
03048 SIVAL(pdata,0,psbuf->st_uid);
03049 SIVAL(pdata,4,0);
03050 pdata += 8;
03051
03052 SIVAL(pdata,0,psbuf->st_gid);
03053 SIVAL(pdata,4,0);
03054 pdata += 8;
03055
03056 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
03057 pdata += 4;
03058
03059 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));
03060 SIVAL(pdata,4,0);
03061 pdata += 8;
03062
03063 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));
03064 SIVAL(pdata,4,0);
03065 pdata += 8;
03066
03067 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);
03068 pdata += 8;
03069
03070 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));
03071 SIVAL(pdata,4,0);
03072 pdata += 8;
03073
03074 SIVAL(pdata,0,psbuf->st_nlink);
03075 SIVAL(pdata,4,0);
03076 pdata += 8;
03077
03078 return pdata;
03079 }
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
03090 info2_flags_map[] =
03091 {
03092 #ifdef UF_NODUMP
03093 { UF_NODUMP, EXT_DO_NOT_BACKUP },
03094 #endif
03095
03096 #ifdef UF_IMMUTABLE
03097 { UF_IMMUTABLE, EXT_IMMUTABLE },
03098 #endif
03099
03100 #ifdef UF_APPEND
03101 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
03102 #endif
03103
03104 #ifdef UF_HIDDEN
03105 { UF_HIDDEN, EXT_HIDDEN },
03106 #endif
03107
03108
03109
03110
03111 { 0, 0 }
03112
03113 };
03114
03115 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
03116 uint32 *smb_fflags, uint32 *smb_fmask)
03117 {
03118 #ifdef HAVE_STAT_ST_FLAGS
03119 int i;
03120
03121 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
03122 *smb_fmask |= info2_flags_map[i].smb_fflag;
03123 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
03124 *smb_fflags |= info2_flags_map[i].smb_fflag;
03125 }
03126 }
03127 #endif
03128 }
03129
03130 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
03131 const uint32 smb_fflags,
03132 const uint32 smb_fmask,
03133 int *stat_fflags)
03134 {
03135 #ifdef HAVE_STAT_ST_FLAGS
03136 uint32 max_fmask = 0;
03137 int i;
03138
03139 *stat_fflags = psbuf->st_flags;
03140
03141
03142
03143
03144
03145
03146 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
03147 max_fmask |= info2_flags_map[i].smb_fflag;
03148 if (smb_fmask & info2_flags_map[i].smb_fflag) {
03149 if (smb_fflags & info2_flags_map[i].smb_fflag) {
03150 *stat_fflags |= info2_flags_map[i].stat_fflag;
03151 } else {
03152 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
03153 }
03154 }
03155 }
03156
03157
03158
03159
03160 if ((smb_fmask & max_fmask) != smb_fmask) {
03161 return False;
03162 }
03163
03164 return True;
03165 #else
03166 return False;
03167 #endif
03168 }
03169
03170
03171
03172
03173
03174 static char *store_file_unix_basic_info2(connection_struct *conn,
03175 char *pdata,
03176 files_struct *fsp,
03177 const SMB_STRUCT_STAT *psbuf)
03178 {
03179 uint32 file_flags = 0;
03180 uint32 flags_mask = 0;
03181
03182 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
03183
03184
03185 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
03186 pdata += 8;
03187
03188 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
03189 SIVAL(pdata, 0, file_flags);
03190 SIVAL(pdata, 4, flags_mask);
03191 pdata += 8;
03192
03193 return pdata;
03194 }
03195
03196
03197
03198
03199
03200
03201 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
03202 unsigned int tran_call,
03203 char **pparams, int total_params, char **ppdata, int total_data,
03204 unsigned int max_data_bytes)
03205 {
03206 char *params = *pparams;
03207 char *pdata = *ppdata;
03208 uint16 info_level;
03209 int mode=0;
03210 int nlink;
03211 SMB_OFF_T file_size=0;
03212 SMB_BIG_UINT allocation_size=0;
03213 unsigned int data_size = 0;
03214 unsigned int param_size = 2;
03215 SMB_STRUCT_STAT sbuf;
03216 pstring fname, dos_fname;
03217 char *fullpathname;
03218 char *base_name;
03219 char *p;
03220 SMB_OFF_T pos = 0;
03221 BOOL delete_pending = False;
03222 int len;
03223 time_t create_time, mtime, atime;
03224 struct timespec create_time_ts, mtime_ts, atime_ts;
03225 files_struct *fsp = NULL;
03226 TALLOC_CTX *data_ctx = NULL;
03227 struct ea_list *ea_list = NULL;
03228 uint32 access_mask = 0x12019F;
03229 char *lock_data = NULL;
03230
03231 if (!params)
03232 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03233
03234 ZERO_STRUCT(sbuf);
03235
03236 if (tran_call == TRANSACT2_QFILEINFO) {
03237 if (total_params < 4) {
03238 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03239 }
03240
03241 fsp = file_fsp(params,0);
03242 info_level = SVAL(params,2);
03243
03244 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
03245
03246 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
03247 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
03248 }
03249
03250 if(fsp && (fsp->fake_file_handle)) {
03251
03252
03253
03254
03255 pstrcpy(fname, fsp->fsp_name);
03256
03257
03258 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
03259
03260
03261
03262
03263
03264
03265 pstrcpy(fname, fsp->fsp_name);
03266
03267 if (INFO_LEVEL_IS_UNIX(info_level)) {
03268
03269 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
03270 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
03271 return UNIXERROR(ERRDOS,ERRbadpath);
03272 }
03273 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
03274 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
03275 return UNIXERROR(ERRDOS,ERRbadpath);
03276 }
03277
03278 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
03279 } else {
03280
03281
03282
03283 CHECK_FSP(fsp,conn);
03284
03285 pstrcpy(fname, fsp->fsp_name);
03286 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
03287 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
03288 return(UNIXERROR(ERRDOS,ERRbadfid));
03289 }
03290 pos = fsp->fh->position_information;
03291 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
03292 access_mask = fsp->access_mask;
03293 }
03294 } else {
03295 NTSTATUS status = NT_STATUS_OK;
03296
03297
03298 if (total_params < 7) {
03299 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03300 }
03301
03302 info_level = SVAL(params,0);
03303
03304 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
03305
03306 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
03307 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
03308 }
03309
03310 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
03311 if (!NT_STATUS_IS_OK(status)) {
03312 return ERROR_NT(status);
03313 }
03314
03315 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
03316 if (!NT_STATUS_IS_OK(status)) {
03317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
03318 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
03319 }
03320 return ERROR_NT(status);
03321 }
03322
03323 status = unix_convert(conn, fname, False, NULL, &sbuf);
03324 if (!NT_STATUS_IS_OK(status)) {
03325 return ERROR_NT(status);
03326 }
03327 status = check_name(conn, fname);
03328 if (!NT_STATUS_IS_OK(status)) {
03329 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
03330 return ERROR_NT(status);
03331 }
03332
03333 if (INFO_LEVEL_IS_UNIX(info_level)) {
03334
03335 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
03336 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
03337 return UNIXERROR(ERRDOS,ERRbadpath);
03338 }
03339 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
03340 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
03341 return UNIXERROR(ERRDOS,ERRbadpath);
03342 }
03343
03344 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
03345 if (delete_pending) {
03346 return ERROR_NT(NT_STATUS_DELETE_PENDING);
03347 }
03348 }
03349
03350 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
03351 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
03352 }
03353
03354 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
03355 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
03356
03357 p = strrchr_m(fname,'/');
03358 if (!p)
03359 base_name = fname;
03360 else
03361 base_name = p+1;
03362
03363 mode = dos_mode(conn,fname,&sbuf);
03364 if (!mode)
03365 mode = FILE_ATTRIBUTE_NORMAL;
03366
03367 nlink = sbuf.st_nlink;
03368
03369 if (nlink && (mode&aDIR)) {
03370 nlink = 1;
03371 }
03372
03373 if ((nlink > 0) && delete_pending) {
03374 nlink -= 1;
03375 }
03376
03377 fullpathname = fname;
03378 if (!(mode & aDIR))
03379 file_size = get_file_size(sbuf);
03380
03381
03382 switch (info_level) {
03383 case SMB_INFO_QUERY_EAS_FROM_LIST:
03384 {
03385
03386 uint32 ea_size;
03387
03388 if (total_data < 4) {
03389 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03390 }
03391 ea_size = IVAL(pdata,0);
03392
03393 if (total_data > 0 && ea_size != total_data) {
03394 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
03395 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
03396 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03397 }
03398
03399 if (!lp_ea_support(SNUM(conn))) {
03400 return ERROR_DOS(ERRDOS,ERReasnotsupported);
03401 }
03402
03403 if ((data_ctx = talloc_init("ea_list")) == NULL) {
03404 return ERROR_NT(NT_STATUS_NO_MEMORY);
03405 }
03406
03407
03408 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
03409 if (!ea_list) {
03410 talloc_destroy(data_ctx);
03411 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03412 }
03413 break;
03414 }
03415
03416 case SMB_QUERY_POSIX_LOCK:
03417 {
03418 if (fsp == NULL || fsp->fh->fd == -1) {
03419 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
03420 }
03421
03422 if (total_data != POSIX_LOCK_DATA_SIZE) {
03423 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03424 }
03425
03426 if ((data_ctx = talloc_init("lock_request")) == NULL) {
03427 return ERROR_NT(NT_STATUS_NO_MEMORY);
03428 }
03429
03430
03431 lock_data = (char *)TALLOC_MEMDUP(
03432 data_ctx, pdata, total_data);
03433 if (!lock_data) {
03434 talloc_destroy(data_ctx);
03435 return ERROR_NT(NT_STATUS_NO_MEMORY);
03436 }
03437 }
03438 default:
03439 break;
03440 }
03441
03442 *pparams = (char *)SMB_REALLOC(*pparams,2);
03443 if (*pparams == NULL) {
03444 talloc_destroy(data_ctx);
03445 return ERROR_NT(NT_STATUS_NO_MEMORY);
03446 }
03447 params = *pparams;
03448 SSVAL(params,0,0);
03449 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
03450 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
03451 if (*ppdata == NULL ) {
03452 talloc_destroy(data_ctx);
03453 return ERROR_NT(NT_STATUS_NO_MEMORY);
03454 }
03455 pdata = *ppdata;
03456
03457 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
03458 mtime_ts = get_mtimespec(&sbuf);
03459 atime_ts = get_atimespec(&sbuf);
03460
03461 allocation_size = get_allocation_size(conn,fsp,&sbuf);
03462
03463 if (fsp) {
03464 if (!null_timespec(fsp->pending_modtime)) {
03465
03466 mtime_ts = fsp->pending_modtime;
03467 }
03468 } else {
03469
03470 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
03471 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
03472
03473 mtime_ts = fsp1->pending_modtime;
03474 }
03475 if (fsp1 && fsp1->initial_allocation_size) {
03476 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
03477 }
03478 }
03479
03480 if (lp_dos_filetime_resolution(SNUM(conn))) {
03481 dos_filetime_timespec(&create_time_ts);
03482 dos_filetime_timespec(&mtime_ts);
03483 dos_filetime_timespec(&atime_ts);
03484 }
03485
03486 create_time = convert_timespec_to_time_t(create_time_ts);
03487 mtime = convert_timespec_to_time_t(mtime_ts);
03488 atime = convert_timespec_to_time_t(atime_ts);
03489
03490
03491
03492 if (strequal(base_name,".")) {
03493 pstrcpy(dos_fname, "\\");
03494 } else {
03495 pstr_sprintf(dos_fname, "\\%s", fname);
03496 string_replace(dos_fname, '/', '\\');
03497 }
03498
03499 switch (info_level) {
03500 case SMB_INFO_STANDARD:
03501 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
03502 data_size = 22;
03503 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
03504 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
03505 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime);
03506 SIVAL(pdata,l1_cbFile,(uint32)file_size);
03507 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
03508 SSVAL(pdata,l1_attrFile,mode);
03509 break;
03510
03511 case SMB_INFO_QUERY_EA_SIZE:
03512 {
03513 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
03514 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
03515 data_size = 26;
03516 srv_put_dos_date2(pdata,0,create_time);
03517 srv_put_dos_date2(pdata,4,atime);
03518 srv_put_dos_date2(pdata,8,mtime);
03519 SIVAL(pdata,12,(uint32)file_size);
03520 SIVAL(pdata,16,(uint32)allocation_size);
03521 SSVAL(pdata,20,mode);
03522 SIVAL(pdata,22,ea_size);
03523 break;
03524 }
03525
03526 case SMB_INFO_IS_NAME_VALID:
03527 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
03528 if (tran_call == TRANSACT2_QFILEINFO) {
03529
03530 return ERROR_DOS(ERRDOS,ERRbadfunc);
03531 }
03532 data_size = 0;
03533 param_size = 0;
03534 break;
03535
03536 case SMB_INFO_QUERY_EAS_FROM_LIST:
03537 {
03538 size_t total_ea_len = 0;
03539 struct ea_list *ea_file_list = NULL;
03540
03541 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
03542
03543 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
03544 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
03545
03546 if (!ea_list || (total_ea_len > data_size)) {
03547 talloc_destroy(data_ctx);
03548 data_size = 4;
03549 SIVAL(pdata,0,4);
03550 break;
03551 }
03552
03553 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
03554 talloc_destroy(data_ctx);
03555 break;
03556 }
03557
03558 case SMB_INFO_QUERY_ALL_EAS:
03559 {
03560
03561 size_t total_ea_len = 0;
03562
03563 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
03564
03565 data_ctx = talloc_init("ea_ctx");
03566 if (!data_ctx) {
03567 return ERROR_NT(NT_STATUS_NO_MEMORY);
03568 }
03569
03570 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
03571 if (!ea_list || (total_ea_len > data_size)) {
03572 talloc_destroy(data_ctx);
03573 data_size = 4;
03574 SIVAL(pdata,0,4);
03575 break;
03576 }
03577
03578 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
03579 talloc_destroy(data_ctx);
03580 break;
03581 }
03582
03583 case SMB_FILE_BASIC_INFORMATION:
03584 case SMB_QUERY_FILE_BASIC_INFO:
03585
03586 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
03587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
03588 data_size = 36;
03589 } else {
03590 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
03591 data_size = 40;
03592 SIVAL(pdata,36,0);
03593 }
03594 put_long_date_timespec(pdata,create_time_ts);
03595 put_long_date_timespec(pdata+8,atime_ts);
03596 put_long_date_timespec(pdata+16,mtime_ts);
03597 put_long_date_timespec(pdata+24,mtime_ts);
03598 SIVAL(pdata,32,mode);
03599
03600 DEBUG(5,("SMB_QFBI - "));
03601 DEBUG(5,("create: %s ", ctime(&create_time)));
03602 DEBUG(5,("access: %s ", ctime(&atime)));
03603 DEBUG(5,("write: %s ", ctime(&mtime)));
03604 DEBUG(5,("change: %s ", ctime(&mtime)));
03605 DEBUG(5,("mode: %x\n", mode));
03606 break;
03607
03608 case SMB_FILE_STANDARD_INFORMATION:
03609 case SMB_QUERY_FILE_STANDARD_INFO:
03610
03611 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
03612 data_size = 24;
03613 SOFF_T(pdata,0,allocation_size);
03614 SOFF_T(pdata,8,file_size);
03615 SIVAL(pdata,16,nlink);
03616 SCVAL(pdata,20,delete_pending?1:0);
03617 SCVAL(pdata,21,(mode&aDIR)?1:0);
03618 SSVAL(pdata,22,0);
03619 break;
03620
03621 case SMB_FILE_EA_INFORMATION:
03622 case SMB_QUERY_FILE_EA_INFO:
03623 {
03624 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
03625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
03626 data_size = 4;
03627 SIVAL(pdata,0,ea_size);
03628 break;
03629 }
03630
03631
03632 case SMB_QUERY_FILE_ALT_NAME_INFO:
03633 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
03634 {
03635 pstring short_name;
03636
03637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
03638 pstrcpy(short_name,base_name);
03639
03640 if(!mangle_is_8_3(short_name, True, conn->params)) {
03641 mangle_map(short_name,True,True,conn->params);
03642 }
03643 len = srvstr_push(outbuf, pdata+4, short_name, max_data_bytes - 4, STR_UNICODE);
03644 data_size = 4 + len;
03645 SIVAL(pdata,0,len);
03646 break;
03647 }
03648
03649 case SMB_QUERY_FILE_NAME_INFO:
03650
03651
03652
03653 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - 4, STR_UNICODE);
03654 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
03655 data_size = 4 + len;
03656 SIVAL(pdata,0,len);
03657 break;
03658
03659 case SMB_FILE_ALLOCATION_INFORMATION:
03660 case SMB_QUERY_FILE_ALLOCATION_INFO:
03661 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
03662 data_size = 8;
03663 SOFF_T(pdata,0,allocation_size);
03664 break;
03665
03666 case SMB_FILE_END_OF_FILE_INFORMATION:
03667 case SMB_QUERY_FILE_END_OF_FILEINFO:
03668 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
03669 data_size = 8;
03670 SOFF_T(pdata,0,file_size);
03671 break;
03672
03673 case SMB_QUERY_FILE_ALL_INFO:
03674 case SMB_FILE_ALL_INFORMATION:
03675 {
03676 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
03677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
03678 put_long_date_timespec(pdata,create_time_ts);
03679 put_long_date_timespec(pdata+8,atime_ts);
03680 put_long_date_timespec(pdata+16,mtime_ts);
03681 put_long_date_timespec(pdata+24,mtime_ts);
03682 SIVAL(pdata,32,mode);
03683 SIVAL(pdata,36,0);
03684 pdata += 40;
03685 SOFF_T(pdata,0,allocation_size);
03686 SOFF_T(pdata,8,file_size);
03687 SIVAL(pdata,16,nlink);
03688 SCVAL(pdata,20,delete_pending);
03689 SCVAL(pdata,21,(mode&aDIR)?1:0);
03690 SSVAL(pdata,22,0);
03691 pdata += 24;
03692 SIVAL(pdata,0,ea_size);
03693 pdata += 4;
03694 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - (pdata+4 - *ppdata), STR_UNICODE);
03695 SIVAL(pdata,0,len);
03696 pdata += 4 + len;
03697 data_size = PTR_DIFF(pdata,(*ppdata));
03698 break;
03699 }
03700 case SMB_FILE_INTERNAL_INFORMATION:
03701
03702
03703
03704
03705
03706
03707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
03708 SIVAL(pdata,0,sbuf.st_ino);
03709 SIVAL(pdata,4,sbuf.st_dev);
03710 data_size = 8;
03711 break;
03712
03713 case SMB_FILE_ACCESS_INFORMATION:
03714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
03715 SIVAL(pdata,0,access_mask);
03716 data_size = 4;
03717 break;
03718
03719 case SMB_FILE_NAME_INFORMATION:
03720
03721 {
03722 size_t byte_len;
03723 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
03724 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
03725 SIVAL(pdata,0,byte_len);
03726 data_size = 4 + byte_len;
03727 break;
03728 }
03729
03730 case SMB_FILE_DISPOSITION_INFORMATION:
03731 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
03732 data_size = 1;
03733 SCVAL(pdata,0,delete_pending);
03734 break;
03735
03736 case SMB_FILE_POSITION_INFORMATION:
03737 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
03738 data_size = 8;
03739 SOFF_T(pdata,0,pos);
03740 break;
03741
03742 case SMB_FILE_MODE_INFORMATION:
03743 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
03744 SIVAL(pdata,0,mode);
03745 data_size = 4;
03746 break;
03747
03748 case SMB_FILE_ALIGNMENT_INFORMATION:
03749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
03750 SIVAL(pdata,0,0);
03751 data_size = 4;
03752 break;
03753
03754 #if 0
03755
03756
03757
03758
03759
03760 case SMB_QUERY_FILE_STREAM_INFO:
03761 #endif
03762 case SMB_FILE_STREAM_INFORMATION:
03763 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
03764 if (mode & aDIR) {
03765 data_size = 0;
03766 } else {
03767 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
03768 SIVAL(pdata,0,0);
03769 SIVAL(pdata,4,byte_len);
03770 SOFF_T(pdata,8,file_size);
03771 SOFF_T(pdata,16,allocation_size);
03772 data_size = 24 + byte_len;
03773 }
03774 break;
03775
03776 case SMB_QUERY_COMPRESSION_INFO:
03777 case SMB_FILE_COMPRESSION_INFORMATION:
03778 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
03779 SOFF_T(pdata,0,file_size);
03780 SIVAL(pdata,8,0);
03781 SIVAL(pdata,12,0);
03782 data_size = 16;
03783 break;
03784
03785 case SMB_FILE_NETWORK_OPEN_INFORMATION:
03786 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
03787 put_long_date_timespec(pdata,create_time_ts);
03788 put_long_date_timespec(pdata+8,atime_ts);
03789 put_long_date_timespec(pdata+16,mtime_ts);
03790 put_long_date_timespec(pdata+24,mtime_ts);
03791 SOFF_T(pdata,32,allocation_size);
03792 SOFF_T(pdata,40,file_size);
03793 SIVAL(pdata,48,mode);
03794 SIVAL(pdata,52,0);
03795 data_size = 56;
03796 break;
03797
03798 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
03799 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
03800 SIVAL(pdata,0,mode);
03801 SIVAL(pdata,4,0);
03802 data_size = 8;
03803 break;
03804
03805
03806
03807
03808
03809 case SMB_QUERY_FILE_UNIX_BASIC:
03810
03811 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
03812 data_size = PTR_DIFF(pdata,(*ppdata));
03813
03814 {
03815 int i;
03816 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
03817
03818 for (i=0; i<100; i++)
03819 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
03820 DEBUG(4,("\n"));
03821 }
03822
03823 break;
03824
03825 case SMB_QUERY_FILE_UNIX_INFO2:
03826
03827 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
03828 data_size = PTR_DIFF(pdata,(*ppdata));
03829
03830 {
03831 int i;
03832 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
03833
03834 for (i=0; i<100; i++)
03835 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
03836 DEBUG(4,("\n"));
03837 }
03838
03839 break;
03840
03841 case SMB_QUERY_FILE_UNIX_LINK:
03842 {
03843 pstring buffer;
03844
03845 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
03846 #ifdef S_ISLNK
03847 if(!S_ISLNK(sbuf.st_mode))
03848 return(UNIXERROR(ERRSRV,ERRbadlink));
03849 #else
03850 return(UNIXERROR(ERRDOS,ERRbadlink));
03851 #endif
03852 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);
03853 if (len == -1)
03854 return(UNIXERROR(ERRDOS,ERRnoaccess));
03855 buffer[len] = 0;
03856 len = srvstr_push(outbuf, pdata, buffer, max_data_bytes, STR_TERMINATE);
03857 pdata += len;
03858 data_size = PTR_DIFF(pdata,(*ppdata));
03859
03860 break;
03861 }
03862
03863 #if defined(HAVE_POSIX_ACLS)
03864 case SMB_QUERY_POSIX_ACL:
03865 {
03866 SMB_ACL_T file_acl = NULL;
03867 SMB_ACL_T def_acl = NULL;
03868 uint16 num_file_acls = 0;
03869 uint16 num_def_acls = 0;
03870
03871 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
03872 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
03873 } else {
03874 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
03875 }
03876
03877 if (file_acl == NULL && no_acl_syscall_error(errno)) {
03878 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
03879 fname ));
03880 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
03881 }
03882
03883 if (S_ISDIR(sbuf.st_mode)) {
03884 if (fsp && fsp->is_directory) {
03885 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
03886 } else {
03887 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
03888 }
03889 def_acl = free_empty_sys_acl(conn, def_acl);
03890 }
03891
03892 num_file_acls = count_acl_entries(conn, file_acl);
03893 num_def_acls = count_acl_entries(conn, def_acl);
03894
03895 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
03896 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
03897 data_size,
03898 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
03899 SMB_POSIX_ACL_HEADER_SIZE) ));
03900 if (file_acl) {
03901 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
03902 }
03903 if (def_acl) {
03904 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03905 }
03906 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
03907 }
03908
03909 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
03910 SSVAL(pdata,2,num_file_acls);
03911 SSVAL(pdata,4,num_def_acls);
03912 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
03913 if (file_acl) {
03914 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
03915 }
03916 if (def_acl) {
03917 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03918 }
03919 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
03920 }
03921 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
03922 if (file_acl) {
03923 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
03924 }
03925 if (def_acl) {
03926 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03927 }
03928 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
03929 }
03930
03931 if (file_acl) {
03932 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
03933 }
03934 if (def_acl) {
03935 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
03936 }
03937 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
03938 break;
03939 }
03940 #endif
03941
03942
03943 case SMB_QUERY_POSIX_LOCK:
03944 {
03945 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
03946 SMB_BIG_UINT count;
03947 SMB_BIG_UINT offset;
03948 uint32 lock_pid;
03949 enum brl_type lock_type;
03950
03951 if (total_data != POSIX_LOCK_DATA_SIZE) {
03952 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03953 }
03954
03955 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
03956 case POSIX_LOCK_TYPE_READ:
03957 lock_type = READ_LOCK;
03958 break;
03959 case POSIX_LOCK_TYPE_WRITE:
03960 lock_type = WRITE_LOCK;
03961 break;
03962 case POSIX_LOCK_TYPE_UNLOCK:
03963 default:
03964
03965 talloc_destroy(data_ctx);
03966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03967 }
03968
03969 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
03970 #if defined(HAVE_LONGLONG)
03971 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
03972 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
03973 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
03974 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
03975 #else
03976 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
03977 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
03978 #endif
03979
03980 status = query_lock(fsp,
03981 &lock_pid,
03982 &count,
03983 &offset,
03984 &lock_type,
03985 POSIX_LOCK);
03986
03987 if (ERROR_WAS_LOCK_DENIED(status)) {
03988
03989 data_size = POSIX_LOCK_DATA_SIZE;
03990
03991 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
03992 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
03993 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
03994 #if defined(HAVE_LONGLONG)
03995 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
03996 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
03997 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
03998 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
03999 #else
04000 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
04001 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
04002 #endif
04003
04004 } else if (NT_STATUS_IS_OK(status)) {
04005
04006
04007 data_size = POSIX_LOCK_DATA_SIZE;
04008 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
04009 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
04010 } else {
04011 return ERROR_NT(status);
04012 }
04013 break;
04014 }
04015
04016 default:
04017 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
04018 }
04019
04020 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
04021
04022 return(-1);
04023 }
04024
04025
04026
04027
04028
04029
04030 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
04031 {
04032 SMB_STRUCT_STAT sbuf1, sbuf2;
04033 pstring last_component_oldname;
04034 pstring last_component_newname;
04035 NTSTATUS status = NT_STATUS_OK;
04036
04037 ZERO_STRUCT(sbuf1);
04038 ZERO_STRUCT(sbuf2);
04039
04040 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
04041 if (!NT_STATUS_IS_OK(status)) {
04042 return status;
04043 }
04044
04045 status = check_name(conn, oldname);
04046 if (!NT_STATUS_IS_OK(status)) {
04047 return status;
04048 }
04049
04050
04051 if (!VALID_STAT(sbuf1)) {
04052 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04053 }
04054
04055 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
04056 if (!NT_STATUS_IS_OK(status)) {
04057 return status;
04058 }
04059
04060 status = check_name(conn, newname);
04061 if (!NT_STATUS_IS_OK(status)) {
04062 return status;
04063 }
04064
04065
04066 if (VALID_STAT(sbuf2)) {
04067 return NT_STATUS_OBJECT_NAME_COLLISION;
04068 }
04069
04070
04071 if (S_ISDIR(sbuf1.st_mode)) {
04072 return NT_STATUS_FILE_IS_A_DIRECTORY;
04073 }
04074
04075
04076 status = reduce_name(conn, oldname);
04077 if (!NT_STATUS_IS_OK(status)) {
04078 return status;
04079 }
04080
04081 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
04082
04083 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
04084 status = map_nt_error_from_unix(errno);
04085 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
04086 nt_errstr(status), newname, oldname));
04087 }
04088
04089 return status;
04090 }
04091
04092
04093
04094
04095
04096 static NTSTATUS smb_set_file_time(connection_struct *conn,
04097 files_struct *fsp,
04098 const char *fname,
04099 const SMB_STRUCT_STAT *psbuf,
04100 struct timespec ts[2])
04101 {
04102 uint32 action =
04103 FILE_NOTIFY_CHANGE_LAST_ACCESS
04104 |FILE_NOTIFY_CHANGE_LAST_WRITE;
04105
04106
04107 if (!VALID_STAT(*psbuf)) {
04108 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04109 }
04110
04111
04112 if (null_timespec(ts[0])) {
04113 ts[0] = get_atimespec(psbuf);
04114 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
04115 }
04116
04117 if (null_timespec(ts[1])) {
04118 ts[1] = get_mtimespec(psbuf);
04119 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
04120 }
04121
04122 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
04123 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
04124
04125
04126
04127
04128
04129
04130 {
04131 struct timespec mts = get_mtimespec(psbuf);
04132 struct timespec ats = get_atimespec(psbuf);
04133 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
04134 return NT_STATUS_OK;
04135 }
04136 }
04137
04138 if(fsp != NULL) {
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149 if (!null_timespec(ts[1])) {
04150 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
04151 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
04152 fsp_set_pending_modtime(fsp, ts[1]);
04153 }
04154
04155 }
04156 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
04157
04158 if(file_ntimes(conn, fname, ts)!=0) {
04159 return map_nt_error_from_unix(errno);
04160 }
04161 if (action != 0) {
04162 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
04163 }
04164 return NT_STATUS_OK;
04165 }
04166
04167
04168
04169
04170
04171 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
04172 const char *fname,
04173 SMB_STRUCT_STAT *psbuf,
04174 uint32 dosmode)
04175 {
04176 if (!VALID_STAT(*psbuf)) {
04177 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04178 }
04179
04180 if (dosmode) {
04181 if (S_ISDIR(psbuf->st_mode)) {
04182 dosmode |= aDIR;
04183 } else {
04184 dosmode &= ~aDIR;
04185 }
04186 }
04187
04188 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
04189
04190
04191 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
04192
04193 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
04194 fname, (unsigned int)dosmode ));
04195
04196 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
04197 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
04198 fname, strerror(errno)));
04199 return map_nt_error_from_unix(errno);
04200 }
04201 }
04202 return NT_STATUS_OK;
04203 }
04204
04205
04206
04207
04208
04209 static NTSTATUS smb_set_file_size(connection_struct *conn,
04210 files_struct *fsp,
04211 const char *fname,
04212 SMB_STRUCT_STAT *psbuf,
04213 SMB_OFF_T size)
04214 {
04215 NTSTATUS status = NT_STATUS_OK;
04216 files_struct *new_fsp = NULL;
04217
04218 if (!VALID_STAT(*psbuf)) {
04219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04220 }
04221
04222 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
04223
04224 if (size == get_file_size(*psbuf)) {
04225 return NT_STATUS_OK;
04226 }
04227
04228 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
04229 fname, (double)size ));
04230
04231 if (fsp && fsp->fh->fd != -1) {
04232
04233 if (vfs_set_filelen(fsp, size) == -1) {
04234 return map_nt_error_from_unix(errno);
04235 }
04236 return NT_STATUS_OK;
04237 }
04238
04239 status = open_file_ntcreate(conn, fname, psbuf,
04240 FILE_WRITE_DATA,
04241 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
04242 FILE_OPEN,
04243 0,
04244 FILE_ATTRIBUTE_NORMAL,
04245 FORCE_OPLOCK_BREAK_TO_NONE,
04246 NULL, &new_fsp);
04247
04248 if (!NT_STATUS_IS_OK(status)) {
04249
04250 return status;
04251 }
04252
04253 if (vfs_set_filelen(new_fsp, size) == -1) {
04254 status = map_nt_error_from_unix(errno);
04255 close_file(new_fsp,NORMAL_CLOSE);
04256 return status;
04257 }
04258
04259 close_file(new_fsp,NORMAL_CLOSE);
04260 return NT_STATUS_OK;
04261 }
04262
04263
04264
04265
04266
04267 static NTSTATUS smb_info_set_ea(connection_struct *conn,
04268 const char *pdata,
04269 int total_data,
04270 files_struct *fsp,
04271 const char *fname)
04272 {
04273 struct ea_list *ea_list = NULL;
04274 TALLOC_CTX *ctx = NULL;
04275 NTSTATUS status = NT_STATUS_OK;
04276
04277 if (total_data < 10) {
04278
04279
04280
04281
04282 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
04283
04284 return NT_STATUS_OK;
04285 }
04286
04287 return NT_STATUS_INVALID_PARAMETER;
04288 }
04289
04290 if (IVAL(pdata,0) > total_data) {
04291 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
04292 IVAL(pdata,0), (unsigned int)total_data));
04293 return NT_STATUS_INVALID_PARAMETER;
04294 }
04295
04296 ctx = talloc_init("SMB_INFO_SET_EA");
04297 if (!ctx) {
04298 return NT_STATUS_NO_MEMORY;
04299 }
04300 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
04301 if (!ea_list) {
04302 talloc_destroy(ctx);
04303 return NT_STATUS_INVALID_PARAMETER;
04304 }
04305 status = set_ea(conn, fsp, fname, ea_list);
04306 talloc_destroy(ctx);
04307
04308 return status;
04309 }
04310
04311
04312
04313
04314
04315 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
04316 const char *pdata,
04317 int total_data,
04318 files_struct *fsp,
04319 const char *fname,
04320 SMB_STRUCT_STAT *psbuf)
04321 {
04322 NTSTATUS status = NT_STATUS_OK;
04323 BOOL delete_on_close;
04324 uint32 dosmode = 0;
04325
04326 if (total_data < 1) {
04327 return NT_STATUS_INVALID_PARAMETER;
04328 }
04329
04330 if (fsp == NULL) {
04331 return NT_STATUS_INVALID_HANDLE;
04332 }
04333
04334 delete_on_close = (CVAL(pdata,0) ? True : False);
04335 dosmode = dos_mode(conn, fname, psbuf);
04336
04337 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
04338 "delete_on_close = %u\n",
04339 fsp->fsp_name,
04340 (unsigned int)dosmode,
04341 (unsigned int)delete_on_close ));
04342
04343 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
04344
04345 if (!NT_STATUS_IS_OK(status)) {
04346 return status;
04347 }
04348
04349
04350 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
04351 return NT_STATUS_ACCESS_DENIED;
04352 }
04353 return NT_STATUS_OK;
04354 }
04355
04356
04357
04358
04359
04360 static NTSTATUS smb_file_position_information(connection_struct *conn,
04361 const char *pdata,
04362 int total_data,
04363 files_struct *fsp)
04364 {
04365 SMB_BIG_UINT position_information;
04366
04367 if (total_data < 8) {
04368 return NT_STATUS_INVALID_PARAMETER;
04369 }
04370
04371 if (fsp == NULL) {
04372
04373 return NT_STATUS_OK;
04374 }
04375
04376 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
04377 #ifdef LARGE_SMB_OFF_T
04378 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
04379 #else
04380 if (IVAL(pdata,4) != 0) {
04381
04382 return NT_STATUS_INVALID_PARAMETER;
04383 }
04384 #endif
04385
04386 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
04387 fsp->fsp_name, (double)position_information ));
04388 fsp->fh->position_information = position_information;
04389 return NT_STATUS_OK;
04390 }
04391
04392
04393
04394
04395
04396 static NTSTATUS smb_file_mode_information(connection_struct *conn,
04397 const char *pdata,
04398 int total_data)
04399 {
04400 uint32 mode;
04401
04402 if (total_data < 4) {
04403 return NT_STATUS_INVALID_PARAMETER;
04404 }
04405 mode = IVAL(pdata,0);
04406 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
04407 return NT_STATUS_INVALID_PARAMETER;
04408 }
04409 return NT_STATUS_OK;
04410 }
04411
04412
04413
04414
04415
04416 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
04417 char *inbuf,
04418 const char *pdata,
04419 int total_data,
04420 const char *fname)
04421 {
04422 pstring link_target;
04423 const char *newname = fname;
04424 NTSTATUS status = NT_STATUS_OK;
04425
04426
04427
04428
04429 if (total_data == 0) {
04430 return NT_STATUS_INVALID_PARAMETER;
04431 }
04432
04433 if (!lp_symlinks(SNUM(conn))) {
04434 return NT_STATUS_ACCESS_DENIED;
04435 }
04436
04437 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
04438
04439
04440
04441 if (!lp_widelinks(SNUM(conn))) {
04442 pstring rel_name;
04443 char *last_dirp = NULL;
04444
04445 if (*link_target == '/') {
04446
04447 return NT_STATUS_ACCESS_DENIED;
04448 }
04449 pstrcpy(rel_name, newname);
04450 last_dirp = strrchr_m(rel_name, '/');
04451 if (last_dirp) {
04452 last_dirp[1] = '\0';
04453 } else {
04454 pstrcpy(rel_name, "./");
04455 }
04456 pstrcat(rel_name, link_target);
04457
04458 status = check_name(conn, rel_name);
04459 if (!NT_STATUS_IS_OK(status)) {
04460 return status;
04461 }
04462 }
04463
04464 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
04465 newname, link_target ));
04466
04467 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
04468 return map_nt_error_from_unix(errno);
04469 }
04470
04471 return NT_STATUS_OK;
04472 }
04473
04474
04475
04476
04477
04478 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
04479 char *inbuf,
04480 char *outbuf,
04481 const char *pdata,
04482 int total_data,
04483 pstring fname)
04484 {
04485 pstring oldname;
04486 NTSTATUS status = NT_STATUS_OK;
04487
04488
04489 if (total_data == 0) {
04490 return NT_STATUS_INVALID_PARAMETER;
04491 }
04492
04493 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
04494 if (!NT_STATUS_IS_OK(status)) {
04495 return status;
04496 }
04497
04498 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
04499 if (!NT_STATUS_IS_OK(status)) {
04500 return status;
04501 }
04502
04503 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
04504 fname, oldname));
04505
04506 return hardlink_internals(conn, oldname, fname);
04507 }
04508
04509
04510
04511
04512
04513 static NTSTATUS smb_file_rename_information(connection_struct *conn,
04514 char *inbuf,
04515 char *outbuf,
04516 const char *pdata,
04517 int total_data,
04518 files_struct *fsp,
04519 pstring fname)
04520 {
04521 BOOL overwrite;
04522
04523 uint32 len;
04524 pstring newname;
04525 pstring base_name;
04526 BOOL dest_has_wcard = False;
04527 NTSTATUS status = NT_STATUS_OK;
04528 char *p;
04529
04530 if (total_data < 13) {
04531 return NT_STATUS_INVALID_PARAMETER;
04532 }
04533
04534 overwrite = (CVAL(pdata,0) ? True : False);
04535
04536 len = IVAL(pdata,8);
04537
04538 if (len > (total_data - 12) || (len == 0)) {
04539 return NT_STATUS_INVALID_PARAMETER;
04540 }
04541
04542 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
04543 if (!NT_STATUS_IS_OK(status)) {
04544 return status;
04545 }
04546
04547 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
04548 if (!NT_STATUS_IS_OK(status)) {
04549 return status;
04550 }
04551
04552
04553 if (strchr_m(newname, '/')) {
04554 return NT_STATUS_NOT_SUPPORTED;
04555 }
04556
04557
04558 pstrcpy(base_name, fname);
04559 p = strrchr_m(base_name, '/');
04560 if (p) {
04561 p[1] = '\0';
04562 } else {
04563 pstrcpy(base_name, "./");
04564 }
04565
04566 pstrcat(base_name, newname);
04567
04568 if (fsp) {
04569 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
04570 fsp->fnum, fsp->fsp_name, base_name ));
04571 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
04572 } else {
04573 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
04574 fname, newname ));
04575 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
04576 }
04577
04578 return status;
04579 }
04580
04581
04582
04583
04584
04585 #if defined(HAVE_POSIX_ACLS)
04586 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
04587 const char *pdata,
04588 int total_data,
04589 files_struct *fsp,
04590 const char *fname,
04591 SMB_STRUCT_STAT *psbuf)
04592 {
04593 uint16 posix_acl_version;
04594 uint16 num_file_acls;
04595 uint16 num_def_acls;
04596 BOOL valid_file_acls = True;
04597 BOOL valid_def_acls = True;
04598
04599 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
04600 return NT_STATUS_INVALID_PARAMETER;
04601 }
04602 posix_acl_version = SVAL(pdata,0);
04603 num_file_acls = SVAL(pdata,2);
04604 num_def_acls = SVAL(pdata,4);
04605
04606 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
04607 valid_file_acls = False;
04608 num_file_acls = 0;
04609 }
04610
04611 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
04612 valid_def_acls = False;
04613 num_def_acls = 0;
04614 }
04615
04616 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
04617 return NT_STATUS_INVALID_PARAMETER;
04618 }
04619
04620 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
04621 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
04622 return NT_STATUS_INVALID_PARAMETER;
04623 }
04624
04625 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
04626 fname ? fname : fsp->fsp_name,
04627 (unsigned int)num_file_acls,
04628 (unsigned int)num_def_acls));
04629
04630 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
04631 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
04632 return map_nt_error_from_unix(errno);
04633 }
04634
04635 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
04636 pdata + SMB_POSIX_ACL_HEADER_SIZE +
04637 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
04638 return map_nt_error_from_unix(errno);
04639 }
04640 return NT_STATUS_OK;
04641 }
04642 #endif
04643
04644
04645
04646
04647
04648 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
04649 char *inbuf,
04650 int length,
04651 const char *pdata,
04652 int total_data,
04653 files_struct *fsp)
04654 {
04655 SMB_BIG_UINT count;
04656 SMB_BIG_UINT offset;
04657 uint32 lock_pid;
04658 BOOL blocking_lock = False;
04659 enum brl_type lock_type;
04660 NTSTATUS status = NT_STATUS_OK;
04661
04662 if (fsp == NULL || fsp->fh->fd == -1) {
04663 return NT_STATUS_INVALID_HANDLE;
04664 }
04665
04666 if (total_data != POSIX_LOCK_DATA_SIZE) {
04667 return NT_STATUS_INVALID_PARAMETER;
04668 }
04669
04670 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
04671 case POSIX_LOCK_TYPE_READ:
04672 lock_type = READ_LOCK;
04673 break;
04674 case POSIX_LOCK_TYPE_WRITE:
04675
04676 if (!fsp->can_write) {
04677 return NT_STATUS_INVALID_HANDLE;
04678 }
04679 lock_type = WRITE_LOCK;
04680 break;
04681 case POSIX_LOCK_TYPE_UNLOCK:
04682 lock_type = UNLOCK_LOCK;
04683 break;
04684 default:
04685 return NT_STATUS_INVALID_PARAMETER;
04686 }
04687
04688 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
04689 blocking_lock = False;
04690 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
04691 blocking_lock = True;
04692 } else {
04693 return NT_STATUS_INVALID_PARAMETER;
04694 }
04695
04696 if (!lp_blocking_locks(SNUM(conn))) {
04697 blocking_lock = False;
04698 }
04699
04700 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
04701 #if defined(HAVE_LONGLONG)
04702 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
04703 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
04704 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
04705 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
04706 #else
04707 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
04708 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
04709 #endif
04710
04711 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
04712 "lock_pid = %u, count = %.0f, offset = %.0f\n",
04713 fsp->fsp_name,
04714 (unsigned int)lock_type,
04715 (unsigned int)lock_pid,
04716 (double)count,
04717 (double)offset ));
04718
04719 if (lock_type == UNLOCK_LOCK) {
04720 status = do_unlock(fsp,
04721 lock_pid,
04722 count,
04723 offset,
04724 POSIX_LOCK);
04725 } else {
04726 uint32 block_smbpid;
04727
04728 struct byte_range_lock *br_lck = do_lock(fsp,
04729 lock_pid,
04730 count,
04731 offset,
04732 lock_type,
04733 POSIX_LOCK,
04734 blocking_lock,
04735 &status,
04736 &block_smbpid);
04737
04738 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
04739
04740
04741
04742
04743
04744 if(push_blocking_lock_request(br_lck,
04745 inbuf, length,
04746 fsp,
04747 -1,
04748 0,
04749 lock_pid,
04750 lock_type,
04751 POSIX_LOCK,
04752 offset,
04753 count,
04754 block_smbpid)) {
04755 TALLOC_FREE(br_lck);
04756 return status;
04757 }
04758 }
04759 TALLOC_FREE(br_lck);
04760 }
04761
04762 return status;
04763 }
04764
04765
04766
04767
04768
04769 static NTSTATUS smb_set_info_standard(connection_struct *conn,
04770 const char *pdata,
04771 int total_data,
04772 files_struct *fsp,
04773 const char *fname,
04774 const SMB_STRUCT_STAT *psbuf)
04775 {
04776 struct timespec ts[2];
04777
04778 if (total_data < 12) {
04779 return NT_STATUS_INVALID_PARAMETER;
04780 }
04781
04782
04783 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
04784
04785 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
04786
04787 DEBUG(10,("smb_set_info_standard: file %s\n",
04788 fname ? fname : fsp->fsp_name ));
04789
04790 return smb_set_file_time(conn,
04791 fsp,
04792 fname,
04793 psbuf,
04794 ts);
04795 }
04796
04797
04798
04799
04800
04801 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
04802 const char *pdata,
04803 int total_data,
04804 files_struct *fsp,
04805 const char *fname,
04806 SMB_STRUCT_STAT *psbuf)
04807 {
04808
04809 struct timespec write_time;
04810 struct timespec changed_time;
04811 uint32 dosmode = 0;
04812 struct timespec ts[2];
04813 NTSTATUS status = NT_STATUS_OK;
04814
04815 if (total_data < 36) {
04816 return NT_STATUS_INVALID_PARAMETER;
04817 }
04818
04819
04820 dosmode = IVAL(pdata,32);
04821 status = smb_set_file_dosmode(conn,
04822 fname,
04823 psbuf,
04824 dosmode);
04825 if (!NT_STATUS_IS_OK(status)) {
04826 return status;
04827 }
04828
04829
04830
04831
04832 ts[0] = interpret_long_date(pdata+8);
04833
04834 write_time = interpret_long_date(pdata+16);
04835 changed_time = interpret_long_date(pdata+24);
04836
04837
04838 ts[1] = timespec_min(&write_time, &changed_time);
04839
04840 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
04841 ts[1] = write_time;
04842 }
04843
04844
04845 if (null_timespec(ts[1])) {
04846 ts[1] = null_timespec(write_time) ? changed_time : write_time;
04847 }
04848
04849 DEBUG(10,("smb_set_file_basic_info: file %s\n",
04850 fname ? fname : fsp->fsp_name ));
04851
04852 return smb_set_file_time(conn,
04853 fsp,
04854 fname,
04855 psbuf,
04856 ts);
04857 }
04858
04859
04860
04861
04862
04863 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
04864 const char *pdata,
04865 int total_data,
04866 files_struct *fsp,
04867 const char *fname,
04868 SMB_STRUCT_STAT *psbuf)
04869 {
04870 SMB_BIG_UINT allocation_size = 0;
04871 NTSTATUS status = NT_STATUS_OK;
04872 files_struct *new_fsp = NULL;
04873
04874 if (!VALID_STAT(*psbuf)) {
04875 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04876 }
04877
04878 if (total_data < 8) {
04879 return NT_STATUS_INVALID_PARAMETER;
04880 }
04881
04882 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
04883 #ifdef LARGE_SMB_OFF_T
04884 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
04885 #else
04886 if (IVAL(pdata,4) != 0) {
04887
04888 return NT_STATUS_INVALID_PARAMETER;
04889 }
04890 #endif
04891
04892 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
04893 fname, (double)allocation_size ));
04894
04895 if (allocation_size) {
04896 allocation_size = smb_roundup(conn, allocation_size);
04897 }
04898
04899 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
04900 fname, (double)allocation_size ));
04901
04902 if (fsp && fsp->fh->fd != -1) {
04903
04904
04905 if (allocation_size != get_file_size(*psbuf)) {
04906 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
04907 return map_nt_error_from_unix(errno);
04908 }
04909 }
04910
04911 if (null_timespec(fsp->pending_modtime)) {
04912
04913
04914
04915
04916 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
04917 }
04918 return NT_STATUS_OK;
04919 }
04920
04921
04922
04923 status = open_file_ntcreate(conn, fname, psbuf,
04924 FILE_WRITE_DATA,
04925 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
04926 FILE_OPEN,
04927 0,
04928 FILE_ATTRIBUTE_NORMAL,
04929 FORCE_OPLOCK_BREAK_TO_NONE,
04930 NULL, &new_fsp);
04931
04932 if (!NT_STATUS_IS_OK(status)) {
04933
04934 return status;
04935 }
04936
04937
04938 if (allocation_size != get_file_size(*psbuf)) {
04939 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
04940 status = map_nt_error_from_unix(errno);
04941 close_file(new_fsp,NORMAL_CLOSE);
04942 return status;
04943 }
04944 }
04945
04946
04947
04948
04949
04950 fsp_set_pending_modtime(new_fsp, timespec_current());
04951
04952 close_file(new_fsp,NORMAL_CLOSE);
04953 return NT_STATUS_OK;
04954 }
04955
04956
04957
04958
04959
04960 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
04961 const char *pdata,
04962 int total_data,
04963 files_struct *fsp,
04964 const char *fname,
04965 SMB_STRUCT_STAT *psbuf)
04966 {
04967 SMB_OFF_T size;
04968
04969 if (total_data < 8) {
04970 return NT_STATUS_INVALID_PARAMETER;
04971 }
04972
04973 size = IVAL(pdata,0);
04974 #ifdef LARGE_SMB_OFF_T
04975 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
04976 #else
04977 if (IVAL(pdata,4) != 0) {
04978
04979 return NT_STATUS_INVALID_PARAMETER;
04980 }
04981 #endif
04982 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
04983 "file %s to %.0f\n", fname, (double)size ));
04984
04985 return smb_set_file_size(conn,
04986 fsp,
04987 fname,
04988 psbuf,
04989 size);
04990 }
04991
04992
04993
04994
04995
04996 static NTSTATUS smb_unix_mknod(connection_struct *conn,
04997 const char *pdata,
04998 int total_data,
04999 const char *fname,
05000 SMB_STRUCT_STAT *psbuf)
05001 {
05002 uint32 file_type = IVAL(pdata,56);
05003 #if defined(HAVE_MAKEDEV)
05004 uint32 dev_major = IVAL(pdata,60);
05005 uint32 dev_minor = IVAL(pdata,68);
05006 #endif
05007 SMB_DEV_T dev = (SMB_DEV_T)0;
05008 uint32 raw_unixmode = IVAL(pdata,84);
05009 NTSTATUS status;
05010 mode_t unixmode;
05011
05012 if (total_data < 100) {
05013 return NT_STATUS_INVALID_PARAMETER;
05014 }
05015
05016 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
05017 if (!NT_STATUS_IS_OK(status)) {
05018 return status;
05019 }
05020
05021 #if defined(HAVE_MAKEDEV)
05022 dev = makedev(dev_major, dev_minor);
05023 #endif
05024
05025 switch (file_type) {
05026 #if defined(S_IFIFO)
05027 case UNIX_TYPE_FIFO:
05028 unixmode |= S_IFIFO;
05029 break;
05030 #endif
05031 #if defined(S_IFSOCK)
05032 case UNIX_TYPE_SOCKET:
05033 unixmode |= S_IFSOCK;
05034 break;
05035 #endif
05036 #if defined(S_IFCHR)
05037 case UNIX_TYPE_CHARDEV:
05038 unixmode |= S_IFCHR;
05039 break;
05040 #endif
05041 #if defined(S_IFBLK)
05042 case UNIX_TYPE_BLKDEV:
05043 unixmode |= S_IFBLK;
05044 break;
05045 #endif
05046 default:
05047 return NT_STATUS_INVALID_PARAMETER;
05048 }
05049
05050 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
05051 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
05052
05053
05054 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
05055 return map_nt_error_from_unix(errno);
05056 }
05057
05058
05059
05060
05061
05062 if (lp_inherit_perms(SNUM(conn))) {
05063 inherit_access_acl(
05064 conn, parent_dirname(fname),
05065 fname, unixmode);
05066 }
05067
05068 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
05069 status = map_nt_error_from_unix(errno);
05070 SMB_VFS_UNLINK(conn,fname);
05071 return status;
05072 }
05073 return NT_STATUS_OK;
05074 }
05075
05076
05077
05078
05079
05080 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
05081 const char *pdata,
05082 int total_data,
05083 files_struct *fsp,
05084 const char *fname,
05085 SMB_STRUCT_STAT *psbuf)
05086 {
05087 struct timespec ts[2];
05088 uint32 raw_unixmode;
05089 mode_t unixmode;
05090 SMB_OFF_T size = 0;
05091 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
05092 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
05093 NTSTATUS status = NT_STATUS_OK;
05094 BOOL delete_on_fail = False;
05095 enum perm_type ptype;
05096
05097 if (total_data < 100) {
05098 return NT_STATUS_INVALID_PARAMETER;
05099 }
05100
05101 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
05102 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
05103 size=IVAL(pdata,0);
05104 #ifdef LARGE_SMB_OFF_T
05105 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
05106 #else
05107 if (IVAL(pdata,4) != 0) {
05108
05109 return NT_STATUS_INVALID_PARAMETER;
05110 }
05111 #endif
05112 }
05113
05114 ts[0] = interpret_long_date(pdata+24);
05115 ts[1] = interpret_long_date(pdata+32);
05116 set_owner = (uid_t)IVAL(pdata,40);
05117 set_grp = (gid_t)IVAL(pdata,48);
05118 raw_unixmode = IVAL(pdata,84);
05119
05120 if (VALID_STAT(*psbuf)) {
05121 if (S_ISDIR(psbuf->st_mode)) {
05122 ptype = PERM_EXISTING_DIR;
05123 } else {
05124 ptype = PERM_EXISTING_FILE;
05125 }
05126 } else {
05127 ptype = PERM_NEW_FILE;
05128 }
05129
05130 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
05131 if (!NT_STATUS_IS_OK(status)) {
05132 return status;
05133 }
05134
05135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
05136 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
05137 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
05138
05139 if (!VALID_STAT(*psbuf)) {
05140
05141
05142
05143
05144
05145
05146 status = smb_unix_mknod(conn,
05147 pdata,
05148 total_data,
05149 fname,
05150 psbuf);
05151 if (!NT_STATUS_IS_OK(status)) {
05152 return status;
05153 }
05154
05155
05156 raw_unixmode = SMB_MODE_NO_CHANGE;
05157 size = get_file_size(*psbuf);
05158 ts[0] = get_atimespec(psbuf);
05159 ts[1] = get_mtimespec(psbuf);
05160
05161
05162
05163
05164 delete_on_fail = True;
05165 }
05166
05167 #if 1
05168
05169
05170
05171
05172 if (!size) {
05173 size = get_file_size(*psbuf);
05174 }
05175 #endif
05176
05177
05178
05179
05180
05181 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
05182 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
05183 (unsigned int)unixmode, fname ));
05184 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
05185 return map_nt_error_from_unix(errno);
05186 }
05187 }
05188
05189
05190
05191
05192
05193 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
05194 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
05195 (unsigned int)set_owner, fname ));
05196 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
05197 status = map_nt_error_from_unix(errno);
05198 if (delete_on_fail) {
05199 SMB_VFS_UNLINK(conn,fname);
05200 }
05201 return status;
05202 }
05203 }
05204
05205
05206
05207
05208
05209 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
05210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
05211 (unsigned int)set_owner, fname ));
05212 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
05213 status = map_nt_error_from_unix(errno);
05214 if (delete_on_fail) {
05215 SMB_VFS_UNLINK(conn,fname);
05216 }
05217 return status;
05218 }
05219 }
05220
05221
05222
05223 status = smb_set_file_size(conn,
05224 fsp,
05225 fname,
05226 psbuf,
05227 size);
05228 if (!NT_STATUS_IS_OK(status)) {
05229 return status;
05230 }
05231
05232
05233
05234 return smb_set_file_time(conn,
05235 fsp,
05236 fname,
05237 psbuf,
05238 ts);
05239 }
05240
05241
05242
05243
05244
05245 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
05246 const char *pdata,
05247 int total_data,
05248 files_struct *fsp,
05249 const char *fname,
05250 SMB_STRUCT_STAT *psbuf)
05251 {
05252 NTSTATUS status;
05253 uint32 smb_fflags;
05254 uint32 smb_fmask;
05255
05256 if (total_data < 116) {
05257 return NT_STATUS_INVALID_PARAMETER;
05258 }
05259
05260
05261
05262
05263 status = smb_set_file_unix_basic(conn, pdata, total_data,
05264 fsp, fname, psbuf);
05265 if (!NT_STATUS_IS_OK(status)) {
05266 return status;
05267 }
05268
05269 smb_fflags = IVAL(pdata, 108);
05270 smb_fmask = IVAL(pdata, 112);
05271
05272
05273
05274
05275 if (smb_fmask != 0) {
05276 int stat_fflags = 0;
05277
05278 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
05279 &stat_fflags)) {
05280
05281 return NT_STATUS_INVALID_PARAMETER;
05282 }
05283
05284 if (fsp && fsp->fh->fd != -1) {
05285
05286 return NT_STATUS_NOT_SUPPORTED;
05287 } else {
05288 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
05289 return map_nt_error_from_unix(errno);
05290 }
05291 }
05292 }
05293
05294
05295
05296
05297
05298
05299 return NT_STATUS_OK;
05300 }
05301
05302
05303
05304
05305
05306 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
05307 char **ppdata,
05308 int total_data,
05309 const char *fname,
05310 SMB_STRUCT_STAT *psbuf,
05311 int *pdata_return_size)
05312 {
05313 NTSTATUS status = NT_STATUS_OK;
05314 uint32 raw_unixmode = 0;
05315 uint32 mod_unixmode = 0;
05316 mode_t unixmode = (mode_t)0;
05317 files_struct *fsp = NULL;
05318 uint16 info_level_return = 0;
05319 int info;
05320 char *pdata = *ppdata;
05321
05322 if (total_data < 18) {
05323 return NT_STATUS_INVALID_PARAMETER;
05324 }
05325
05326 raw_unixmode = IVAL(pdata,8);
05327
05328
05329 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
05330 if (!NT_STATUS_IS_OK(status)) {
05331 return status;
05332 }
05333
05334 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
05335
05336 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
05337 fname, (unsigned int)unixmode ));
05338
05339 status = open_directory(conn,
05340 fname,
05341 psbuf,
05342 FILE_READ_ATTRIBUTES,
05343 FILE_SHARE_NONE,
05344 FILE_CREATE,
05345 0,
05346 mod_unixmode,
05347 &info,
05348 &fsp);
05349
05350 if (NT_STATUS_IS_OK(status)) {
05351 close_file(fsp, NORMAL_CLOSE);
05352 }
05353
05354 info_level_return = SVAL(pdata,16);
05355
05356 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
05357 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
05358 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
05359 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
05360 } else {
05361 *pdata_return_size = 12;
05362 }
05363
05364
05365 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
05366 if (*ppdata == NULL) {
05367 *pdata_return_size = 0;
05368 return NT_STATUS_NO_MEMORY;
05369 }
05370 pdata = *ppdata;
05371
05372 SSVAL(pdata,0,NO_OPLOCK_RETURN);
05373 SSVAL(pdata,2,0);
05374 SIVAL(pdata,4,info);
05375
05376 switch (info_level_return) {
05377 case SMB_QUERY_FILE_UNIX_BASIC:
05378 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
05379 SSVAL(pdata,10,0);
05380 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
05381 break;
05382 case SMB_QUERY_FILE_UNIX_INFO2:
05383 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
05384 SSVAL(pdata,10,0);
05385 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
05386 break;
05387 default:
05388 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
05389 SSVAL(pdata,10,0);
05390 break;
05391 }
05392
05393 return status;
05394 }
05395
05396
05397
05398
05399
05400 static NTSTATUS smb_posix_open(connection_struct *conn,
05401 char **ppdata,
05402 int total_data,
05403 const char *fname,
05404 SMB_STRUCT_STAT *psbuf,
05405 int *pdata_return_size)
05406 {
05407 BOOL extended_oplock_granted = False;
05408 char *pdata = *ppdata;
05409 uint32 flags = 0;
05410 uint32 wire_open_mode = 0;
05411 uint32 raw_unixmode = 0;
05412 uint32 mod_unixmode = 0;
05413 uint32 create_disp = 0;
05414 uint32 access_mask = 0;
05415 uint32 create_options = 0;
05416 NTSTATUS status = NT_STATUS_OK;
05417 mode_t unixmode = (mode_t)0;
05418 files_struct *fsp = NULL;
05419 int oplock_request = 0;
05420 int info = 0;
05421 uint16 info_level_return = 0;
05422
05423 if (total_data < 18) {
05424 return NT_STATUS_INVALID_PARAMETER;
05425 }
05426
05427 flags = IVAL(pdata,0);
05428 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
05429 if (oplock_request) {
05430 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
05431 }
05432
05433 wire_open_mode = IVAL(pdata,4);
05434
05435 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
05436 return smb_posix_mkdir(conn,
05437 ppdata,
05438 total_data,
05439 fname,
05440 psbuf,
05441 pdata_return_size);
05442 }
05443
05444 switch (wire_open_mode & SMB_ACCMODE) {
05445 case SMB_O_RDONLY:
05446 access_mask = FILE_READ_DATA;
05447 break;
05448 case SMB_O_WRONLY:
05449 access_mask = FILE_WRITE_DATA;
05450 break;
05451 case SMB_O_RDWR:
05452 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
05453 break;
05454 default:
05455 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
05456 (unsigned int)wire_open_mode ));
05457 return NT_STATUS_INVALID_PARAMETER;
05458 }
05459
05460 wire_open_mode &= ~SMB_ACCMODE;
05461
05462 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
05463 create_disp = FILE_CREATE;
05464 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
05465 create_disp = FILE_OVERWRITE_IF;
05466 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
05467 create_disp = FILE_OPEN_IF;
05468 } else {
05469 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
05470 (unsigned int)wire_open_mode ));
05471 return NT_STATUS_INVALID_PARAMETER;
05472 }
05473
05474 raw_unixmode = IVAL(pdata,8);
05475
05476
05477 status = unix_perms_from_wire(conn,
05478 psbuf,
05479 raw_unixmode,
05480 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
05481 &unixmode);
05482
05483 if (!NT_STATUS_IS_OK(status)) {
05484 return status;
05485 }
05486
05487 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
05488
05489 if (wire_open_mode & SMB_O_SYNC) {
05490 create_options |= FILE_WRITE_THROUGH;
05491 }
05492 if (wire_open_mode & SMB_O_APPEND) {
05493 access_mask |= FILE_APPEND_DATA;
05494 }
05495 if (wire_open_mode & SMB_O_DIRECT) {
05496 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
05497 }
05498
05499 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
05500 fname,
05501 (unsigned int)wire_open_mode,
05502 (unsigned int)unixmode ));
05503
05504 status = open_file_ntcreate(conn,
05505 fname,
05506 psbuf,
05507 access_mask,
05508 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
05509 create_disp,
05510 0,
05511 mod_unixmode,
05512 oplock_request,
05513 &info,
05514 &fsp);
05515
05516 if (!NT_STATUS_IS_OK(status)) {
05517 return status;
05518 }
05519
05520 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
05521 extended_oplock_granted = True;
05522 }
05523
05524 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
05525 extended_oplock_granted = True;
05526 }
05527
05528 info_level_return = SVAL(pdata,16);
05529
05530
05531
05532 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
05533 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
05534 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
05535 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
05536 } else {
05537 *pdata_return_size = 12;
05538 }
05539
05540
05541 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
05542 if (*ppdata == NULL) {
05543 close_file(fsp,ERROR_CLOSE);
05544 *pdata_return_size = 0;
05545 return NT_STATUS_NO_MEMORY;
05546 }
05547 pdata = *ppdata;
05548
05549 if (extended_oplock_granted) {
05550 if (flags & REQUEST_BATCH_OPLOCK) {
05551 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
05552 } else {
05553 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
05554 }
05555 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
05556 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
05557 } else {
05558 SSVAL(pdata,0,NO_OPLOCK_RETURN);
05559 }
05560
05561 SSVAL(pdata,2,fsp->fnum);
05562 SIVAL(pdata,4,info);
05563
05564 switch (info_level_return) {
05565 case SMB_QUERY_FILE_UNIX_BASIC:
05566 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
05567 SSVAL(pdata,10,0);
05568 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
05569 break;
05570 case SMB_QUERY_FILE_UNIX_INFO2:
05571 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
05572 SSVAL(pdata,10,0);
05573 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
05574 break;
05575 default:
05576 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
05577 SSVAL(pdata,10,0);
05578 break;
05579 }
05580 return NT_STATUS_OK;
05581 }
05582
05583
05584
05585
05586
05587 static NTSTATUS smb_posix_unlink(connection_struct *conn,
05588 const char *pdata,
05589 int total_data,
05590 const char *fname,
05591 SMB_STRUCT_STAT *psbuf)
05592 {
05593 NTSTATUS status = NT_STATUS_OK;
05594 files_struct *fsp = NULL;
05595 uint16 flags = 0;
05596 char del = 1;
05597 int info = 0;
05598 int i;
05599 struct share_mode_lock *lck = NULL;
05600
05601 if (total_data < 2) {
05602 return NT_STATUS_INVALID_PARAMETER;
05603 }
05604
05605 flags = SVAL(pdata,0);
05606
05607 if (!VALID_STAT(*psbuf)) {
05608 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
05609 }
05610
05611 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
05612 !VALID_STAT_OF_DIR(*psbuf)) {
05613 return NT_STATUS_NOT_A_DIRECTORY;
05614 }
05615
05616 DEBUG(10,("smb_posix_unlink: %s %s\n",
05617 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
05618 fname));
05619
05620 if (VALID_STAT_OF_DIR(*psbuf)) {
05621 status = open_directory(conn,
05622 fname,
05623 psbuf,
05624 DELETE_ACCESS,
05625 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
05626 FILE_OPEN,
05627 0,
05628 FILE_FLAG_POSIX_SEMANTICS|0777,
05629 &info,
05630 &fsp);
05631 } else {
05632
05633 status = open_file_ntcreate(conn,
05634 fname,
05635 psbuf,
05636 DELETE_ACCESS,
05637 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
05638 FILE_OPEN,
05639 0,
05640 FILE_FLAG_POSIX_SEMANTICS|0777,
05641 0,
05642 &info,
05643 &fsp);
05644 }
05645
05646 if (!NT_STATUS_IS_OK(status)) {
05647 return status;
05648 }
05649
05650
05651
05652
05653
05654
05655 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
05656 if (lck == NULL) {
05657 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
05658 "lock for file %s\n", fsp->fsp_name));
05659 close_file(fsp, NORMAL_CLOSE);
05660 return NT_STATUS_INVALID_PARAMETER;
05661 }
05662
05663
05664
05665
05666
05667
05668 for (i=0; i<lck->num_share_modes; i++) {
05669 struct share_mode_entry *e = &lck->share_modes[i];
05670 if (is_valid_share_mode_entry(e)) {
05671 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
05672 continue;
05673 }
05674
05675 close_file(fsp, NORMAL_CLOSE);
05676 TALLOC_FREE(lck);
05677 return NT_STATUS_SHARING_VIOLATION;
05678 }
05679 }
05680
05681
05682
05683
05684 status = smb_set_file_disposition_info(conn,
05685 &del,
05686 1,
05687 fsp,
05688 fname,
05689 psbuf);
05690
05691 if (!NT_STATUS_IS_OK(status)) {
05692 close_file(fsp, NORMAL_CLOSE);
05693 TALLOC_FREE(lck);
05694 return status;
05695 }
05696 TALLOC_FREE(lck);
05697 return close_file(fsp, NORMAL_CLOSE);
05698 }
05699
05700
05701
05702
05703
05704 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
05705 unsigned int tran_call,
05706 char **pparams, int total_params, char **ppdata, int total_data,
05707 unsigned int max_data_bytes)
05708 {
05709 char *params = *pparams;
05710 char *pdata = *ppdata;
05711 uint16 info_level;
05712 SMB_STRUCT_STAT sbuf;
05713 pstring fname;
05714 files_struct *fsp = NULL;
05715 NTSTATUS status = NT_STATUS_OK;
05716 int data_return_size = 0;
05717
05718 if (!params) {
05719 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
05720 }
05721
05722 ZERO_STRUCT(sbuf);
05723
05724 if (tran_call == TRANSACT2_SETFILEINFO) {
05725 if (total_params < 4) {
05726 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
05727 }
05728
05729 fsp = file_fsp(params,0);
05730 info_level = SVAL(params,2);
05731
05732 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
05733
05734
05735
05736
05737
05738 pstrcpy(fname, fsp->fsp_name);
05739 if (INFO_LEVEL_IS_UNIX(info_level)) {
05740
05741 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
05742 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
05743 return UNIXERROR(ERRDOS,ERRbadpath);
05744 }
05745 } else {
05746 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
05747 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
05748 return UNIXERROR(ERRDOS,ERRbadpath);
05749 }
05750 }
05751 } else if (fsp && fsp->print_file) {
05752
05753
05754
05755 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
05756 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
05757
05758 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
05759
05760 SSVAL(params,0,0);
05761 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
05762 return(-1);
05763 } else
05764 return (UNIXERROR(ERRDOS,ERRbadpath));
05765 } else {
05766
05767
05768
05769 CHECK_FSP(fsp,conn);
05770
05771 pstrcpy(fname, fsp->fsp_name);
05772
05773 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
05774 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
05775 return(UNIXERROR(ERRDOS,ERRbadfid));
05776 }
05777 }
05778 } else {
05779
05780 if (total_params < 7) {
05781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
05782 }
05783
05784 info_level = SVAL(params,0);
05785 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
05786 if (!NT_STATUS_IS_OK(status)) {
05787 return ERROR_NT(status);
05788 }
05789
05790 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
05791 if (!NT_STATUS_IS_OK(status)) {
05792 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
05793 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
05794 }
05795 return ERROR_NT(status);
05796 }
05797
05798 status = unix_convert(conn, fname, False, NULL, &sbuf);
05799 if (!NT_STATUS_IS_OK(status)) {
05800 return ERROR_NT(status);
05801 }
05802
05803 status = check_name(conn, fname);
05804 if (!NT_STATUS_IS_OK(status)) {
05805 return ERROR_NT(status);
05806 }
05807
05808 if (INFO_LEVEL_IS_UNIX(info_level)) {
05809
05810
05811
05812
05813
05814 SMB_VFS_LSTAT(conn,fname,&sbuf);
05815
05816 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
05817 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
05818 return UNIXERROR(ERRDOS,ERRbadpath);
05819 }
05820 }
05821
05822 if (!CAN_WRITE(conn)) {
05823 return ERROR_DOS(ERRSRV,ERRaccess);
05824 }
05825
05826 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
05827 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
05828 }
05829
05830 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
05831 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
05832
05833
05834 *pparams = (char *)SMB_REALLOC(*pparams,2);
05835 if (*pparams == NULL) {
05836 return ERROR_NT(NT_STATUS_NO_MEMORY);
05837 }
05838 params = *pparams;
05839
05840 SSVAL(params,0,0);
05841
05842 if (fsp && !null_timespec(fsp->pending_modtime)) {
05843
05844 set_mtimespec(&sbuf, fsp->pending_modtime);
05845 }
05846
05847 switch (info_level) {
05848
05849 case SMB_INFO_STANDARD:
05850 {
05851 status = smb_set_info_standard(conn,
05852 pdata,
05853 total_data,
05854 fsp,
05855 fname,
05856 &sbuf);
05857 break;
05858 }
05859
05860 case SMB_INFO_SET_EA:
05861 {
05862 status = smb_info_set_ea(conn,
05863 pdata,
05864 total_data,
05865 fsp,
05866 fname);
05867 break;
05868 }
05869
05870 case SMB_SET_FILE_BASIC_INFO:
05871 case SMB_FILE_BASIC_INFORMATION:
05872 {
05873 status = smb_set_file_basic_info(conn,
05874 pdata,
05875 total_data,
05876 fsp,
05877 fname,
05878 &sbuf);
05879 break;
05880 }
05881
05882 case SMB_FILE_ALLOCATION_INFORMATION:
05883 case SMB_SET_FILE_ALLOCATION_INFO:
05884 {
05885 status = smb_set_file_allocation_info(conn,
05886 pdata,
05887 total_data,
05888 fsp,
05889 fname,
05890 &sbuf);
05891 break;
05892 }
05893
05894 case SMB_FILE_END_OF_FILE_INFORMATION:
05895 case SMB_SET_FILE_END_OF_FILE_INFO:
05896 {
05897 status = smb_set_file_end_of_file_info(conn,
05898 pdata,
05899 total_data,
05900 fsp,
05901 fname,
05902 &sbuf);
05903 break;
05904 }
05905
05906 case SMB_FILE_DISPOSITION_INFORMATION:
05907 case SMB_SET_FILE_DISPOSITION_INFO:
05908 {
05909 #if 0
05910
05911
05912
05913
05914 if (tran_call != TRANSACT2_SETFILEINFO) {
05915 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
05916 }
05917 #endif
05918 status = smb_set_file_disposition_info(conn,
05919 pdata,
05920 total_data,
05921 fsp,
05922 fname,
05923 &sbuf);
05924 break;
05925 }
05926
05927 case SMB_FILE_POSITION_INFORMATION:
05928 {
05929 status = smb_file_position_information(conn,
05930 pdata,
05931 total_data,
05932 fsp);
05933 break;
05934 }
05935
05936
05937
05938
05939
05940
05941
05942 case SMB_FILE_MODE_INFORMATION:
05943 {
05944 status = smb_file_mode_information(conn,
05945 pdata,
05946 total_data);
05947 break;
05948 }
05949
05950
05951
05952
05953
05954 case SMB_SET_FILE_UNIX_BASIC:
05955 {
05956 status = smb_set_file_unix_basic(conn,
05957 pdata,
05958 total_data,
05959 fsp,
05960 fname,
05961 &sbuf);
05962 break;
05963 }
05964
05965 case SMB_SET_FILE_UNIX_INFO2:
05966 {
05967 status = smb_set_file_unix_info2(conn,
05968 pdata,
05969 total_data,
05970 fsp,
05971 fname,
05972 &sbuf);
05973 break;
05974 }
05975
05976 case SMB_SET_FILE_UNIX_LINK:
05977 {
05978 if (tran_call != TRANSACT2_SETPATHINFO) {
05979
05980 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
05981 }
05982 status = smb_set_file_unix_link(conn,
05983 inbuf,
05984 pdata,
05985 total_data,
05986 fname);
05987 break;
05988 }
05989
05990 case SMB_SET_FILE_UNIX_HLINK:
05991 {
05992 if (tran_call != TRANSACT2_SETPATHINFO) {
05993
05994 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
05995 }
05996 status = smb_set_file_unix_hlink(conn,
05997 inbuf,
05998 outbuf,
05999 pdata,
06000 total_data,
06001 fname);
06002 break;
06003 }
06004
06005 case SMB_FILE_RENAME_INFORMATION:
06006 {
06007 status = smb_file_rename_information(conn,
06008 inbuf,
06009 outbuf,
06010 pdata,
06011 total_data,
06012 fsp,
06013 fname);
06014 break;
06015 }
06016
06017 #if defined(HAVE_POSIX_ACLS)
06018 case SMB_SET_POSIX_ACL:
06019 {
06020 status = smb_set_posix_acl(conn,
06021 pdata,
06022 total_data,
06023 fsp,
06024 fname,
06025 &sbuf);
06026 break;
06027 }
06028 #endif
06029
06030 case SMB_SET_POSIX_LOCK:
06031 {
06032 if (tran_call != TRANSACT2_SETFILEINFO) {
06033 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
06034 }
06035 status = smb_set_posix_lock(conn,
06036 inbuf,
06037 length,
06038 pdata,
06039 total_data,
06040 fsp);
06041 break;
06042 }
06043
06044 case SMB_POSIX_PATH_OPEN:
06045 {
06046 if (tran_call != TRANSACT2_SETPATHINFO) {
06047
06048 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
06049 }
06050
06051 status = smb_posix_open(conn,
06052 ppdata,
06053 total_data,
06054 fname,
06055 &sbuf,
06056 &data_return_size);
06057 break;
06058 }
06059
06060 case SMB_POSIX_PATH_UNLINK:
06061 {
06062 if (tran_call != TRANSACT2_SETPATHINFO) {
06063
06064 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
06065 }
06066
06067 status = smb_posix_unlink(conn,
06068 pdata,
06069 total_data,
06070 fname,
06071 &sbuf);
06072 break;
06073 }
06074
06075 default:
06076 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
06077 }
06078
06079
06080 if (!NT_STATUS_IS_OK(status)) {
06081 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
06082
06083 return -1;
06084 }
06085 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
06086
06087 return -1;
06088 }
06089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
06090 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
06091 }
06092 if (info_level == SMB_POSIX_PATH_OPEN) {
06093 return ERROR_OPEN(status);
06094 }
06095 return ERROR_NT(status);
06096 }
06097
06098 SSVAL(params,0,0);
06099 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
06100
06101 return -1;
06102 }
06103
06104
06105
06106
06107
06108 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
06109 char **pparams, int total_params, char **ppdata, int total_data,
06110 unsigned int max_data_bytes)
06111 {
06112 char *params = *pparams;
06113 char *pdata = *ppdata;
06114 pstring directory;
06115 SMB_STRUCT_STAT sbuf;
06116 NTSTATUS status = NT_STATUS_OK;
06117 struct ea_list *ea_list = NULL;
06118
06119 if (!CAN_WRITE(conn))
06120 return ERROR_DOS(ERRSRV,ERRaccess);
06121
06122 if (total_params < 5) {
06123 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06124 }
06125
06126 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
06127 if (!NT_STATUS_IS_OK(status)) {
06128 return ERROR_NT(status);
06129 }
06130
06131 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
06132
06133 status = unix_convert(conn, directory, False, NULL, &sbuf);
06134 if (!NT_STATUS_IS_OK(status)) {
06135 return ERROR_NT(status);
06136 }
06137
06138 status = check_name(conn, directory);
06139 if (!NT_STATUS_IS_OK(status)) {
06140 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
06141 return ERROR_NT(status);
06142 }
06143
06144
06145 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
06146 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
06147 }
06148
06149
06150
06151
06152
06153
06154
06155 if (total_data != 4) {
06156 if (total_data < 10) {
06157 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06158 }
06159
06160 if (IVAL(pdata,0) > total_data) {
06161 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
06162 IVAL(pdata,0), (unsigned int)total_data));
06163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06164 }
06165
06166 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
06167 total_data - 4);
06168 if (!ea_list) {
06169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06170 }
06171 } else if (IVAL(pdata,0) != 4) {
06172 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06173 }
06174
06175 status = create_directory(conn, directory);
06176
06177 if (!NT_STATUS_IS_OK(status)) {
06178 return ERROR_NT(status);
06179 }
06180
06181
06182 if (ea_list) {
06183 status = set_ea(conn, NULL, directory, ea_list);
06184 if (!NT_STATUS_IS_OK(status)) {
06185 return ERROR_NT(status);
06186 }
06187 }
06188
06189
06190 *pparams = (char *)SMB_REALLOC(*pparams,2);
06191 if(*pparams == NULL) {
06192 return ERROR_NT(NT_STATUS_NO_MEMORY);
06193 }
06194 params = *pparams;
06195
06196 SSVAL(params,0,0);
06197
06198 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
06199
06200 return(-1);
06201 }
06202
06203
06204
06205
06206
06207
06208 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
06209 char **pparams, int total_params, char **ppdata, int total_data,
06210 unsigned int max_data_bytes)
06211 {
06212 static uint16 fnf_handle = 257;
06213 char *params = *pparams;
06214 uint16 info_level;
06215
06216 if (total_params < 6) {
06217 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06218 }
06219
06220 info_level = SVAL(params,4);
06221 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
06222
06223 switch (info_level) {
06224 case 1:
06225 case 2:
06226 break;
06227 default:
06228 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
06229 }
06230
06231
06232 *pparams = (char *)SMB_REALLOC(*pparams,6);
06233 if (*pparams == NULL) {
06234 return ERROR_NT(NT_STATUS_NO_MEMORY);
06235 }
06236 params = *pparams;
06237
06238 SSVAL(params,0,fnf_handle);
06239 SSVAL(params,2,0);
06240 SSVAL(params,4,0);
06241
06242 fnf_handle++;
06243
06244 if(fnf_handle == 0)
06245 fnf_handle = 257;
06246
06247 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
06248
06249 return(-1);
06250 }
06251
06252
06253
06254
06255
06256
06257 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
06258 char **pparams, int total_params, char **ppdata, int total_data,
06259 unsigned int max_data_bytes)
06260 {
06261 char *params = *pparams;
06262
06263 DEBUG(3,("call_trans2findnotifynext\n"));
06264
06265
06266 *pparams = (char *)SMB_REALLOC(*pparams,4);
06267 if (*pparams == NULL) {
06268 return ERROR_NT(NT_STATUS_NO_MEMORY);
06269 }
06270 params = *pparams;
06271
06272 SSVAL(params,0,0);
06273 SSVAL(params,2,0);
06274
06275 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
06276
06277 return(-1);
06278 }
06279
06280
06281
06282
06283
06284 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
06285 char **pparams, int total_params, char **ppdata, int total_data,
06286 unsigned int max_data_bytes)
06287 {
06288 char *params = *pparams;
06289 pstring pathname;
06290 int reply_size = 0;
06291 int max_referral_level;
06292 NTSTATUS status = NT_STATUS_OK;
06293
06294 DEBUG(10,("call_trans2getdfsreferral\n"));
06295
06296 if (total_params < 3) {
06297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06298 }
06299
06300 max_referral_level = SVAL(params,0);
06301
06302 if(!lp_host_msdfs())
06303 return ERROR_DOS(ERRDOS,ERRbadfunc);
06304
06305 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
06306 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
06307 return ERROR_NT(status);
06308
06309 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
06310 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
06311
06312 return(-1);
06313 }
06314
06315 #define LMCAT_SPL 0x53
06316 #define LMFUNC_GETJOBID 0x60
06317
06318
06319
06320
06321
06322 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
06323 char **pparams, int total_params, char **ppdata, int total_data,
06324 unsigned int max_data_bytes)
06325 {
06326 char *pdata = *ppdata;
06327 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
06328
06329
06330
06331 if (!fsp)
06332 return(ERROR_DOS(ERRDOS,ERRbadfid));
06333
06334 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
06335 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
06336 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
06337 if (*ppdata == NULL) {
06338 return ERROR_NT(NT_STATUS_NO_MEMORY);
06339 }
06340 pdata = *ppdata;
06341
06342
06343
06344
06345 SSVAL(pdata,0,fsp->rap_print_jobid);
06346 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE);
06347 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE);
06348 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
06349 return(-1);
06350 } else {
06351 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
06352 return ERROR_DOS(ERRSRV,ERRerror);
06353 }
06354 }
06355
06356
06357
06358
06359
06360 int reply_findclose(connection_struct *conn,
06361 char *inbuf,char *outbuf,int length,int bufsize)
06362 {
06363 int outsize = 0;
06364 int dptr_num=SVALS(inbuf,smb_vwv0);
06365 START_PROFILE(SMBfindclose);
06366
06367 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
06368
06369 dptr_close(&dptr_num);
06370
06371 outsize = set_message(outbuf,0,0,False);
06372
06373 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
06374
06375 END_PROFILE(SMBfindclose);
06376 return(outsize);
06377 }
06378
06379
06380
06381
06382
06383 int reply_findnclose(connection_struct *conn,
06384 char *inbuf,char *outbuf,int length,int bufsize)
06385 {
06386 int outsize = 0;
06387 int dptr_num= -1;
06388 START_PROFILE(SMBfindnclose);
06389
06390 dptr_num = SVAL(inbuf,smb_vwv0);
06391
06392 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
06393
06394
06395
06396
06397
06398 outsize = set_message(outbuf,0,0,False);
06399
06400 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
06401
06402 END_PROFILE(SMBfindnclose);
06403 return(outsize);
06404 }
06405
06406 int handle_trans2(connection_struct *conn,
06407 struct trans_state *state,
06408 char *inbuf, char *outbuf, int size, int bufsize)
06409 {
06410 int outsize;
06411
06412 if (Protocol >= PROTOCOL_NT1) {
06413 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40);
06414 }
06415
06416
06417 switch(state->call) {
06418 case TRANSACT2_OPEN:
06419 {
06420 START_PROFILE(Trans2_open);
06421 outsize = call_trans2open(
06422 conn, inbuf, outbuf, bufsize,
06423 &state->param, state->total_param,
06424 &state->data, state->total_data,
06425 state->max_data_return);
06426 END_PROFILE(Trans2_open);
06427 break;
06428 }
06429
06430 case TRANSACT2_FINDFIRST:
06431 {
06432 START_PROFILE(Trans2_findfirst);
06433 outsize = call_trans2findfirst(
06434 conn, inbuf, outbuf, bufsize,
06435 &state->param, state->total_param,
06436 &state->data, state->total_data,
06437 state->max_data_return);
06438 END_PROFILE(Trans2_findfirst);
06439 break;
06440 }
06441
06442 case TRANSACT2_FINDNEXT:
06443 {
06444 START_PROFILE(Trans2_findnext);
06445 outsize = call_trans2findnext(
06446 conn, inbuf, outbuf, size, bufsize,
06447 &state->param, state->total_param,
06448 &state->data, state->total_data,
06449 state->max_data_return);
06450 END_PROFILE(Trans2_findnext);
06451 break;
06452 }
06453
06454 case TRANSACT2_QFSINFO:
06455 {
06456 START_PROFILE(Trans2_qfsinfo);
06457 outsize = call_trans2qfsinfo(
06458 conn, inbuf, outbuf, size, bufsize,
06459 &state->param, state->total_param,
06460 &state->data, state->total_data,
06461 state->max_data_return);
06462 END_PROFILE(Trans2_qfsinfo);
06463 break;
06464 }
06465
06466 case TRANSACT2_SETFSINFO:
06467 {
06468 START_PROFILE(Trans2_setfsinfo);
06469 outsize = call_trans2setfsinfo(
06470 conn, inbuf, outbuf, size, bufsize,
06471 &state->param, state->total_param,
06472 &state->data, state->total_data,
06473 state->max_data_return);
06474 END_PROFILE(Trans2_setfsinfo);
06475 break;
06476 }
06477
06478 case TRANSACT2_QPATHINFO:
06479 case TRANSACT2_QFILEINFO:
06480 {
06481 START_PROFILE(Trans2_qpathinfo);
06482 outsize = call_trans2qfilepathinfo(
06483 conn, inbuf, outbuf, size, bufsize, state->call,
06484 &state->param, state->total_param,
06485 &state->data, state->total_data,
06486 state->max_data_return);
06487 END_PROFILE(Trans2_qpathinfo);
06488 break;
06489 }
06490
06491 case TRANSACT2_SETPATHINFO:
06492 case TRANSACT2_SETFILEINFO:
06493 {
06494 START_PROFILE(Trans2_setpathinfo);
06495 outsize = call_trans2setfilepathinfo(
06496 conn, inbuf, outbuf, size, bufsize, state->call,
06497 &state->param, state->total_param,
06498 &state->data, state->total_data,
06499 state->max_data_return);
06500 END_PROFILE(Trans2_setpathinfo);
06501 break;
06502 }
06503
06504 case TRANSACT2_FINDNOTIFYFIRST:
06505 {
06506 START_PROFILE(Trans2_findnotifyfirst);
06507 outsize = call_trans2findnotifyfirst(
06508 conn, inbuf, outbuf, size, bufsize,
06509 &state->param, state->total_param,
06510 &state->data, state->total_data,
06511 state->max_data_return);
06512 END_PROFILE(Trans2_findnotifyfirst);
06513 break;
06514 }
06515
06516 case TRANSACT2_FINDNOTIFYNEXT:
06517 {
06518 START_PROFILE(Trans2_findnotifynext);
06519 outsize = call_trans2findnotifynext(
06520 conn, inbuf, outbuf, size, bufsize,
06521 &state->param, state->total_param,
06522 &state->data, state->total_data,
06523 state->max_data_return);
06524 END_PROFILE(Trans2_findnotifynext);
06525 break;
06526 }
06527
06528 case TRANSACT2_MKDIR:
06529 {
06530 START_PROFILE(Trans2_mkdir);
06531 outsize = call_trans2mkdir(
06532 conn, inbuf, outbuf, size, bufsize,
06533 &state->param, state->total_param,
06534 &state->data, state->total_data,
06535 state->max_data_return);
06536 END_PROFILE(Trans2_mkdir);
06537 break;
06538 }
06539
06540 case TRANSACT2_GET_DFS_REFERRAL:
06541 {
06542 START_PROFILE(Trans2_get_dfs_referral);
06543 outsize = call_trans2getdfsreferral(
06544 conn, inbuf, outbuf, size, bufsize,
06545 &state->param, state->total_param,
06546 &state->data, state->total_data,
06547 state->max_data_return);
06548 END_PROFILE(Trans2_get_dfs_referral);
06549 break;
06550 }
06551
06552 case TRANSACT2_IOCTL:
06553 {
06554 START_PROFILE(Trans2_ioctl);
06555 outsize = call_trans2ioctl(
06556 conn, inbuf, outbuf, size, bufsize,
06557 &state->param, state->total_param,
06558 &state->data, state->total_data,
06559 state->max_data_return);
06560 END_PROFILE(Trans2_ioctl);
06561 break;
06562 }
06563
06564 default:
06565
06566 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
06567 outsize = ERROR_DOS(ERRSRV,ERRerror);
06568 }
06569
06570 return outsize;
06571 }
06572
06573
06574
06575
06576
06577 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
06578 int size, int bufsize)
06579 {
06580 int outsize = 0;
06581 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
06582 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
06583 unsigned int psoff = SVAL(inbuf, smb_psoff);
06584 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
06585 unsigned int tran_call = SVAL(inbuf, smb_setup0);
06586 unsigned int av_size = size-4;
06587 struct trans_state *state;
06588 NTSTATUS result;
06589
06590 START_PROFILE(SMBtrans2);
06591
06592 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
06593 if (!NT_STATUS_IS_OK(result)) {
06594 DEBUG(2, ("Got invalid trans2 request: %s\n",
06595 nt_errstr(result)));
06596 END_PROFILE(SMBtrans2);
06597 return ERROR_NT(result);
06598 }
06599
06600 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
06601 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
06602 END_PROFILE(SMBtrans2);
06603 return ERROR_DOS(ERRSRV,ERRaccess);
06604 }
06605
06606 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
06607 DEBUG(0, ("talloc failed\n"));
06608 END_PROFILE(SMBtrans2);
06609 return ERROR_NT(NT_STATUS_NO_MEMORY);
06610 }
06611
06612 state->cmd = SMBtrans2;
06613
06614 state->mid = SVAL(inbuf, smb_mid);
06615 state->vuid = SVAL(inbuf, smb_uid);
06616 state->setup_count = SVAL(inbuf, smb_suwcnt);
06617 state->setup = NULL;
06618 state->total_param = SVAL(inbuf, smb_tpscnt);
06619 state->param = NULL;
06620 state->total_data = SVAL(inbuf, smb_tdscnt);
06621 state->data = NULL;
06622 state->max_param_return = SVAL(inbuf, smb_mprcnt);
06623 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
06624 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
06625 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
06626 state->one_way = BITSETW(inbuf+smb_vwv5,1);
06627
06628 state->call = tran_call;
06629
06630
06631
06632 if (state->setup_count != 1) {
06633
06634
06635
06636
06637
06638
06639
06640
06641 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
06642 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
06643 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
06644 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
06645 } else {
06646 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
06647 DEBUG(2,("Transaction is %d\n",tran_call));
06648 TALLOC_FREE(state);
06649 END_PROFILE(SMBtrans2);
06650 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06651 }
06652 }
06653
06654 if ((dscnt > state->total_data) || (pscnt > state->total_param))
06655 goto bad_param;
06656
06657 if (state->total_data) {
06658
06659
06660 state->data = (char *)SMB_MALLOC(state->total_data);
06661 if (state->data == NULL) {
06662 DEBUG(0,("reply_trans2: data malloc fail for %u "
06663 "bytes !\n", (unsigned int)state->total_data));
06664 TALLOC_FREE(state);
06665 END_PROFILE(SMBtrans2);
06666 return(ERROR_DOS(ERRDOS,ERRnomem));
06667 }
06668
06669 if (dscnt > state->total_data ||
06670 dsoff+dscnt < dsoff) {
06671 goto bad_param;
06672 }
06673
06674 if (dsoff > av_size ||
06675 dscnt > av_size ||
06676 dsoff+dscnt > av_size) {
06677 goto bad_param;
06678 }
06679
06680 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
06681 }
06682
06683 if (state->total_param) {
06684
06685
06686 state->param = (char *)SMB_MALLOC(state->total_param);
06687 if (state->param == NULL) {
06688 DEBUG(0,("reply_trans: param malloc fail for %u "
06689 "bytes !\n", (unsigned int)state->total_param));
06690 SAFE_FREE(state->data);
06691 TALLOC_FREE(state);
06692 END_PROFILE(SMBtrans2);
06693 return(ERROR_DOS(ERRDOS,ERRnomem));
06694 }
06695
06696 if (pscnt > state->total_param ||
06697 psoff+pscnt < psoff) {
06698 goto bad_param;
06699 }
06700
06701 if (psoff > av_size ||
06702 pscnt > av_size ||
06703 psoff+pscnt > av_size) {
06704 goto bad_param;
06705 }
06706
06707 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
06708 }
06709
06710 state->received_data = dscnt;
06711 state->received_param = pscnt;
06712
06713 if ((state->received_param == state->total_param) &&
06714 (state->received_data == state->total_data)) {
06715
06716 outsize = handle_trans2(conn, state, inbuf, outbuf,
06717 size, bufsize);
06718 SAFE_FREE(state->data);
06719 SAFE_FREE(state->param);
06720 TALLOC_FREE(state);
06721 END_PROFILE(SMBtrans2);
06722 return outsize;
06723 }
06724
06725 DLIST_ADD(conn->pending_trans, state);
06726
06727
06728
06729 outsize = set_message(outbuf,0,0,False);
06730 show_msg(outbuf);
06731 END_PROFILE(SMBtrans2);
06732 return outsize;
06733
06734 bad_param:
06735
06736 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
06737 SAFE_FREE(state->data);
06738 SAFE_FREE(state->param);
06739 TALLOC_FREE(state);
06740 END_PROFILE(SMBtrans2);
06741 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06742 }
06743
06744
06745
06746
06747
06748
06749 int reply_transs2(connection_struct *conn,
06750 char *inbuf,char *outbuf,int size,int bufsize)
06751 {
06752 int outsize = 0;
06753 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
06754 unsigned int av_size = size-4;
06755 struct trans_state *state;
06756
06757 START_PROFILE(SMBtranss2);
06758
06759 show_msg(inbuf);
06760
06761 for (state = conn->pending_trans; state != NULL;
06762 state = state->next) {
06763 if (state->mid == SVAL(inbuf,smb_mid)) {
06764 break;
06765 }
06766 }
06767
06768 if ((state == NULL) || (state->cmd != SMBtrans2)) {
06769 END_PROFILE(SMBtranss2);
06770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06771 }
06772
06773
06774
06775
06776 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
06777 state->total_param = SVAL(inbuf, smb_tpscnt);
06778 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
06779 state->total_data = SVAL(inbuf, smb_tdscnt);
06780
06781 pcnt = SVAL(inbuf, smb_spscnt);
06782 poff = SVAL(inbuf, smb_spsoff);
06783 pdisp = SVAL(inbuf, smb_spsdisp);
06784
06785 dcnt = SVAL(inbuf, smb_sdscnt);
06786 doff = SVAL(inbuf, smb_sdsoff);
06787 ddisp = SVAL(inbuf, smb_sdsdisp);
06788
06789 state->received_param += pcnt;
06790 state->received_data += dcnt;
06791
06792 if ((state->received_data > state->total_data) ||
06793 (state->received_param > state->total_param))
06794 goto bad_param;
06795
06796 if (pcnt) {
06797 if (pdisp > state->total_param ||
06798 pcnt > state->total_param ||
06799 pdisp+pcnt > state->total_param ||
06800 pdisp+pcnt < pdisp) {
06801 goto bad_param;
06802 }
06803
06804 if (poff > av_size ||
06805 pcnt > av_size ||
06806 poff+pcnt > av_size ||
06807 poff+pcnt < poff) {
06808 goto bad_param;
06809 }
06810
06811 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
06812 pcnt);
06813 }
06814
06815 if (dcnt) {
06816 if (ddisp > state->total_data ||
06817 dcnt > state->total_data ||
06818 ddisp+dcnt > state->total_data ||
06819 ddisp+dcnt < ddisp) {
06820 goto bad_param;
06821 }
06822
06823 if (doff > av_size ||
06824 dcnt > av_size ||
06825 doff+dcnt > av_size ||
06826 doff+dcnt < doff) {
06827 goto bad_param;
06828 }
06829
06830 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
06831 dcnt);
06832 }
06833
06834 if ((state->received_param < state->total_param) ||
06835 (state->received_data < state->total_data)) {
06836 END_PROFILE(SMBtranss2);
06837 return -1;
06838 }
06839
06840
06841
06842
06843 SCVAL(outbuf,smb_com,SMBtrans2);
06844
06845 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
06846
06847 DLIST_REMOVE(conn->pending_trans, state);
06848 SAFE_FREE(state->data);
06849 SAFE_FREE(state->param);
06850 TALLOC_FREE(state);
06851
06852 if (outsize == 0) {
06853 END_PROFILE(SMBtranss2);
06854 return(ERROR_DOS(ERRSRV,ERRnosupport));
06855 }
06856
06857 END_PROFILE(SMBtranss2);
06858 return(outsize);
06859
06860 bad_param:
06861
06862 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
06863 DLIST_REMOVE(conn->pending_trans, state);
06864 SAFE_FREE(state->data);
06865 SAFE_FREE(state->param);
06866 TALLOC_FREE(state);
06867 END_PROFILE(SMBtranss2);
06868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
06869 }