~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/ntvfs/posix/pvfs_util.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
   Copyright (C) Andrew Tridgell 2004
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
   
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
   
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
/*
 
20
  utility functions for posix backend
 
21
*/
 
22
 
 
23
#include "includes.h"
 
24
#include "vfs_posix.h"
 
25
 
 
26
/*
 
27
  return true if a string contains one of the CIFS wildcard characters
 
28
*/
 
29
bool pvfs_has_wildcard(const char *str)
 
30
{
 
31
        if (strpbrk(str, "*?<>\"")) {
 
32
                return true;
 
33
        }
 
34
        return false;
 
35
}
 
36
 
 
37
/*
 
38
  map a unix errno to a NTSTATUS
 
39
*/
 
40
NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno)
 
41
{
 
42
        return map_nt_error_from_unix(unix_errno);
 
43
}
 
44
 
 
45
 
 
46
/*
 
47
  check if a filename has an attribute matching the given attribute search value
 
48
  this is used by calls like unlink and search which take an attribute
 
49
  and only include special files if they match the given attribute
 
50
*/
 
51
NTSTATUS pvfs_match_attrib(struct pvfs_state *pvfs, struct pvfs_filename *name, 
 
52
                           uint32_t attrib, uint32_t must_attrib)
 
53
{
 
54
        if ((name->dos.attrib & ~attrib) & FILE_ATTRIBUTE_DIRECTORY) {
 
55
                return NT_STATUS_FILE_IS_A_DIRECTORY;
 
56
        }
 
57
        if ((name->dos.attrib & ~attrib) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
 
58
                return NT_STATUS_NO_SUCH_FILE;
 
59
        }
 
60
        if (must_attrib & ~name->dos.attrib) {
 
61
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
62
        }
 
63
        return NT_STATUS_OK;
 
64
}
 
65
 
 
66
 
 
67
/*
 
68
  normalise a file attribute
 
69
*/
 
70
uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode)
 
71
{
 
72
        if (attrib != FILE_ATTRIBUTE_NORMAL) {
 
73
                attrib &= ~FILE_ATTRIBUTE_NORMAL;
 
74
        }
 
75
        if (S_ISDIR(mode)) {
 
76
                attrib |= FILE_ATTRIBUTE_DIRECTORY;
 
77
        } else {
 
78
                attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
 
79
        }
 
80
        return attrib;
 
81
}
 
82
 
 
83
 
 
84
/*
 
85
  copy a file. Caller is supposed to have already ensured that the
 
86
  operation is allowed. The destination file must not exist.
 
87
*/
 
88
NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
 
89
                        struct pvfs_filename *name1, 
 
90
                        struct pvfs_filename *name2)
 
91
{
 
92
        int fd1, fd2;
 
93
        mode_t mode;
 
94
        NTSTATUS status;
 
95
        size_t buf_size = 0x10000;
 
96
        uint8_t *buf = talloc_array(name2, uint8_t, buf_size);
 
97
 
 
98
        if (buf == NULL) {
 
99
                return NT_STATUS_NO_MEMORY;
 
100
        }
 
101
 
 
102
        fd1 = open(name1->full_name, O_RDONLY);
 
103
        if (fd1 == -1) {
 
104
                talloc_free(buf);
 
105
                return pvfs_map_errno(pvfs, errno);
 
106
        }
 
107
 
 
108
        fd2 = open(name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0);
 
109
        if (fd2 == -1) {
 
110
                close(fd1);
 
111
                talloc_free(buf);
 
112
                return pvfs_map_errno(pvfs, errno);
 
113
        }
 
114
 
 
115
        while (1) {
 
116
                ssize_t ret2, ret = read(fd1, buf, buf_size);
 
117
                if (ret == -1 && 
 
118
                    (errno == EINTR || errno == EAGAIN)) {
 
119
                        continue;
 
120
                }
 
121
                if (ret <= 0) break;
 
122
 
 
123
                ret2 = write(fd2, buf, ret);
 
124
                if (ret2 == -1 &&
 
125
                    (errno == EINTR || errno == EAGAIN)) {
 
126
                        continue;
 
127
                }
 
128
                
 
129
                if (ret2 != ret) {
 
130
                        close(fd1);
 
131
                        close(fd2);
 
132
                        talloc_free(buf);
 
133
                        unlink(name2->full_name);
 
134
                        if (ret2 == -1) {
 
135
                                return pvfs_map_errno(pvfs, errno);
 
136
                        }
 
137
                        return NT_STATUS_DISK_FULL;
 
138
                }
 
139
        }
 
140
 
 
141
        talloc_free(buf);
 
142
        close(fd1);
 
143
 
 
144
        mode = pvfs_fileperms(pvfs, name1->dos.attrib);
 
145
        if (fchmod(fd2, mode) == -1) {
 
146
                status = pvfs_map_errno(pvfs, errno);
 
147
                close(fd2);
 
148
                unlink(name2->full_name);
 
149
                return status;
 
150
        }
 
151
 
 
152
        name2->st.st_mode = mode;
 
153
        name2->dos = name1->dos;
 
154
 
 
155
        status = pvfs_dosattrib_save(pvfs, name2, fd2);
 
156
        if (!NT_STATUS_IS_OK(status)) {
 
157
                close(fd2);
 
158
                unlink(name2->full_name);
 
159
                return status;
 
160
        }
 
161
 
 
162
        close(fd2);
 
163
 
 
164
        return NT_STATUS_OK;
 
165
}
 
166
 
 
167
 
 
168
/* 
 
169
   hash a string of the specified length. The string does not need to be
 
170
   null terminated 
 
171
 
 
172
   hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce).
 
173
   see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a
 
174
   discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors
 
175
*/
 
176
uint32_t pvfs_name_hash(const char *key, size_t length)
 
177
{
 
178
        const uint32_t fnv1_prime = 0x01000193;
 
179
        const uint32_t fnv1_init = 0xa6b93095;
 
180
        uint32_t value = fnv1_init;
 
181
 
 
182
        while (*key && length--) {
 
183
                size_t c_size;
 
184
                codepoint_t c = next_codepoint(key, &c_size);
 
185
                c = toupper_m(c);
 
186
                value *= fnv1_prime;
 
187
                value ^= (uint32_t)c;
 
188
                key += c_size;
 
189
        }
 
190
 
 
191
        return value;
 
192
}
 
193
 
 
194
 
 
195
/*
 
196
  file allocation size rounding. This is required to pass ifstest
 
197
*/
 
198
uint64_t pvfs_round_alloc_size(struct pvfs_state *pvfs, uint64_t size)
 
199
{
 
200
        const uint32_t round_value = pvfs->alloc_size_rounding;
 
201
        return round_value * ((size + round_value - 1)/round_value);
 
202
}