[mercury-users] io.m, directory listing

Paul Massey pma at miscrit.be
Wed Oct 6 18:01:55 AEST 1999


Hello,

Don't know if this will help, but here's something similar I knocked
up quite a while ago ...

Paul.

%------------------------------------------------------------------
% Author : P.A, Massey (MC)
% Date   : 1999
% Purpose: An incomplete set of routines for listing directories, 
%          file properties, etc.

:- module files.
:- interface.
:- import_module io.
:- import_module string.
:- import_module list.
:- import_module bool.

:- type files__res(T) --->
		  ok(T)
		; error(string).

:- type files__dir.

:- type files__properties.

:- type files__sortform --->
             modification
           ; access
           ; name
           ; size.

:- type files__sort --->
             sort(files__sortform)
           ; unsorted.

	% returns a list of all the files found in directory Arg1 (unsorted).
:- pred files__dirlist(string,files__res(list(string)),io__state,io__state).
:- mode files__dirlist(in,out,di,uo) is det.

	% as above except that the resulting list can be sorted in some
        % way or other.
:- pred files__dirlist(string,files__sort,files__res(list(string)),
                       io__state,io__state).
:- mode files__dirlist(in,in,out,di,uo) is det.

	% As above except that the properties list is returned.
:- pred files__dirlist_properties(string,files__sort,files__res(list(properties)),
                       io__state,io__state).
:- mode files__dirlist_properties(in,in,out,di,uo) is det.

	% recovers the property list for a list of files.
:- pred files__properties(list(string),list(properties),io__state,io__state).
:- mode files__properties(in,out,di,uo) is det.

	% Same as above except that the directory name is provided.
:- pred files__properties(string,list(string),list(properties),
		          io__state,io__state).
:- mode files__properties(in,in,out,di,uo) is det.

	% Recovers the various file properties associated with 
        % each file entry.

:- pred files__properties_get_access(files__properties::in,string::out)is det.
:- pred files__properties_get_mod(files__properties::in,string::out)is det.
:- pred files__properties_get_filename(files__properties::in,
				       string::out)is det.
:- pred files__properties_get_size(files__properties::in,int::out)is det.

	% Create a directory.
:- pred files__mkdir(string,files__res(bool),io__state,io__state).
:- mode files__mkdir(in,out,di,uo) is det.

%---------------------------------------------------------------------
:- implementation.
%---------------------------------------------------------------------

:- type files__properties --->
		property(string,string,string,string,int).

:- type files__dir == c_pointer.

