Mercurial > octave
changeset 20836:ce8c465aa6a4
fileattrib.m: Overhaul file for greater Windows and Matlab compatibility.
Add support for Windows attributes like Hidden, System when running on Windows.
Return NaN for unsupported group and other permission bits on Windows.
* fileattrib.m: Improve docstring. Use default argument in function header to
simplify input validation. Move input validation to top of function. Directly
build struct array for output rather than creating cell arrays and then calling
struct() at end of function. Call system command 'attrib' on Windows platforms
to get special attributes. Add BIST tests.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 09 Dec 2015 15:43:37 -0800 |
parents | 14cd86258b3d |
children | c54ae1fb7e3b |
files | scripts/miscellaneous/fileattrib.m |
diffstat | 1 files changed, 92 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/miscellaneous/fileattrib.m Wed Dec 09 16:35:12 2015 -0500 +++ b/scripts/miscellaneous/fileattrib.m Wed Dec 09 15:43:37 2015 -0800 @@ -17,7 +17,9 @@ ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {[@var{status}, @var{result}, @var{msgid}] =} fileattrib (@var{file}) +## @deftypefn {Function File} {} fileattrib () +## @deftypefnx {Function File} {} fileattrib (@var{file}) +## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} fileattrib (@var{file}) ## Return information about @var{file}. ## ## If successful, @var{status} is 1, with @var{result} containing a structure @@ -65,78 +67,108 @@ ## @seealso{glob} ## @end deftypefn -function [status, msg, msgid] = fileattrib (file) +function [status, msg, msgid] = fileattrib (file = ".") + + if (nargin > 1) + print_usage (); + endif + + if (! ischar (file)) + error ("fileattrib: FILE must be a string"); + endif status = true; msg = ""; msgid = ""; - if (nargin == 0) - file = "."; + files = glob (file); + if (isempty (files)) + files = {file}; endif + nfiles = numel (files); + + for i = [nfiles, 1:nfiles-1] # first time in loop extends the struct array + [info, err, msg] = stat (files{i}); + if (! err) + r(i).Name = canonicalize_file_name (files{i}); - if (ischar (file)) - files = glob (file); - if (isempty (files)) - files = {file}; - nfiles = 1; - else - nfiles = length (files); - endif - else - error ("fileattrib: FILE must be a string"); - endif + if (isunix ()) + r(i).archive = NaN; + r(i).system = NaN; + r(i).hidden = NaN; + else + [~, attrib] = dos (sprintf ('attrib "%s"', r(i).Name)); + ## dos() never returns error status so have to check it indirectly + if (length (attrib) < 12 + || ! strcmp (deblank (attrib(12:end)), r(i).Name)) + status = false; + msgid = "fileattrib"; + break; + endif + attrib = attrib(1:11); + r(i).archive = any (attrib == "A"); + r(i).system = any (attrib == "S"); + r(i).hidden = any (attrib == "H"); + endif - if (nargin == 0 || nargin == 1) - - r_n = r_a = r_s = r_h = r_d ... - = r_u_r = r_u_w = r_u_x ... - = r_g_r = r_g_w = r_g_x ... - = r_o_r = r_o_w = r_o_x = cell (nfiles, 1); - - curr_dir = pwd (); + r(i).directory = S_ISDIR (info.mode); - for i = 1:nfiles - [info, err, msg] = stat (files{i}); - if (! err) - r_n{i} = canonicalize_file_name (files{i}); - r_a{i} = NaN; - r_s{i} = NaN; - r_h{i} = NaN; - r_d{i} = S_ISDIR (info.mode); - ## FIXME: Maybe we should have S_IRUSR etc. masks? - modestr = info.modestr; - r_u_r{i} = modestr(2) == "r"; - r_u_w{i} = modestr(3) == "w"; - r_u_x{i} = modestr(4) == "x"; - r_g_r{i} = modestr(5) == "r"; - r_g_w{i} = modestr(6) == "w"; - r_g_x{i} = modestr(7) == "x"; - r_o_r{i} = modestr(8) == "r"; - r_o_w{i} = modestr(9) == "w"; - r_o_x{i} = modestr(10) == "x"; + modestr = info.modestr; + r(i).UserRead = (modestr(2) == "r"); + r(i).UserWrite = (modestr(3) == "w"); + r(i).UserExecute = (modestr(4) == "x"); + if (isunix ()) + r(i).GroupRead = (modestr(5) == "r"); + r(i).GroupWrite = (modestr(6) == "w"); + r(i).GroupExecute = (modestr(7) == "x"); + r(i).OtherRead = (modestr(8) == "r"); + r(i).OtherWrite = (modestr(9) == "w"); + r(i).OtherExecute = (modestr(10) == "x"); else - status = false; - msgid = "fileattrib"; - break; + r(i).GroupRead = NaN; + r(i).GroupWrite = NaN; + r(i).GroupExecute = NaN; + r(i).OtherRead = NaN; + r(i).OtherWrite = NaN; + r(i).OtherExecute = NaN; endif - endfor - if (status) - r = struct ("Name", r_n, "archive", r_a, "system", r_s, - "hidden", r_s, "directory", r_d, "UserRead", r_u_r, - "UserWrite", r_u_w, "UserExecute", r_u_x, - "GroupRead", r_g_r, "GroupWrite", r_g_w, - "GroupExecute", r_g_x, "OtherRead", r_o_r, - "OtherWrite", r_o_w, "OtherExecute", r_o_x); - if (nargout == 0) - status = r; - else - msg = r; - endif + else + status = false; + msgid = "fileattrib"; + break; endif - else - print_usage (); + endfor + + if (status) + if (nargout == 0) + status = r; + else + msg = r; + endif endif endfunction + +%!test +%! [status, attr] = fileattrib (P_tmpdir ()); +%! assert (status); +%! assert (isstruct (attr)); +%! assert (numel (fieldnames (attr)), 14); +%! assert (attr.Name, P_tmpdir ()); +%! assert (attr.directory); +%! if (ispc ()) +%! assert (! isnan (attr.archive)); +%! else +%! assert (isnan (attr.archive)); +%! endif +%! assert (attr.UserRead); +%! if (ispc ()) +%! assert (isnan (attr.GroupRead)); +%! else +%! assert (! isnan (attr.GroupRead)); +%! endif + +%!error fileattrib (1, 2) +%!error <FILE must be a string> fileattrib (1) +