/***************************************************************************
 *   Copyright (C) 2005 by Reel Multimedia                                 *
 *                                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "stringtools.h"
#include "filetools.h"

#include <sys/stat.h>
#include <sys/types.h> 
#include <dirent.h>
#include <errno.h>

namespace Filetools
{
    bool MyS_IFLNK(mode_t mode)
    {
        bool val = (mode & S_IFMT) == S_IFLNK;
        return val;
    }

    bool IsFile(const std::string &entry)
    {
        struct stat64 statBuf;
        stat64(entry.c_str(), &statBuf);
        if(S_ISREG(statBuf.st_mode)) //regular file
        {
            return true;
        }
        return false;
    }

    bool IsDir(const std::string &entry)
    {
        struct stat64 statBuf;
        stat64(entry.c_str(), &statBuf);
        if(S_ISDIR(statBuf.st_mode)) //regular file
        {
            return true;
        }
        return false; 
    }

    long long GetFileSize(const std::string &file)
    {
        struct stat64 statBuf;
        stat64(file.c_str(), &statBuf);
        if(S_ISREG(statBuf.st_mode)) //regular file
        {
            return statBuf.st_size;
        }
        return 0;
    }

    int GetRights(std::string filename, mode_t &mode)
    {
        struct stat64 statBuf;
        int ret = stat64(filename.c_str(), &statBuf);
        mode = statBuf.st_mode;
        return ret;
    }

    int SetRights(std::string filename, mode_t mode)
    {
        return chmod(filename.c_str(), mode);
    }

    int GetOwner(std::string filename, uid_t &owner, gid_t &group)
    {
        struct stat64 statBuf;
        int ret = stat64(filename.c_str(), &statBuf);
        owner = statBuf.st_uid;
        group = statBuf.st_gid;
        return ret;
    }

    int SetOwner(std::string filename, uid_t owner, gid_t group)
    {
        return chown(filename.c_str(), owner, group);
    }

    bool FileExists(const std::string &file)
    {
        FILE *fd = fopen64(file.c_str(), "r");
        if(fd)
        { 
            fclose(fd);
            return true;
        }
        return false;
    }

    bool DirExists(const std::string &dir)
    {
        if (opendir(dir.c_str()) == NULL && errno == ENOENT) 
        { 
            return false;
        }
        return true;
    }

    bool GetDirEntries(const std::string &dir, std::vector<std::string>  &entries)
    {
        DIR *dirp;
        struct dirent64 *dp; 

        if ((dirp = opendir(dir.c_str())) == NULL) 
        {
            printf("couldn't open %s\n", dir.c_str()); 
            return false;
        }

        while((dp = readdir64(dirp)) != NULL)
        {
            std::string name = dir + "/" + dp->d_name;
            entries.push_back(name);
        }
        closedir(dirp);
        return true;
    } 

    bool GetDirEntries(const std::string &dir, std::vector<dirEntryInfo> &dirEntries, std::vector<dirEntryInfo>  &fileEntries,
                                        std::vector<dirEntryInfo>  &dirLinkEntries, std::vector<dirEntryInfo>  &fileLinkEntries)
    { 
        DIR *dirp;
        struct dirent64 *dp; 
        struct stat64 buf, lbuf;

        if ((dirp = opendir(dir.c_str())) == NULL) 
        {
            printf("couldn't open %s\n", dir.c_str()); 
            return false;
        }

        while((dp = readdir64(dirp)) != NULL)
        {
            std::string path = dir + "/" + dp->d_name;
            int statSuccess = stat64(path.c_str(), &buf);
            int lstatSuccess = lstat64(path.c_str(), &lbuf);

            if((lstatSuccess == 0) && MyS_IFLNK(lbuf.st_mode))
            {
                if((statSuccess == 0) && S_ISDIR(buf.st_mode))
                {
                    dirLinkEntries.push_back(dirEntryInfo(path, buf));
                }
                else if((statSuccess == 0) && S_ISREG(buf.st_mode))
                {
                    fileEntries.push_back(dirEntryInfo(path, buf));
                }
                else if(statSuccess != 0)
                {
                    dirEntries.push_back(dirEntryInfo(path, buf));
                }
            }
            else if(statSuccess == 0)
            {
                if(S_ISDIR(buf.st_mode))
                { 
                    dirEntries.push_back(dirEntryInfo(path, buf));
                }
                else if(S_ISREG(buf.st_mode))
                {
                    fileEntries.push_back(dirEntryInfo(path, buf));
                }
            }
        }
        closedir(dirp);
        return true;
    }

    bool GetDirEntries(const std::string &dir, std::vector<dirEntryInfo>  &dirEntries, std::vector<dirEntryInfo>  &fileEntries)
    { 
        std::vector<dirEntryInfo> dirLinkEntries;
        std::vector<dirEntryInfo> fileLinkEntries;
        return GetDirEntries(dir, dirEntries, fileEntries, dirLinkEntries, fileLinkEntries);
    }
}
