~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libcli/smb2/find.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   SMB2 client find calls
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2005
 
7
   
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
#include "libcli/raw/libcliraw.h"
 
24
#include "libcli/raw/raw_proto.h"
 
25
#include "libcli/smb2/smb2.h"
 
26
#include "libcli/smb2/smb2_calls.h"
 
27
 
 
28
/*
 
29
  send a find request
 
30
*/
 
31
struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io)
 
32
{
 
33
        struct smb2_request *req;
 
34
        NTSTATUS status;
 
35
 
 
36
        req = smb2_request_init_tree(tree, SMB2_OP_FIND, 0x20, true, 0);
 
37
        if (req == NULL) return NULL;
 
38
 
 
39
        SCVAL(req->out.body, 0x02, io->in.level);
 
40
        SCVAL(req->out.body, 0x03, io->in.continue_flags);
 
41
        SIVAL(req->out.body, 0x04, io->in.file_index);
 
42
        smb2_push_handle(req->out.body+0x08, &io->in.file.handle);
 
43
 
 
44
        status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern);
 
45
        if (!NT_STATUS_IS_OK(status)) {
 
46
                talloc_free(req);
 
47
                return NULL;
 
48
        }
 
49
 
 
50
        SIVAL(req->out.body, 0x1C, io->in.max_response_size);
 
51
 
 
52
        smb2_transport_send(req);
 
53
 
 
54
        return req;
 
55
}
 
56
 
 
57
 
 
58
/*
 
59
  recv a find reply
 
60
*/
 
61
NTSTATUS smb2_find_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
 
62
                           struct smb2_find *io)
 
63
{
 
64
        NTSTATUS status;
 
65
 
 
66
        if (!smb2_request_receive(req) || 
 
67
            smb2_request_is_error(req)) {
 
68
                return smb2_request_destroy(req);
 
69
        }
 
70
 
 
71
        SMB2_CHECK_PACKET_RECV(req, 0x08, true);
 
72
 
 
73
        status = smb2_pull_o16s32_blob(&req->in, mem_ctx, 
 
74
                                       req->in.body+0x02, &io->out.blob);
 
75
        if (!NT_STATUS_IS_OK(status)) {
 
76
                return status;
 
77
        }
 
78
 
 
79
        return smb2_request_destroy(req);
 
80
}
 
81
 
 
82
/*
 
83
  sync find request
 
84
*/
 
85
NTSTATUS smb2_find(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
 
86
                   struct smb2_find *io)
 
87
{
 
88
        struct smb2_request *req = smb2_find_send(tree, io);
 
89
        return smb2_find_recv(req, mem_ctx, io);
 
90
}
 
91
 
 
92
 
 
93
/*
 
94
  a varient of smb2_find_recv that parses the resulting blob into
 
95
  smb_search_data structures
 
96
*/
 
97
NTSTATUS smb2_find_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
 
98
                              uint8_t level, uint_t *count,
 
99
                              union smb_search_data **io)
 
100
{
 
101
        struct smb2_find f;
 
102
        NTSTATUS status;
 
103
        DATA_BLOB b;
 
104
        enum smb_search_data_level smb_level;
 
105
        uint_t next_ofs=0;
 
106
 
 
107
        switch (level) {
 
108
        case SMB2_FIND_DIRECTORY_INFO:
 
109
                smb_level = RAW_SEARCH_DATA_DIRECTORY_INFO;
 
110
                break;
 
111
        case SMB2_FIND_FULL_DIRECTORY_INFO:
 
112
                smb_level = RAW_SEARCH_DATA_FULL_DIRECTORY_INFO;
 
113
                break;
 
114
        case SMB2_FIND_BOTH_DIRECTORY_INFO:
 
115
                smb_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
 
116
                break;
 
117
        case SMB2_FIND_NAME_INFO:
 
118
                smb_level = RAW_SEARCH_DATA_NAME_INFO;
 
119
                break;
 
120
        case SMB2_FIND_ID_FULL_DIRECTORY_INFO:
 
121
                smb_level = RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO;
 
122
                break;
 
123
        case SMB2_FIND_ID_BOTH_DIRECTORY_INFO:
 
124
                smb_level = RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO;
 
125
                break;
 
126
        default:
 
127
                return NT_STATUS_INVALID_INFO_CLASS;
 
128
        }
 
129
 
 
130
        status = smb2_find_recv(req, mem_ctx, &f);
 
131
        NT_STATUS_NOT_OK_RETURN(status);
 
132
        
 
133
        b = f.out.blob;
 
134
        *io = NULL;
 
135
        *count = 0;
 
136
 
 
137
        do {
 
138
                union smb_search_data *io2;
 
139
 
 
140
                io2 = talloc_realloc(mem_ctx, *io, union smb_search_data, (*count)+1);
 
141
                if (io2 == NULL) {
 
142
                        data_blob_free(&f.out.blob);
 
143
                        talloc_free(*io);
 
144
                        return NT_STATUS_NO_MEMORY;
 
145
                }
 
146
                *io = io2;
 
147
 
 
148
                status = smb_raw_search_common(*io, smb_level, &b, (*io) + (*count), 
 
149
                                               &next_ofs, STR_UNICODE);
 
150
 
 
151
                if (NT_STATUS_IS_OK(status) &&
 
152
                    next_ofs >= b.length) {
 
153
                        data_blob_free(&f.out.blob);
 
154
                        talloc_free(*io);
 
155
                        return NT_STATUS_INFO_LENGTH_MISMATCH;                  
 
156
                }
 
157
 
 
158
                (*count)++;
 
159
 
 
160
                b = data_blob_const(b.data+next_ofs, b.length - next_ofs);
 
161
        } while (NT_STATUS_IS_OK(status) && next_ofs != 0);
 
162
 
 
163
        data_blob_free(&f.out.blob);
 
164
        
 
165
        return NT_STATUS_OK;
 
166
}
 
167
 
 
168
/*
 
169
  a varient of smb2_find that parses the resulting blob into
 
170
  smb_search_data structures
 
171
*/
 
172
NTSTATUS smb2_find_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
 
173
                         struct smb2_find *f, 
 
174
                         uint_t *count, union smb_search_data **io)
 
175
{
 
176
        struct smb2_request *req;
 
177
 
 
178
        req = smb2_find_send(tree, f);
 
179
        return smb2_find_level_recv(req, mem_ctx, f->in.level, count, io);
 
180
}