NativeState::ftruncate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1.064

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 3
cts 5
cp 0.6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1.064
1
<?php
2
/**
3
 * Copyright (c) 2014 Robin Appelman <[email protected]>
4
 * This file is licensed under the Licensed under the MIT license:
5
 * http://opensource.org/licenses/MIT
6
 */
7
8
namespace Icewind\SMB\Native;
9
10
use Icewind\SMB\Exception\AlreadyExistsException;
11
use Icewind\SMB\Exception\ConnectionRefusedException;
12
use Icewind\SMB\Exception\ConnectionResetException;
13
use Icewind\SMB\Exception\Exception;
14
use Icewind\SMB\Exception\FileInUseException;
15
use Icewind\SMB\Exception\ForbiddenException;
16
use Icewind\SMB\Exception\HostDownException;
17
use Icewind\SMB\Exception\InvalidArgumentException;
18
use Icewind\SMB\Exception\InvalidTypeException;
19
use Icewind\SMB\Exception\ConnectionAbortedException;
20
use Icewind\SMB\Exception\NoRouteToHostException;
21
use Icewind\SMB\Exception\NotEmptyException;
22
use Icewind\SMB\Exception\NotFoundException;
23
use Icewind\SMB\Exception\OutOfSpaceException;
24
use Icewind\SMB\Exception\TimedOutException;
25
use Icewind\SMB\IAuth;
26
use Icewind\SMB\IOptions;
27
28
/**
29
 * Low level wrapper for libsmbclient-php with error handling
30
 */
31
class NativeState {
32
	/** @var resource|null */
33
	protected $state = null;
34
35
	/** @var bool */
36
	protected $handlerSet = false;
37
38
	/** @var bool */
39
	protected $connected = false;
40
41
	// see error.h
42
	const EXCEPTION_MAP = [
43
		1   => ForbiddenException::class,
44
		2   => NotFoundException::class,
45
		13  => ForbiddenException::class,
46
		16  => FileInUseException::class,
47
		17  => AlreadyExistsException::class,
48
		20  => InvalidTypeException::class,
49
		21  => InvalidTypeException::class,
50
		22  => InvalidArgumentException::class,
51
		28  => OutOfSpaceException::class,
52
		39  => NotEmptyException::class,
53
		103 => ConnectionAbortedException::class,
54
		104 => ConnectionResetException::class,
55
		110 => TimedOutException::class,
56
		111 => ConnectionRefusedException::class,
57
		112 => HostDownException::class,
58
		113 => NoRouteToHostException::class
59
	];
60
61 494
	protected function handleError(?string $path): void {
62 494
		/** @var int $error */
63 494
		$error = smbclient_state_errno($this->state);
64 494
		if ($error === 0) {
65
			return;
66 36
		}
67
		throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path);
68
	}
69 494
70 494
	/**
71
	 * @param mixed $result
72 494
	 * @param string|null $uri
73 36
	 * @throws Exception
74 36
	 */
75
	protected function testResult($result, ?string $uri): void {
76 494
		if ($result === false or $result === null) {
77
			// smb://host/share/path
78 494
			if (is_string($uri) && count(explode('/', $uri, 5)) > 4) {
79
				list(, , , , $path) = explode('/', $uri, 5);
80 494
				$path = '/' . $path;
81
			} else {
82
				$path = $uri;
83
			}
84
			$this->handleError($path);
85
		}
86
	}
87 494
88 494
	/**
89
	 * @param IAuth $auth
90
	 * @param IOptions $options
91 494
	 * @return bool
92 494
	 */
93 494
	public function init(IAuth $auth, IOptions $options) {
94 494
		if ($this->connected) {
95 494
			return true;
96
		}
97 494
		/** @var resource $state */
98 494
		$state = smbclient_state_new();
99 494
		$this->state = $state;
100
		/** @psalm-suppress UnusedFunctionCall */
101
		smbclient_option_set($this->state, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, false);
102
		/** @psalm-suppress UnusedFunctionCall */
103
		smbclient_option_set($this->state, SMBCLIENT_OPT_TIMEOUT, $options->getTimeout() * 1000);
104
105
		if (function_exists('smbclient_client_protocols')) {
106 494
			smbclient_client_protocols($this->state, $options->getMinProtocol(), $options->getMaxProtocol());
107 494
		}
108
109 494
		$auth->setExtraSmbClientOptions($this->state);
110 494
		/** @var bool $result */
111
		$result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword());