:- pragma(c_header_code, "
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#ifdef UNIX
#include <sys/socket.h>
#else
#endif
#include <sys/stat.h>
#include <sys/dirent.h>
#include <time.h>

struct dirent *dp;

#define update_io(r_src, r_dest)	((r_dest) = (r_src))
").

files__dirlist(Directory, SortedForm, Results) -->
	files__dirlist_properties(Directory, SortedForm, PropertiesOk),
	( { PropertiesOk = ok(In) } ->
	      { list__map(files__properties_get_filename,In,Out) },
	      { Results = ok(Out) }
        ; { PropertiesOk = error(Msg) } ->
	      { Results = error(Msg) }
	;     { Results = error("files__dirlist/5: unknown return type") } ).

files__dirlist(Directory, Results) -->
       files__dirlist(Directory, unsorted, Results).

files__dirlist_properties(Directory, SortedForm, Results) -->
	opendir(Directory, DirPointer),
	( { is_null(DirPointer) } ->
		{Results = error("couldn't open file")}
	;	readfiles(Directory,DirPointer,FileProperties),
	        { files__sort(SortedForm,FileProperties,ResultsList) },
		{ Results = ok(ResultsList) },
		closedir(DirPointer)).

%--------------------------------------------------------
% Sorts the resulting file list as required.

:- pred files__sort(files__sort,list(properties),list(properties)).
:- mode files__sort(in,in,out) is det.

files__sort(unsorted, In, In).
files__sort(sort(_), In, Out):-
       list__sort(lambda([X::in,Y::in,CR::out] is det,
		     (files__properties_get_mod(X,M1),
		      files__properties_get_mod(Y,M2),
		      compare(CR,M1,M2))),In,Out0),
       list__reverse(Out0,Out).

%--------------------------------------------------------
% convert the list of filenames, into a list of property 
% structures.

files__properties(Files,Properties) -->
	files__properties(".",Files,Properties).

files__properties(_DirName,[], [], I, I).
files__properties(DirName,[FileName|Rest],[Property|Rem]) -->
	files__get_properties(DirName,FileName,Property),
	files__properties(DirName,Rest, Rem).

:- pred files__get_properties(string,string,properties,io__state,io__state). 
:- mode files__get_properties(in,in,out,di,uo) is det.

files__get_properties(DirName,FileName,Properties) -->
%	io__format("files__get_properties(%s,%s)\n",[s(DirName),s(FileName)]),
        { string__append_list([DirName,"/",FileName],FFileName) },
        get_times(FFileName,Acc,Mod,Size),
	{ Properties = property(DirName,FileName,Acc,Mod,Size) }.
	
:- pred get_times(string,string,string,int,io__state,io__state).
:- mode get_times(in,out,out,out,di,uo) is det.

:- pragma(c_code, get_times(File::in,Acc::out,Mod::out,Size::out,
                            II0::di,IO::uo),"
	Word tmp;
	struct stat sb;
	if (stat(File,&sb) == 0) {
	    int sz;
	    sz = (21+sizeof(Word))/sizeof(Word);
	    incr_hp_atomic(tmp,sz);
	    strftime((char *)tmp,21,\"%Y:%m:%d %H:%M:%S\",gmtime(&(sb.st_atime)));
	    Acc = (char *) tmp;
	    incr_hp_atomic(tmp,sz);
	    strftime((char *)tmp,21,\"%Y:%m:%d %H:%M:%S\",gmtime(&(sb.st_mtime)));
	    Mod = (char *) tmp;
            Size = (Word) sb.st_size;
            }
	else { Mod = NULL; Acc = NULL; Size = 0;};
	update_io(II0, IO);
	").

files__properties_get_access(property(_D,_,A,_,_),A).
files__properties_get_mod(property(_D,_,_,M,_),M).
files__properties_get_filename(property(_D,F,_,_,_),F).
files__properties_get_size(property(_,_,_,_,Size),Size).

:- pred readfiles(string,files__dir,list(properties),io__state,io__state).
:- mode readfiles(in,in,out,di,uo) is det.

readfiles(Directory,DirPointer, List) -->
	readdir_filename(DirPointer, Entry),
	( { Entry = "" } ->
		{ List = [] }
	; { Entry = "." } ->
		readfiles(Directory,DirPointer, List) 
	; { Entry = ".." } ->
		readfiles(Directory,DirPointer,List) 
	; 	files__get_properties(Directory,Entry,Properties),
	        { List = [Properties|Next] },
		readfiles(Directory, DirPointer, Next) ).

:- pred readdir_filename(files__dir,string,io__state,io__state).
:- mode readdir_filename(in,out,di,uo) is det.
:- pragma(c_code, readdir_filename(DirP::in,FileName::out,II0::di,IO::uo),"
	Word tmp;
	dp = readdir((DIR *)DirP);
	if (dp == (struct dirent *)NULL) {
	    incr_hp_atomic(tmp,(1+sizeof(Word))/sizeof(Word));
	    strcpy((char *)tmp,\"\");
	    FileName = (char *)tmp; }
	else {
	    incr_hp_atomic(tmp,(strlen(dp->d_name)+sizeof(Word))/sizeof(Word));
	    strcpy((char *)tmp,dp->d_name);
	    FileName = (char *)tmp;
	};
	update_io(II0, IO);
	").

:- pred opendir(string::in,files__dir::out,io__state::di,io__state::uo)is det.
:- pragma(c_code, opendir(DirName::in,Dirp::out,IO0::di,IO::uo),"
	Dirp = opendir(DirName);
	update_io(IO0,IO);").

:- pred closedir(files__dir::in,io__state::di,io__state::uo) is det.
:- pragma(c_code, closedir(Dir::in,IO0::di,IO::uo), "{
	(void)closedir((DIR *)Dir);
	update_io(IO0, IO);};").

:- pred is_null(c_pointer::in) is semidet.
:- pragma(c_code, is_null(Cpointer::in), "
	SUCCESS_INDICATOR = (Cpointer == (Word *)0);").

files__mkdir(Dir,Result) -->
	cmkdir(Dir,Res),
	( { Res = 0 } ->
	     { Result = ok(yes) }
	;    { Result = error("mkdir: failed") }).

:- pred cmkdir(string::in,int::out,io__state::di,io__state::uo) is det.
:- pragma(c_code, cmkdir(Dir::in,Res::out,IO0::di,IO::uo), "{
        Res = (Word) mkdir(Dir,S_IWGRP|S_IWOTH);
        if (Res != (Word) 0) Res = (Word) errno;
	update_io(IO0, IO); }").

:- end_module files.
+--------------------------------------------------------------

--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list