return ret_data_size;
}
+static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
+ char *pdata,
+ unsigned int total_data_size,
+ unsigned int *ret_data_size,
+ connection_struct *conn,
+ struct ea_list *ea_list)
+{
+ uint8_t *p = (uint8_t *)pdata;
+ uint8_t *last_start = NULL;
+
+ *ret_data_size = 0;
+
+ if (!lp_ea_support(SNUM(conn))) {
+ return NT_STATUS_NO_EAS_ON_FILE;
+ }
+
+ for (; ea_list; ea_list = ea_list->next) {
+ size_t dos_namelen;
+ fstring dos_ea_name;
+ size_t this_size;
+
+ if (last_start) {
+ SIVAL(last_start, 0, PTR_DIFF(p, last_start));
+ }
+ last_start = p;
+
+ push_ascii_fstring(dos_ea_name, ea_list->ea.name);
+ dos_namelen = strlen(dos_ea_name);
+ if (dos_namelen > 255 || dos_namelen == 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ if (ea_list->ea.value.length > 65535) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
+
+ if (ea_list->next) {
+ size_t pad = 4 - (this_size % 4);
+ this_size += pad;
+ }
+
+ if (this_size > total_data_size) {
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* We know we have room. */
+ SIVAL(p, 0x00, 0); /* next offset */
+ SCVAL(p, 0x04, ea_list->ea.flags);
+ SCVAL(p, 0x05, dos_namelen);
+ SSVAL(p, 0x06, ea_list->ea.value.length);
+ fstrcpy((char *)(p+0x08), dos_ea_name);
+ memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
+
+ total_data_size -= this_size;
+ p += this_size;
+ }
+
+ *ret_data_size = PTR_DIFF(p, pdata);
+ DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
+ return NT_STATUS_OK;
+}
+
static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
{
size_t total_ea_len = 0;
return;
}
-static NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- files_struct *fsp,
- const struct smb_filename *smb_fname,
- bool delete_pending,
- struct timespec write_time_ts,
- bool ms_dfs_link,
- struct ea_list *ea_list,
- int lock_data_count,
- char *lock_data,
- uint16_t flags2,
- unsigned int max_data_bytes,
- char **ppdata,
- unsigned int *pdata_size)
+NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
+ TALLOC_CTX *mem_ctx,
+ uint16_t info_level,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ bool delete_pending,
+ struct timespec write_time_ts,
+ bool ms_dfs_link,
+ struct ea_list *ea_list,
+ int lock_data_count,
+ char *lock_data,
+ uint16_t flags2,
+ unsigned int max_data_bytes,
+ char **ppdata,
+ unsigned int *pdata_size)
{
char *pdata = *ppdata;
char *dstart, *dend;
uint64_t file_size = 0;
uint64_t pos = 0;
uint64_t allocation_size = 0;
+ uint64_t file_index = 0;
+ uint32_t access_mask = 0;
sbuf = smb_fname->st;
pos = fsp->fh->position_information;
}
+ if (fsp) {
+ access_mask = fsp->access_mask;
+ } else {
+ /* GENERIC_EXECUTE mapping from Windows */
+ access_mask = 0x12019F;
+ }
+
+ /* This should be an index number - looks like
+ dev/ino to me :-)
+
+ I think this causes us to fail the IFSKIT
+ BasicFileInformationTest. -tpot */
+ file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
+ file_index |= ((sbuf.st_ex_dev) & UINT32_MAX) << 32; /* FileIndexHigh */
+
switch (info_level) {
case SMB_INFO_STANDARD:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
break;
}
+ case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
+ {
+ /* We have data_size bytes to put EA's into. */
+ size_t total_ea_len = 0;
+ struct ea_list *ea_file_list = NULL;
+
+ DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
+
+ /*TODO: add filtering and index handling */
+
+ ea_file_list = get_ea_list_from_file(mem_ctx,
+ conn, fsp,
+ fname,
+ &total_ea_len);
+ if (!ea_file_list) {
+ return NT_STATUS_NO_EAS_ON_FILE;
+ }
+
+ status = fill_ea_chained_buffer(mem_ctx,
+ pdata,
+ data_size,
+ &data_size,
+ conn, ea_file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ break;
+ }
+
case SMB_FILE_BASIC_INFORMATION:
case SMB_QUERY_FILE_BASIC_INFO:
data_size = PTR_DIFF(pdata,(*ppdata));
break;
}
- case SMB_FILE_INTERNAL_INFORMATION:
- /* This should be an index number - looks like
- dev/ino to me :-)
- I think this causes us to fail the IFSKIT
- BasicFileInformationTest. -tpot */
+ case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
+ {
+ int len;
+ unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
+ DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
+ put_long_date_timespec(pdata+0x00,create_time_ts);
+ put_long_date_timespec(pdata+0x08,atime_ts);
+ put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
+ put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
+ SIVAL(pdata, 0x20, mode);
+ SIVAL(pdata, 0x24, 0); /* padding. */
+ SBVAL(pdata, 0x28, allocation_size);
+ SBVAL(pdata, 0x30, file_size);
+ SIVAL(pdata, 0x38, nlink);
+ SCVAL(pdata, 0x3C, delete_pending);
+ SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
+ SSVAL(pdata, 0x3E, 0); /* padding */
+ SBVAL(pdata, 0x40, file_index);
+ SIVAL(pdata, 0x48, ea_size);
+ SIVAL(pdata, 0x4C, access_mask);
+ SBVAL(pdata, 0x50, pos);
+ SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
+ SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
+
+ pdata += 0x60;
+
+ len = srvstr_push(dstart, flags2,
+ pdata+4, dos_fname,
+ PTR_DIFF(dend, pdata+4),
+ STR_UNICODE);
+ SIVAL(pdata,0,len);
+ pdata += 4 + len;
+ data_size = PTR_DIFF(pdata,(*ppdata));
+ break;
+ }
+ case SMB_FILE_INTERNAL_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
- SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
- SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
+ SBVAL(pdata, 0, file_index);
data_size = 8;
break;
case SMB_FILE_ACCESS_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
- if (fsp) {
- SIVAL(pdata,0,fsp->access_mask);
- } else {
- /* GENERIC_EXECUTE mapping from Windows */
- SIVAL(pdata,0,0x12019F);
- }
+ SIVAL(pdata, 0, access_mask);
data_size = 4;
break;
break;
}
+ if ((info_level & 0xFF00) == 0xFF00) {
+ /*
+ * We use levels that start with 0xFF00
+ * internally to represent SMB2 specific levels
+ */
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
+ }
+
status = smbd_do_qfilepathinfo(conn, req, info_level,
fsp, smb_fname,
delete_pending, write_time_ts,