112
113
		$this->testResult($result, '');
114
		$this->connected = true;
115
		return $result;
116
	}
117 494
118 494
	/**
119
	 * @param string $uri
120 494
	 * @return resource
121 494
	 */
122
	public function opendir(string $uri) {
123
		/** @var resource $result */
124
		$result = @smbclient_opendir($this->state, $uri);
125
126
		$this->testResult($result, $uri);
127
		return $result;
128 494
	}
129 494
130
	/**
131 494
	 * @param resource $dir
132 494
	 * @param string $path
133
	 * @return array{"type": string, "comment": string, "name": string}|false
0 ignored issues
show
Documentation introduced by
The doc-type array{"type": could not be parsed: Unknown type name "array{"type":" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
134
	 */
135
	public function readdir($dir, string $path) {
136
		/** @var array{"type": string, "comment": string, "name": string}|false $result */
137
		$result = @smbclient_readdir($this->state, $dir);
138
139
		$this->testResult($result, $path);
140 38
		return $result;
141 38
	}
142
143 38
	/**
144 32
	 * @param resource $dir
145
	 * @param string $path
146
	 * @return bool
147
	 */
148
	public function closedir($dir, string $path): bool {
149
		/** @var bool $result */
150
		$result = smbclient_closedir($this->state, $dir);
151 232
152 232
		$this->testResult($result, $path);
153
		return $result;
154 232
	}
155 230
156
	/**
157
	 * @param string $old
158
	 * @param string $new
159
	 * @return bool
160
	 */
161
	public function rename(string $old, string $new): bool {
162
		/** @var bool $result */
163 494
		$result = @smbclient_rename($this->state, $old, $this->state, $new);
164 494
165
		$this->testResult($result, $new);
166 494
		return $result;
167 494
	}
168
169
	/**
170
	 * @param string $uri
171
	 * @return bool
172
	 */
173
	public function unlink(string $uri): bool {
174 494
		/** @var bool $result */
175 494
		$result = @smbclient_unlink($this->state, $uri);
176
177 494
		$this->testResult($result, $uri);
178 494
		return $result;
179
	}
180
181
	/**
182
	 * @param string $uri
183
	 * @param int $mask
184
	 * @return bool
185 36
	 */
186 36
	public function mkdir(string $uri, int $mask = 0777): bool {
187
		/** @var bool $result */
188 36
		$result = @smbclient_mkdir($this->state, $uri, $mask);
189 36
190
		$this->testResult($result, $uri);
191
		return $result;
192
	}
193
194
	/**
195
	 * @param string $uri
196
	 * @return bool
197
	 */
198
	public function rmdir(string $uri): bool {
199
		/** @var bool $result */
200
		$result = @smbclient_rmdir($this->state, $uri);
201
202
		$this->testResult($result, $uri);
203
		return $result;
204
	}
205
206
	/**
207
	 * @param string $uri
208
	 * @return array{"mtime": int, "size": int, "mode": int}
0 ignored issues
show
Documentation introduced by
The doc-type array{"mtime": could not be parsed: Unknown type name "array{"mtime":" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
209 112
	 */
210 112
	public function stat(string $uri): array {
211
		/** @var array{"mtime": int, "size": int, "mode": int} $result */
212 112
		$result = @smbclient_stat($this->state, $uri);
213 108
214
		$this->testResult($result, $uri);
215
		return $result;
216
	}
217
218
	/**
219
	 * @param resource $file
220
	 * @param string $path
221 232
	 * @return array{"mtime": int, "size": int, "mode": int}
0 ignored issues
show
Documentation introduced by
The doc-type array{"mtime": could not be parsed: Unknown type name "array{"mtime":" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
222 232
	 */
