• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/ntvfs/posix/
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*/
29bool 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*/
40NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno)
41{
42	NTSTATUS status;
43	status = map_nt_error_from_unix(unix_errno);
44	DEBUG(10,(__location__ " mapped unix errno %d -> %s\n", unix_errno, nt_errstr(status)));
45	return status;
46}
47
48
49/*
50  check if a filename has an attribute matching the given attribute search value
51  this is used by calls like unlink and search which take an attribute
52  and only include special files if they match the given attribute
53*/
54NTSTATUS pvfs_match_attrib(struct pvfs_state *pvfs, struct pvfs_filename *name,
55			   uint32_t attrib, uint32_t must_attrib)
56{
57	if ((name->dos.attrib & ~attrib) & FILE_ATTRIBUTE_DIRECTORY) {
58		return NT_STATUS_FILE_IS_A_DIRECTORY;
59	}
60	if ((name->dos.attrib & ~attrib) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
61		return NT_STATUS_NO_SUCH_FILE;
62	}
63	if (must_attrib & ~name->dos.attrib) {
64		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
65	}
66	return NT_STATUS_OK;
67}
68
69
70/*
71  normalise a file attribute
72*/
73uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode)
74{
75	if (attrib != FILE_ATTRIBUTE_NORMAL) {
76		attrib &= ~FILE_ATTRIBUTE_NORMAL;
77	}
78	if (S_ISDIR(mode)) {
79		attrib |= FILE_ATTRIBUTE_DIRECTORY;
80	} else {
81		attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
82	}
83	return attrib;
84}
85
86
87/*
88  copy a file. Caller is supposed to have already ensured that the
89  operation is allowed. The destination file must not exist.
90*/
91NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
92			struct pvfs_filename *name1,
93			struct pvfs_filename *name2)
94{
95	int fd1, fd2;
96	mode_t mode;
97	NTSTATUS status;
98	size_t buf_size = 0x10000;
99	uint8_t *buf = talloc_array(name2, uint8_t, buf_size);
100
101	if (buf == NULL) {
102		return NT_STATUS_NO_MEMORY;
103	}
104
105	fd1 = open(name1->full_name, O_RDONLY);
106	if (fd1 == -1) {
107		talloc_free(buf);
108		return pvfs_map_errno(pvfs, errno);
109	}
110
111	fd2 = open(name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0);
112	if (fd2 == -1) {
113		close(fd1);
114		talloc_free(buf);
115		return pvfs_map_errno(pvfs, errno);
116	}
117
118	while (1) {
119		ssize_t ret2, ret = read(fd1, buf, buf_size);
120		if (ret == -1 &&
121		    (errno == EINTR || errno == EAGAIN)) {
122			continue;
123		}
124		if (ret <= 0) break;
125
126		ret2 = write(fd2, buf, ret);
127		if (ret2 == -1 &&
128		    (errno == EINTR || errno == EAGAIN)) {
129			continue;
130		}
131
132		if (ret2 != ret) {
133			close(fd1);
134			close(fd2);
135			talloc_free(buf);
136			unlink(name2->full_name);
137			if (ret2 == -1) {
138				return pvfs_map_errno(pvfs, errno);
139			}
140			return NT_STATUS_DISK_FULL;
141		}
142	}
143
144	talloc_free(buf);
145	close(fd1);
146
147	mode = pvfs_fileperms(pvfs, name1->dos.attrib);
148	if (fchmod(fd2, mode) == -1) {
149		status = pvfs_map_errno(pvfs, errno);
150		close(fd2);
151		unlink(name2->full_name);
152		return status;
153	}
154
155	name2->st.st_mode = mode;
156	name2->dos = name1->dos;
157
158	status = pvfs_dosattrib_save(pvfs, name2, fd2);
159	if (!NT_STATUS_IS_OK(status)) {
160		close(fd2);
161		unlink(name2->full_name);
162		return status;
163	}
164
165	close(fd2);
166
167	return NT_STATUS_OK;
168}
169
170
171/*
172   hash a string of the specified length. The string does not need to be
173   null terminated
174
175   hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce).
176   see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a
177   discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors
178*/
179uint32_t pvfs_name_hash(const char *key, size_t length)
180{
181	const uint32_t fnv1_prime = 0x01000193;
182	const uint32_t fnv1_init = 0xa6b93095;
183	uint32_t value = fnv1_init;
184
185	while (*key && length--) {
186		size_t c_size;
187		codepoint_t c = next_codepoint(key, &c_size);
188		c = toupper_m(c);
189                value *= fnv1_prime;
190                value ^= (uint32_t)c;
191		key += c_size;
192        }
193
194	return value;
195}
196
197
198/*
199  file allocation size rounding. This is required to pass ifstest
200*/
201uint64_t pvfs_round_alloc_size(struct pvfs_state *pvfs, uint64_t size)
202{
203	const uint32_t round_value = pvfs->alloc_size_rounding;
204	return round_value * ((size + round_value - 1)/round_value);
205}
206