ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/FileUtils.ycp

/**
 * File:        modules/FileUtils.ycp
 * Package:     YaST2
 * Authors:     Lukas Ocilka <lukas.ocilka@suse.cz>
 * Summary:     Module for getting information about files and directories.
 *		Their types and sizes and functions for checking, creating and
 *		removing them.
 * Flags:	Stable
 *
 * $Id: FileUtils.ycp 60264 2010-01-07 13:27:45Z kmachalkova $
 */
{
    module "FileUtils";
    
    textdomain "base";

    import "SCR";
    import "Popup";
    import "String";

    list <string> tmpfiles = [];

    /**
     * Function which determines if the requested file/directory exists.
     *
     * @return	true if exists
     * @param	string file name
     *
     * @example
     *	FileUtils::Exists ("/tmp") -> true
     *	FileUtils::Exists ("/tmp/somefile") -> false
     */
    global define boolean Exists (string target) {
	map info = (map) SCR::Read(.target.stat, target);

	if (info != $[]) {
	    return true;
	}
	return false;
    }

    /**
     * Function which determines if the requested file/directory is a directory
     * or it is a link to a directory.
     *
     * @return	true if it is a directory, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::IsDirectory ("/var") -> true
     *	FileUtils::IsDirectory ("/var/log/messages") -> false
     *	FileUtils::IsDirectory ("/does-not-exist") -> nil
     */
    global define boolean IsDirectory (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["isdir"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is a regular file
     * or it is a link to a regular file.
     *
     * @return	true if it is a regular file, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::IsFile ("/var") -> false
     *	FileUtils::IsFile ("/var/log/messages") -> true
     *	FileUtils::IsFile ("/does-not-exist") -> nil
     */
    global define boolean IsFile (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["isreg"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is a block file (device)
     * or link to a block device.
     *
     * @return	true if it is a block file, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::IsBlock ("/var") -> false
     *	FileUtils::IsBlock ("/dev/sda2") -> true
     *	FileUtils::IsBlock ("/dev/does-not-exist") -> nil
     */
    global define boolean IsBlock (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["isblock"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is a fifo
     * or link to a fifo.
     *
     * @return	true if it is a fifo, nil if doesn't exist
     * @param	string file name
     */
    global define boolean IsFifo (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["isfifo"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is a link.
     *
     * @return	true if it is a link, nil if doesn't exist
     * @param	string file name
     */
    global define boolean IsLink (string target) {
	map info = (map) SCR::Read(.target.lstat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["islink"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is a socket
     * or link to a socket.
     *
     * @return	true if it is a socket, nil if doesn't exist
     * @param	string file name
     */
    global define boolean IsSocket (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["issock"]:defaultv;
    }

    /**
     * Function which determines if the requested file/directory is
     * a character device or link to a character device.
     *
     * @return	true if it is a charcater device, nil if doesn't exist
     * @param	string file name
     */
    global define boolean IsCharacterDevice (string target) {
	map info = (map) SCR::Read(.target.stat, target);
	boolean defaultv = (info != $[] ? false:nil);

	return (boolean) info["ischr"]:defaultv;
    }

    /**
     * Function returns the real type of requested file/directory.
     * If the file is a link to any object, "link" is returned.
     *
     * @return	string file type (directory|regular|block|fifo|link|socket|chr_device), nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::GetFileRealType ("/var") -> "directory"
     *	FileUtils::GetFileRealType ("/etc/passwd") -> "file"
     *	FileUtils::GetFileRealType ("/does-not-exist") -> nil
     */
    global define string GetFileRealType (string target) {
	map info = (map) SCR::Read(.target.lstat, target);

	if (info["islink"]:false == true) {
	    return "link";
	} else if (info["isdir"]:false == true) {
	    return "directory";
	} else if (info["isreg"]:false == true) {
	    return "regular";
	} else if (info["isblock"]:false == true) {
	    return "block";
	} else if (info["isfifo"]:false == true) {
	    return "fifo";
	} else if (info["issock"]:false == true) {
	    return "socket";
	} else if (info["ischr"]:false == true) {
	    return "chr_device";
	} else {
	    return nil;
	}
    }

    /**
     * Function returns the type of requested file/directory.
     * If the file is a link to any object, the object's type is returned.
     *
     * @return	string fle type (directory|regular|block|fifo|link|socket|chr_device), nil if doesn't exist
     * @param	string file name
     */
    global define string GetFileType (string target) {
	map info = (map) SCR::Read(.target.stat, target);

	
	if (info["isdir"]:false == true) {
	    return "directory";
	} else if (info["isreg"]:false == true) {
	    return "regular";
	} else if (info["isblock"]:false == true) {
	    return "block";
	} else if (info["isfifo"]:false == true) {
	    return "fifo";
	} else if (info["issock"]:false == true) {
	    return "socket";
	} else if (info["islink"]:false == true) {
	    return "link";
	} else if (info["ischr"]:false == true) {
	    return "chr_device";
	} else {
	    return nil;
	}
    }

    /**
     * Function which returns the size of requested file/directory.
     *
     * @return	integer file size, -1 if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::GetSize ("/var/log/YaST2") -> 12348
     *	FileUtils::GetSize ("/does-not-exist") -> -1
     */
    global define integer GetSize (string target) {
	return (integer) SCR::Read(.target.size, target);
    }

    /**
     * Function which determines the owner's user ID of requested file/directory.
     *
     * @return	integer UID, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::GetOwnerUserID ("/etc/passwd") -> 0
     *	FileUtils::GetOwnerUserID ("/does-not-exist") -> nil
     */
    global define integer GetOwnerUserID (string target) {
	map info = (map) SCR::Read(.target.stat, target);

	return (integer) info["uid"]:nil;
    }

    /**
     * Function which determines the owner's group ID of requested file/directory.
     *
     * @return	integer GID, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::GetOwnerGroupID ("/etc/passwd") -> 0
     *	FileUtils::GetOwnerGroupID ("/does-not-exist") -> nil
     */
    global define integer GetOwnerGroupID (string target) {
	map info = (map) SCR::Read(.target.stat, target);

	return (integer) info["gid"]:nil;
    }


    /**
     * Checks whether the path (directory) exists and return a boolean
     * value whether everything is OK or user accepted the behavior as
     * despite some errors. If the directory doesn't exist, it offers
     * to create it (and eventually creates it).
     *
     * @param string pathvalue (directory)
     * @return boolean whether everything was OK or whether user decided to ignore eventual errors
     *
     * @unstable
     */
    global define boolean CheckAndCreatePath (string pathvalue) {
        string check_path = pathvalue;

        // remove the final slash
	// but never the last one "/"
	// bugzilla #203363
        if (regexpmatch (check_path, "/$") && check_path != "/")
	    check_path = regexpsub (check_path, "^(.*)/$", "\\1");
        y2milestone("Checking existency of %1 path", check_path);

        // Directory (path) already exists
        if (FileUtils::Exists(check_path)) {
            y2milestone("Path %1 exists", check_path);
            // Directory (path) is a type 'directory'
            if (FileUtils::IsDirectory(check_path)) {
                return true;
            // Directory (path) is not a valid 'directory'
            } else {
                y2warning ("Path %1 is not a directory", check_path);
                // Continue despite the error?
                return Popup::ContinueCancel(sformat(
                    // TRANSLATORS: popup question (with continue / cancel buttons)
                    // %1 is the filesystem path
                    _("Although the path %1 exists, it is not a directory.
Continue or cancel the operation?
"),
                    pathvalue
                ));
            }
        // Directory (path) doesn't exist, trying to create it if wanted
        } else {
    	    y2milestone("Path %1 does not exist", check_path);
            if (Popup::YesNo(sformat(
    		// TRANSLATORS: question popup (with yes / no buttons). A user entered non-existent path
		// for a share, %1 is entered path
		_("The path %1 does not exist.
Create it now?
"),
        	pathvalue
	    ))) {
        	// Directory creation successful
        	if ((boolean) SCR::Execute(.target.mkdir, check_path)) {
		    y2milestone("Directory %1 successfully created", check_path);
            	return true;
        	// Failed to create the directory
        	} else {
            	    y2warning("Failed to create directory %1", check_path);
            	    // Continue despite the error?
            	    return Popup::ContinueCancel(sformat(
                	// TRANSLATORS: popup question (with continue / cancel buttons)
                	// %1 is the name (path) of the directory
                	_("Failed to create the directory %1.
Continue or cancel the current operation?
"),
                	pathvalue
        	    ));
        	}
	    // User doesn't want to create the directory
    	    } else {
        	y2warning("User doesn't want to create the directory %1", check_path);
        	return true;
    	    }
	}
    }

    /**
     * Function return the MD5 sum of the file.
     *
     * @return	string MD5 sum of the file, nil if doesn't exist
     * @param	string file name
     *
     * @example
     *	FileUtils::MD5sum ("/etc/passwd") -> "74855f6ac9bf728fccec4792d1dba828"
     *	FileUtils::MD5sum ("/does-not-exist") -> nil
     */
    global string MD5sum (string target) {
	if (! Exists(target)) {
	    y2error ("File %1 doesn't exist", target);
	    return nil;
	}

	if (! IsFile(target)) {
	    y2error ("Not a file %1", target);
	    return nil;
	}

	string cmd = sformat ("md5sum '%1'", String::Quote (target));
	map cmd_out = (map) SCR::Execute (.target.bash_output, cmd);

	if (cmd_out["exit"]:-1 != 0) {
	    y2error ("Command >%1< returned %2", cmd, cmd_out);
	    return nil;
	}

	string filemd5 = cmd_out["stdout"]:"";
	if (regexpmatch (filemd5, "[^ \t]+[ \t]+.*$")) {
	    // Format: '19ea7ea41de37314f71c6849ddd259d5 /the/file'
	    filemd5 = regexpsub (filemd5, "^([^ \t]+)[ \t]+.*$", "\\1");
	} else {
	    y2warning ("Strange md5out: '%1'", filemd5);
	    return nil;
	}

	return filemd5;
    }

    /**
     * Changes ownership of a file/directory
     *
     * @return	boolean true if succeeded
     * @param	string user and group name (in the form 'user:group')
     * @param	string file name
     * @param	boolean recursive, true if file (2nd param) is a directory
     *
     * @example
     *	FileUtils::Chown ( "somebody:somegroup", "/etc/passwd", false) -> 'chown somebody:somegroup /etc/passwd'
     *	FileUtils::Chown ( "nobody:nogroup", "/tmp", true) -> 'chown nobody:nogroup -R /tmp'
     */

    global boolean Chown( string usergroup, string file, boolean recursive)
    {
        y2milestone("Setting ownership of file %1 to %2", file, usergroup);

        string cmd = sformat("chown %1 %2 %3", usergroup, (recursive ? "-R" : "" ), file);

        integer retval = (integer) SCR::Execute(.target.bash, cmd);

        if( retval != 0)
            y2error("Cannot chown %1", file);

        return (retval == 0);
    }

    /**
     * Changes access rights to a file/directory
     *
     * @return	boolean true if succeeded
     * @param	string modes ( e.g. '744' or 'u+x')
     * @param	string file name
     * @param	boolean recursive, true if file (2nd param) is a directory
     *
     * @example
     *	FileUtils::Chmod ( "go-rwx", "/etc/passwd", false) -> 'chmod go-rwx /etc/passwd'
     *	FileUtils::Chmod ( "700", "/tmp", true) -> 'chmod 700 -R /tmp'
     */

    global boolean Chmod (string modes, string file, boolean recursive)
    {
        y2milestone("Setting access rights of file %1 to %2", file, modes);

        string cmd = sformat("chmod %1 %2 %3", modes, (recursive ? "-R" : "" ), file);

        integer retval = (integer) SCR::Execute(.target.bash, cmd);

        if( retval != 0)
            y2error("Cannot chmod %1", file);

        return (retval == 0);

    }

    string MkTempInternal (string template, string usergroup, string modes, boolean directory)
    {
        string mktemp = sformat("/bin/mktemp %1 %2", 
			(directory ? "-d" : ""), template);

        map cmd_out = (map) SCR::Execute (.target.bash_output, mktemp);
	    if (cmd_out["exit"]:-1 != 0) {
	    y2error ("Error creating temporary file: %1", cmd_out);
	    return nil;
        }

        string tmpfile = splitstring (cmd_out["stdout"]:"", "\n")[0]:"";

        if (tmpfile == nil || tmpfile == "") {
	    y2error ("Error creating temporary file: %1 - empty output", cmd_out);
	    return nil;
        }

        if( !Chown( usergroup, tmpfile, directory) || !Chmod( modes, tmpfile, directory)) {
	    return nil;
        }

        tmpfiles = add(tmpfiles, tmpfile);
        return tmpfile;
    }

    /**
     * Creates temporary file
     *
     * @return	string resulting file name or nil on failure
     * @param	string template for file name e.g. 'tmp.XXXX'
     * @param	string tmp file owner in a form 'user:group' 
     * @param	string tmp file access rights
     *
     * @example
     *	FileUtils::MkTempFile ( "/tmp/tmpfile.XXXX", "somebody:somegroup", "744")
     */

    global string MkTempFile (string template, string usergroup, string modes)
    {
        return MkTempInternal( template, usergroup, modes, false );
    }

    /**
     * The same as MkTempFile, for directories ('mktemp -d ... '). See above
     *
     * @example
     *	FileUtils::MkTempDirectory ( "/tmp/tmpdir.XXXX", "nobody:nogroup", "go+x") 
     */
    global string MkTempDirectory (string template, string usergroup, string modes)
    {
        return MkTempInternal( template, usergroup, modes, true );
    }

    /**
     * Removes files and dirs created in all previous calls to MkTemp[File|Directory]
     *
     */
    global void CleanupTemp()
    {
        foreach (string one_file, tmpfiles, {
	    y2milestone("Removing %1", one_file);
	    SCR::Execute (.target.bash, sformat ("/bin/rm -rf '%1'", one_file));
        });
    }

/* EOF */
}

ACC SHELL 2018