223
	public function fstat($file, string $path): array {
224 232
		/** @var array{"mtime": int, "size": int, "mode": int} $result */
225 228
		$result = @smbclient_fstat($this->state, $file);
226
227
		$this->testResult($result, $path);
228
		return $result;
229
	}
230
231
	/**
232
	 * @param string $uri
233 104
	 * @param string $mode
234 104
	 * @param int $mask
235
	 * @return resource
236 104
	 */
237 104
	public function open(string $uri, string $mode, int $mask = 0666) {
238
		/** @var resource $result */
239
		$result = @smbclient_open($this->state, $uri, $mode, $mask);
240
241
		$this->testResult($result, $uri);
242
		return $result;
243
	}
244
245
	/**
246
	 * @param string $uri
247 230
	 * @param int $mask
248 230
	 * @return resource
249
	 */
250 230
	public function create(string $uri, int $mask = 0666) {
251 230
		/** @var resource $result */
252
		$result = @smbclient_creat($this->state, $uri, $mask);
253
254
		$this->testResult($result, $uri);
255
		return $result;
256
	}
257
258
	/**
259
	 * @param resource $file
260 4
	 * @param int $bytes
261 4
	 * @param string $path
262
	 * @return string
263 4
	 */
264 4
	public function read($file, int $bytes, string $path): string {
265
		/** @var string $result */
266
		$result = @smbclient_read($this->state, $file, $bytes);
267
268
		$this->testResult($result, $path);
269
		return $result;
270
	}
271
272 2
	/**
273 2
	 * @param resource $file
274
	 * @param string $data
275 2
	 * @param string $path
276 2
	 * @param int|null $length
277
	 * @return int
278
	 */
279 230
	public function write($file, string $data, string $path, ?int $length = null): int {
280 230
		/** @var int $result */
281
		$result = @smbclient_write($this->state, $file, $data, $length);
282 230
283 230
		$this->testResult($result, $path);
284
		return $result;
285
	}
286
287
	/**
288
	 * @param resource $file
289
	 * @param int $offset
290
	 * @param int $whence SEEK_SET | SEEK_CUR | SEEK_END
291 192
	 * @param string|null $path
292 192
	 * @return int|false new file offset as measured from the start of the file on success.
293
	 */
294 192
	public function lseek($file, int $offset, int $whence = SEEK_SET, string $path = null) {
295 190
		/** @var int|false $result */
296
		$result = @smbclient_lseek($this->state, $file, $offset, $whence);
297
298
		$this->testResult($result, $path);
299
		return $result;
300
	}
301
302
	/**
303
	 * @param resource $file
304
	 * @param int $size
305
	 * @param string $path
306
	 * @return bool
307
	 */
308
	public function ftruncate($file, int $size, string $path): bool {
309
		/** @var bool $result */
310
		$result = @smbclient_ftruncate($this->state, $file, $size);
311
312 496
		$this->testResult($result, $path);
313 496
		return $result;
314 494
	}
315
316 496
	/**
317
	 * @param resource $file
318
	 * @param string $path
319
	 * @return bool
320
	 */
321
	public function close($file, string $path): bool {
322
		/** @var bool $result */
323
		$result = @smbclient_close($this->state, $file);
324
325
		$this->testResult($result, $path);
326
		return $result;
327
	}
328
329
	/**
330
	 * @param string $uri
331
	 * @param string $key
332
	 * @return string
333
	 */
334
	public function getxattr(string $uri, string $key) {
335
		/** @var string $result */
336
		$result = @smbclient_getxattr($this->state, $uri, $key);
337
338
		$this->testResult($result, $uri);
339
		return $result;
340
	}
341
342
	/**
343
	 * @param string $uri
344
	 * @param string $key
345
	 * @param string $value
346
	 * @param int $flags
347
	 * @return bool
348
	 */
349
	public function setxattr(string $uri, string $key, string $value, int $flags = 0) {
350
		/** @var bool $result */
351
		$result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags);
352
353
		$this->testResult($result, $uri);
354
		return $result;
355
	}
356
357
	public function __destruct() {
358
		if ($this->connected) {
359
			if (smbclient_state_free($this->state) === false) {
360
				throw new Exception("Failed to free smb state");
361
			}
362
		}
363
	}
364
}
365