@@ -28,6 +28,8 @@ class Filesystem
2828 * @param string $originFile The original filename
2929 * @param string $targetFile The target filename
3030 * @param array $override Whether to override an existing file or not
31+ *
32+ * @throws Exception\IOException When copy fails
3133 */
3234 public function copy ($ originFile , $ targetFile , $ override = false )
3335 {
@@ -40,30 +42,31 @@ public function copy($originFile, $targetFile, $override = false)
4042 }
4143
4244 if ($ doCopy ) {
43- copy ($ originFile , $ targetFile );
45+ if (true !== @copy ($ originFile , $ targetFile )) {
46+ throw new Exception \IOException (sprintf ('Failed to copy %s to %s ' , $ originFile , $ targetFile ));
47+ }
4448 }
4549 }
4650
4751 /**
4852 * Creates a directory recursively.
4953 *
5054 * @param string|array|\Traversable $dirs The directory path
51- * @param int $mode The directory mode
55+ * @param integer $mode The directory mode
5256 *
53- * @return Boolean true if the directory has been created, false otherwise
57+ * @throws Exception\IOException On any directory creation failure
5458 */
5559 public function mkdir ($ dirs , $ mode = 0777 )
5660 {
57- $ ret = true ;
5861 foreach ($ this ->toIterator ($ dirs ) as $ dir ) {
5962 if (is_dir ($ dir )) {
6063 continue ;
6164 }
6265
63- $ ret = @mkdir ($ dir , $ mode , true ) && $ ret ;
66+ if (true !== @mkdir ($ dir , $ mode , true )) {
67+ throw new Exception \IOException (sprintf ('Failed to create %s ' , $ dir ));
68+ }
6469 }
65-
66- return $ ret ;
6770 }
6871
6972 /**
@@ -85,21 +88,33 @@ public function exists($files)
8588 }
8689
8790 /**
88- * Creates empty files .
91+ * Sets access and modification time of file .
8992 *
9093 * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
94+ * @param integer $time The touch time as a unix timestamp
95+ * @param integer $atime The access time as a unix timestamp
96+ *
97+ * @throws Exception\IOException When touch fails
9198 */
92- public function touch ($ files )
99+ public function touch ($ files, $ time = null , $ atime = null )
93100 {
101+ if (null === $ time ) {
102+ $ time = time ();
103+ }
104+
94105 foreach ($ this ->toIterator ($ files ) as $ file ) {
95- touch ($ file );
106+ if (true !== @touch ($ file , $ time , $ atime )) {
107+ throw new Exception \IOException (sprintf ('Failed to touch %s ' , $ file ));
108+ }
96109 }
97110 }
98111
99112 /**
100113 * Removes files or directories.
101114 *
102115 * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
116+ *
117+ * @throws Exception\IOException When removal fails
103118 */
104119 public function remove ($ files )
105120 {
@@ -113,13 +128,19 @@ public function remove($files)
113128 if (is_dir ($ file ) && !is_link ($ file )) {
114129 $ this ->remove (new \FilesystemIterator ($ file ));
115130
116- rmdir ($ file );
131+ if (true !== @rmdir ($ file )) {
132+ throw new Exception \IOException (sprintf ('Failed to remove directory %s ' , $ file ));
133+ }
117134 } else {
118135 // https://bugs.php.net/bug.php?id=52176
119136 if (defined ('PHP_WINDOWS_VERSION_MAJOR ' ) && is_dir ($ file )) {
120- rmdir ($ file );
137+ if (true !== @rmdir ($ file )) {
138+ throw new Exception \IOException (sprintf ('Failed to remove file %s ' , $ file ));
139+ }
121140 } else {
122- unlink ($ file );
141+ if (true !== @unlink ($ file )) {
142+ throw new Exception \IOException (sprintf ('Failed to remove file %s ' , $ file ));
143+ }
123144 }
124145 }
125146 }
@@ -128,14 +149,76 @@ public function remove($files)
128149 /**
129150 * Change mode for an array of files or directories.
130151 *
131- * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
132- * @param integer $mode The new mode (octal)
133- * @param integer $umask The mode mask (octal)
152+ * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
153+ * @param integer $mode The new mode (octal)
154+ * @param integer $umask The mode mask (octal)
155+ * @param Boolean $recursive Whether change the mod recursively or not
156+ *
157+ * @throws Exception\IOException When the change fail
134158 */
135- public function chmod ($ files , $ mode , $ umask = 0000 )
159+ public function chmod ($ files , $ mode , $ umask = 0000 , $ recursive = false )
136160 {
137161 foreach ($ this ->toIterator ($ files ) as $ file ) {
138- @chmod ($ file , $ mode & ~$ umask );
162+ if ($ recursive && is_dir ($ file ) && !is_link ($ file )) {
163+ $ this ->chmod (new \FilesystemIterator ($ file ), $ mode , $ umask , true );
164+ }
165+ if (true !== @chmod ($ file , $ mode & ~$ umask )) {
166+ throw new Exception \IOException (sprintf ('Failed to chmod file %s ' , $ file ));
167+ }
168+ }
169+ }
170+
171+ /**
172+ * Change the owner of an array of files or directories
173+ *
174+ * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner
175+ * @param string $user The new owner user name
176+ * @param Boolean $recursive Whether change the owner recursively or not
177+ *
178+ * @throws Exception\IOException When the change fail
179+ */
180+ public function chown ($ files , $ user , $ recursive = false )
181+ {
182+ foreach ($ this ->toIterator ($ files ) as $ file ) {
183+ if ($ recursive && is_dir ($ file ) && !is_link ($ file )) {
184+ $ this ->chown (new \FilesystemIterator ($ file ), $ user , true );
185+ }
186+ if (is_link ($ file ) && function_exists ('lchown ' )) {
187+ if (true !== @lchown ($ file , $ user )) {
188+ throw new Exception \IOException (sprintf ('Failed to chown file %s ' , $ file ));
189+ }
190+ } else {
191+ if (true !== @chown ($ file , $ user )) {
192+ throw new Exception \IOException (sprintf ('Failed to chown file %s ' , $ file ));
193+ }
194+ }
195+ }
196+ }
197+
198+ /**
199+ * Change the group of an array of files or directories
200+ *
201+ * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group
202+ * @param string $group The group name
203+ * @param Boolean $recursive Whether change the group recursively or not
204+ *
205+ * @throws Exception\IOException When the change fail
206+ */
207+ public function chgrp ($ files , $ group , $ recursive = false )
208+ {
209+ foreach ($ this ->toIterator ($ files ) as $ file ) {
210+ if ($ recursive && is_dir ($ file ) && !is_link ($ file )) {
211+ $ this ->chgrp (new \FilesystemIterator ($ file ), $ group , true );
212+ }
213+ if (is_link ($ file ) && function_exists ('lchgrp ' )) {
214+ if (true !== @lchgrp ($ file , $ group )) {
215+ throw new Exception \IOException (sprintf ('Failed to chgrp file %s ' , $ file ));
216+ }
217+ } else {
218+ if (true !== @chgrp ($ file , $ group )) {
219+ throw new Exception \IOException (sprintf ('Failed to chgrp file %s ' , $ file ));
220+ }
221+ }
139222 }
140223 }
141224
@@ -145,18 +228,18 @@ public function chmod($files, $mode, $umask = 0000)
145228 * @param string $origin The origin filename
146229 * @param string $target The new filename
147230 *
148- * @throws \RuntimeException When target file already exists
149- * @throws \RuntimeException When origin cannot be renamed
231+ * @throws Exception\IOException When target file already exists
232+ * @throws Exception\IOException When origin cannot be renamed
150233 */
151234 public function rename ($ origin , $ target )
152235 {
153236 // we check that target does not exist
154237 if (is_readable ($ target )) {
155- throw new \ RuntimeException (sprintf ('Cannot rename because the target "%s" already exist. ' , $ target ));
238+ throw new Exception \ IOException (sprintf ('Cannot rename because the target "%s" already exist. ' , $ target ));
156239 }
157240
158- if (false = == @rename ($ origin , $ target )) {
159- throw new \ RuntimeException (sprintf ('Cannot rename "%s" to "%s". ' , $ origin , $ target ));
241+ if (true ! == @rename ($ origin , $ target )) {
242+ throw new Exception \ IOException (sprintf ('Cannot rename "%s" to "%s". ' , $ origin , $ target ));
160243 }
161244 }
162245
@@ -166,6 +249,8 @@ public function rename($origin, $target)
166249 * @param string $originDir The origin directory path
167250 * @param string $targetDir The symbolic link name
168251 * @param Boolean $copyOnWindows Whether to copy files if on Windows
252+ *
253+ * @throws Exception\IOException When symlink fails
169254 */
170255 public function symlink ($ originDir , $ targetDir , $ copyOnWindows = false )
171256 {
@@ -180,14 +265,16 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)
180265 $ ok = false ;
181266 if (is_link ($ targetDir )) {
182267 if (readlink ($ targetDir ) != $ originDir ) {
183- unlink ($ targetDir );
268+ $ this -> remove ($ targetDir );
184269 } else {
185270 $ ok = true ;
186271 }
187272 }
188273
189274 if (!$ ok ) {
190- symlink ($ originDir , $ targetDir );
275+ if (true !== @symlink ($ originDir , $ targetDir )) {
276+ throw new Exception \IOException (sprintf ('Failed to create symbolic link from %s to %s ' , $ originDir , $ targetDir ));
277+ }
191278 }
192279 }
193280
@@ -235,7 +322,7 @@ public function makePathRelative($endPath, $startPath)
235322 * - $options['override'] Whether to override an existing file on copy or not (see copy())
236323 * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
237324 *
238- * @throws \RuntimeException When file type is unknown
325+ * @throws Exception\IOException When file type is unknown
239326 */
240327 public function mirror ($ originDir , $ targetDir , \Traversable $ iterator = null , $ options = array ())
241328 {
@@ -262,7 +349,7 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o
262349 } elseif (is_file ($ file ) || ($ copyOnWindows && is_link ($ file ))) {
263350 $ this ->copy ($ file , $ target , isset ($ options ['override ' ]) ? $ options ['override ' ] : false );
264351 } else {
265- throw new \ RuntimeException (sprintf ('Unable to guess "%s" file type. ' , $ file ));
352+ throw new Exception \ IOException (sprintf ('Unable to guess "%s" file type. ' , $ file ));
266353 }
267354 }
268355 }
0 commit comments