Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
provision
Commits
fe8994f1
Commit
fe8994f1
authored
Mar 29, 2010
by
Neil Drumm
Browse files
rebase
parent
e567ae3a
Changes
1
Hide whitespace changes
Inline
Side-by-side
provision.path.inc
0 → 100644
View file @
fe8994f1
<?php
// $Id$
/**
* @defgroup pathhandling Managing paths, permissions and file ownership
*
* This group provides an interface to common path handling operations, through
* the provision_path helper function, which will take care of verification and
* any error logging required.
*/
/**
* Perform tasks on a path.
*
* Perform tasks on a path, and logs error messages / codes on success or failure.
* This function will call another function which defines the functionality,
* and exists to provide a consistent interface for file operations with error logging
* integration.
*
* Many of the provision_path_$op functions are really simple, but are wrapped
* in functions to provide a consistent interface for provision_path to operate
* with.
*
* @param type
* The type of operation to perform. One of the following:
* writable - The $path can be written to.
* exists - The $path exists.
* is_dir - The $path is a directory.
* readable - The $path is readable.
* owner - The $path belongs to the user in $confirm.
* group - The $path belongs to the group in $confirm.
* mkdir - Create the $path directory.
* unlink - Delete the file $path.
* symlink - Create a symlink from $path to $confirm.
* rmdir - Delete the directory $path.
* chmod - Change the file permissions of $path to the octal value in $confirm.
* chown - Change the owner of $path to the user in $confirm.
* chgrp - Change the group of $path to the group in $confirm.
* switch_paths - Move $path to $confirm, and vice versa.
*
* @param path
* The path you want to perform the file operation on.
*
* @param confirm
* Confirm that the final value of the file operation matches this value.
* This value defaults to TRUE, which is sufficient for most file operations.
*
* Certain tasks such as chmod, chown and chgp will attempt to change the
* properties of $path to match the value in $confirm, and then test that
* the change was completed succesfully afterwards.
*
* These exceptions are :
* symlink - $confirm is the path to the symlink being created
* chmod - $confirm is an octal value denoting the desired file permissions.
* chown - $confirm is the name or user id you wish to change the file ownership to.
* chgrp - $confirm is the name of group id you wish to change the file group ownership to.
* switch_paths - $confirm is the path that you want to replace the $path with.
*
* @param succeed_message
* Log this as a notice into the logging system, if the operation completed succesfully.
*
* @param fail_message
* Log this as a error to the logging system, if the $error_codes parameter has been set,
* otherwise, log this as a warning. If the operation specifies an additional reason for
* the operation failing, it will be appended to this message.
*
* @param error_codes
* Generate these system level errors using the provision error bitmasks.
*
* @return
* Returns TRUE if the test against $confirm passed, otherwise returns FALSE.
*/
function
provision_path
(
$op
,
$path
,
$confirm
=
TRUE
,
$succeed_message
=
NULL
,
$fail_message
=
NULL
,
$error_codes
=
NULL
)
{
# The code style is a bit weird here, but it's a bit easier to read this way.
$func
=
"provision_path_"
.
$op
;
if
(
function_exists
(
$func
))
{
// The reason variable is passed into the operation function, to allow the function
// to specify an additional reason as to why the operation failed.
$reason
=
''
;
$value
=
$func
(
$path
,
$confirm
,
$reason
);
clearstatcache
();
// this needs to be called, otherwise we get the old info
$tokens
=
array
(
"@path"
=>
$path
,
"@op"
=>
$op
,
"@confirm"
=>
$confirm
);
if
(
$reason
)
{
$fail_message
=
$fail_message
.
" ("
.
$reason
.
")"
;
}
$status
=
(
$value
==
$confirm
);
if
(
$status
)
{
if
(
!
is_null
(
$succeed_message
))
{
drush_log
(
dt
(
$succeed_message
,
$tokens
),
'message'
);
}
}
else
{
if
(
$error_codes
)
{
// Trigger a sysem halting error
if
(
!
is_null
(
$fail_message
))
{
drush_set_error
(
$error_codes
,
dt
(
$fail_message
,
$tokens
));
}
else
{
drush_set_error
(
$error_codes
);
}
}
else
{
// Trigger a warning
if
(
!
is_null
(
$fail_message
))
{
drush_log
(
dt
(
$fail_message
,
$tokens
),
'warning'
);
}
}
}
return
$status
;
}
}
function
provision_path_writable
(
$path
)
{
return
is_writable
(
$path
);
}
function
provision_path_exists
(
$path
)
{
return
file_exists
(
$path
);
}
function
provision_path_is_dir
(
$path
)
{
return
is_dir
(
$path
);
}
function
provision_path_readable
(
$path
)
{
return
is_readable
(
$path
);
}
function
provision_path_owner
(
$path
)
{
$info
=
posix_getpwuid
(
fileowner
(
$path
));
return
$info
[
'name'
];
}
function
provision_path_group
(
$path
)
{
return
filegroup
(
$path
);
}
function
provision_path_mkdir
(
$path
)
{
return
mkdir
(
$path
,
0770
,
TRUE
);
}
function
provision_path_rmdir
(
$path
)
{
return
rmdir
(
$path
);
}
function
provision_path_unlink
(
$path
)
{
return
unlink
(
$path
);
}
/*
* This is where the more complex file operations start
*/
function
provision_path_chmod
(
$path
,
&
$perms
,
&
$reason
,
$recursive
=
FALSE
)
{
$func
=
(
$recursive
)
?
'_provision_chmod_recursive'
:
'chmod'
;
if
(
!@
$func
(
$path
,
$perms
))
{
$reason
=
dt
(
'chmod to @perm failed on @path'
,
array
(
'@perm'
=>
sprintf
(
'%o'
,
$perms
),
'@path'
=>
$path
));
return
false
;
}
clearstatcache
();
// this needs to be called, otherwise we get the old info
$value
=
substr
(
sprintf
(
'%o'
,
fileperms
(
$path
)),
-
4
);
$perms
=
sprintf
(
'%04o'
,
$perms
);
return
$value
;
}
function
provision_path_chown
(
$path
,
&
$owner
,
&
$reason
,
$recursive
=
FALSE
)
{
$func
=
(
$recursive
)
?
'_provision_chown_recursive'
:
'chown'
;
if
(
$owner
=
provision_posix_username
(
$owner
))
{
if
(
!
$func
(
$path
,
$owner
))
{
$reason
=
dt
(
"chown to @owner failed on @path"
,
array
(
'@owner'
=>
$owner
,
'@path'
=>
$path
))
;
}
}
else
{
$reason
=
dt
(
"the user does not exist"
);
}
clearstatcache
();
// this needs to be called, otherwise we get the old info
return
provision_posix_username
(
fileowner
(
$path
));
}
function
provision_path_chgrp
(
$path
,
&
$gid
,
&
$reason
,
$recursive
=
FALSE
)
{
$func
=
(
$recursive
)
?
'_provision_chgrp_recursive'
:
'chgrp'
;
if
(
$group
=
provision_posix_groupname
(
$gid
))
{
if
(
provision_user_in_group
(
drush_get_option
(
'script_user'
),
$gid
))
{
if
(
$func
(
$path
,
$group
))
{
return
$group
;
}
else
{
$reason
=
dt
(
"chgrp to @group failed on @path"
,
array
(
'@group'
=>
$group
,
'@path'
=>
$path
));
}
}
else
{
$reason
=
dt
(
"@user is not in @group group"
,
array
(
"@user"
=>
drush_get_option
(
'script_user'
),
"@group"
=>
$group
));
}
}
elseif
(
!@
$func
(
$path
,
$gid
))
{
# try to change the group anyways
$reason
=
dt
(
"the group does not exist"
);
}
clearstatcache
();
// this needs to be called, otherwise we get the old info
return
provision_posix_groupname
(
filegroup
(
$path
));
}
function
provision_path_chmod_recursive
(
$path
,
&
$perms
,
&
$reason
)
{
return
provision_path_chmod
(
$path
,
$perms
,
$reason
,
TRUE
);
}
function
provision_path_chown_recursive
(
$path
,
&
$owner
,
&
$reason
)
{
return
provision_path_chown
(
$path
,
$owner
,
$reason
,
TRUE
);
}
function
provision_path_chgrp_recursive
(
$path
,
&
$gid
,
&
$reason
)
{
return
provision_path_chgrp
(
$path
,
$gid
,
$reason
,
TRUE
);
}
function
provision_path_switch_paths
(
$path1
,
&
$path2
,
&
$reason
)
{
//TODO : Add error reasons.
$temp
=
$path1
.
'.tmp'
;
if
(
!
file_exists
(
$path1
))
{
return
rename
(
$path2
,
$path1
);
}
elseif
(
!
file_exists
(
$path2
))
{
return
rename
(
$path1
,
$path2
);
}
elseif
(
rename
(
$path1
,
$temp
))
{
if
(
rename
(
$path2
,
$path1
))
{
if
(
rename
(
$temp
,
$path2
))
{
return
$path2
;
// path1 is now path2
}
else
{
// same .. just in reverse
return
rename
(
$path1
,
$path2
)
&&
rename
(
$temp
,
$path1
);
}
}
else
{
// same .. just in reverse
return
rename
(
$temp
,
$path1
);
}
}
return
FALSE
;
}
function
provision_path_extract
(
$path
,
&
$target
,
&
$reason
)
{
if
(
file_exists
(
$path
)
&&
is_readable
(
$path
))
{
if
(
is_writeable
(
dirname
(
$target
))
&&
!
file_exists
(
$target
)
&&
!
is_dir
(
$target
))
{
mkdir
(
$target
);
$oldcwd
=
getcwd
();
// we need to do this because some retarded implementations of tar (e.g. SunOS) don't support -C
chdir
(
$target
);
// same here: some do not support -z
$command
=
'gunzip -c %s | tar pxf -'
;
drush_log
(
dt
(
'Running: %command in %target'
,
array
(
'%command'
=>
sprintf
(
$command
,
$path
),
'%target'
=>
$target
)));
$result
=
provision_shell_exec
(
$command
,
$path
);
chdir
(
$oldcwd
);
if
(
$result
&&
is_writeable
(
dirname
(
$target
))
&&
is_readable
(
dirname
(
$target
))
&&
is_dir
(
$target
))
{
$target
=
TRUE
;
return
TRUE
;
}
else
{
$reason
=
dt
(
"The file could not be extracted"
);
}
}
else
{
$reason
=
dt
(
"The target directory could not be written to"
);
return
false
;
}
}
else
{
$reason
=
dt
(
"Backup file could not be opened"
);
return
false
;
}
}
function
provision_path_symlink
(
$path
,
&
$target
,
&
$reason
)
{
if
(
file_exists
(
$target
)
&&
!
is_link
(
$target
))
{
$reason
=
dt
(
"A file already exists at @path"
);
return
FALSE
;
}
if
(
is_link
(
$target
)
&&
(
readlink
(
$target
)
!=
$path
))
{
$reason
=
dt
(
"A symlink already exists at target, but it is pointing to @link"
,
array
(
"@link"
=>
readlink
(
$target
)));
return
FALSE
;
}
if
(
is_link
(
$target
)
&&
(
readlink
(
$target
)
==
$path
))
{
$target
=
TRUE
;
return
TRUE
;
}
if
(
symlink
(
$path
,
$target
))
{
$target
=
TRUE
;
return
TRUE
;
}
else
{
$reason
=
dt
(
'The symlink could not be created, an error has occured'
);
return
FALSE
;
}
}
/**
*@} end filegroup
*/
/**
* Small helper function for creation of configuration directories.
*/
function
_provision_create_dir
(
$path
,
$name
,
$perms
)
{
$exists
=
provision_path
(
"exists"
,
$path
,
TRUE
,
$name
.
' '
.
dt
(
"path exists."
),
$name
.
' '
.
dt
(
"path does not exist."
)
);
if
(
!
$exists
)
{
$exists
=
provision_path
(
"mkdir"
,
$path
,
TRUE
,
$name
.
' '
.
dt
(
"path has been created."
),
$name
.
' '
.
dt
(
"path could not be created."
),
'DRUSH_PERM_ERROR'
);
}
if
(
$exists
)
{
provision_path
(
"chown"
,
$path
,
drush_get_option
(
'script_user'
),
$name
.
' '
.
dt
(
"ownership of path has been changed to @confirm."
),
$name
.
' '
.
dt
(
"ownership of path could not be changed to @confirm."
),
'DRUSH_PERM_ERROR'
);
provision_path
(
"chmod"
,
$path
,
$perms
,
$name
.
' '
.
dt
(
"permissions of path have been changed to @confirm."
),
$name
.
' '
.
dt
(
"permissions of path could not be changed to @confirm."
),
'DRUSH_PERM_ERROR'
);
$writable
=
provision_path
(
"writable"
,
$path
,
TRUE
,
$name
.
' '
.
dt
(
"path is writable."
),
$name
.
' '
.
dt
(
"path is not writable."
),
'DRUSH_PERM_ERROR'
);
}
return
(
$exists
&&
$writable
);
}
/**
* Walk the given tree recursively (depth first), calling a function on each file
*
* $func is not checked for existence and called directly with $path and $arg
* for every file encountered.
*
* @param string $func a valid callback, usually chmod, chown or chgrp
* @param string $path a path in the filesystem
* @param string $arg the second argument to $func
* @return boolean returns TRUE if every $func call returns true
*/
function
_provision_call_recursive
(
$func
,
$path
,
$arg
)
{
$status
=
1
;
// do not follow symlinks as it could lead to a DOS attack
// consider someone creating a symlink from files/foo to ..: it would create an infinite loop
if
(
!
is_link
(
$path
)
&&
(
$dh
=
@
opendir
(
$path
)))
{
while
((
$file
=
readdir
(
$dh
))
!==
false
)
{
if
(
$file
!=
'.'
&&
$file
!=
'..'
)
{
$status
=
_provision_call_recursive
(
$func
,
$path
.
"/"
.
$file
,
$arg
)
&&
$status
;
}
}
closedir
(
$dh
);
}
$status
=
$func
(
$path
,
$arg
)
&&
$status
;
return
$status
;
}
/**
* Chmod a directory recursively
*
*/
function
_provision_chmod_recursive
(
$path
,
$filemode
)
{
return
_provision_call_recursive
(
"chmod"
,
$path
,
$filemode
);
}
/**
* Chown a directory recursively
*/
function
_provision_chown_recursive
(
$path
,
$owner
)
{
return
_provision_call_recursive
(
"chown"
,
$path
,
$owner
);
}
/**
* Chgrp a directory recursively
*/
function
_provision_chgrp_recursive
(
$path
,
$owner
)
{
return
_provision_call_recursive
(
"chgrp"
,
$path
,
$owner
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment