Files
FireBee_Setup/sources/z-tools/trunk/zview/file/file.c

440 lines
12 KiB
C

/*----------------------------------------------------------------------*/
/* Files utilities */
/*----------------------------------------------------------------------*/
#include "../general.h"
#include "../zedit/zedit.h"
#include "../catalog/catalog_entry.h"
#include "../ztext.h"
#include "../catalog/catalog_icons.h"
#include "../prefs.h"
#include "../mfdb.h"
#include "../txt_data.h"
#include "../custom_font.h"
#include "sort.h"
#define ALLOC_NDIRENTRIES (4) /* number of entries that should be allocated at once by readdir() */
/* Prototype */
boolean dir_parent( char *dir, char *old_dir);
boolean dir_cd( const char *new_dir, char *old_dir, int16 bufflen);
boolean check_write_perm( const struct stat *file_stat);
boolean scan_dir( WINDOW *win, const char *dirpath);
boolean scan_mini_drv( WINDOW *win);
void check_mini_dir( int16 nbr_child, Mini_Entry *entry);
boolean scan_mini_dir( WINDOW *win, Mini_Entry *parent);
/*==================================================================================*
* dir_parent: *
* go to the parent directory. *
*----------------------------------------------------------------------------------*
* returns: TRUE = success, FALSE = if root path ( so, no dir up). *
*----------------------------------------------------------------------------------*
* dir: Pointer to the current directory, the new directory will be *
* returned on the same pointer. *
* old_dir: Pointer on a null string where will be returned the name of the *
* old directory. ( not the full path, only the name) *
*==================================================================================*/
boolean dir_parent( char *dir, char *old_dir)
{
int16 len, i, ii;
len = ( int16) strlen( dir) - 1;
if ( len < 3)
return FALSE;
if ( dir[len] == '\\')
dir[len] = '\0';
len--;
i = len;
while ( dir[i] != '\\')
i--;
ii = len - i - 1;
old_dir[ii + 1] = '\0';
while ( dir[len] != '\\')
{
old_dir[ii] = dir[len];
dir[len] = '\0';
len--;
ii--;
}
return TRUE;
}
/*==================================================================================*
* dir_cd: *
* enter to a directory. *
*----------------------------------------------------------------------------------*
* returns: TRUE = success, FALSE = error *
*----------------------------------------------------------------------------------*
* new_dir: The New directory. *
* old_dir: Pointer where save the previous directory. *
* ( If NULL, no storing is done). *
*==================================================================================*/
boolean dir_cd( const char *new_dir, char *old_dir, int16 bufflen)
{
if ( old_dir != NULL)
getcwd( old_dir, bufflen);
return chdir( new_dir) == 0 ? TRUE : FALSE;
}
/*==================================================================================*
* check_write_perm: *
* Do complex WRITE permission check. *
*----------------------------------------------------------------------------------*
* returns: TRUE = ok, FALSE = no *
*----------------------------------------------------------------------------------*
* stat: Entry Stat. *
*==================================================================================*/
boolean check_write_perm( const struct stat *file_stat)
{
uid_t uid = geteuid();
gid_t gid = getegid();
/* if ( uid == 0)
return TRUE;
*/
if ( file_stat->st_uid == uid)
return ( file_stat->st_mode & S_IWUSR) ? TRUE : FALSE;
if ( file_stat->st_gid == gid)
return ( file_stat->st_mode & S_IWGRP) ? TRUE : FALSE;
return ( file_stat->st_mode & S_IWOTH) ? TRUE : FALSE;
}
/*==================================================================================*
* scan_dir: *
* scan the 'dirpath' directory and fit somes entries in 'dirfile'. *
*----------------------------------------------------------------------------------*
* return: TRUE if ok or FALSE if error *
*==================================================================================*/
boolean scan_dir( WINDOW *win, const char *dirpath)
{
short dum, allocated_entries = 0;
Entry *entry;
DIR *dir;
struct dirent *de;
struct stat file_stat;
struct tm *tmt;
WINDICON *dirfile = ( WINDICON *)DataSearch( win, WD_ICON);
if ( dirfile->nbr_icons)
{
for ( dum = 0; dum < dirfile->nbr_icons; dum++)
{
delete_txt_data( &dirfile->entry[dum].preview);
delete_mfdb( dirfile->entry[dum].preview.image, dirfile->entry[dum].preview.page);
}
dirfile->nbr_icons = 0;
gfree( dirfile->entry);
}
dirfile->first_selected = NULL;
dirfile->entry = NULL;
dirfile->edit = NULL;
if ( !dir_cd( dirpath, NULL, 0))
dir_cd( ".", NULL, 0);
strcpy( dirfile->directory, dirpath);
dum = ( int16)strlen( dirfile->directory);
if ( dirfile->directory[dum-1] != '\\')
strcat( dirfile->directory, "\\");
if (( dir = opendir( ".")) == NULL)
{
errshow( "dir", errno);
goto abort;
}
while(( de = readdir( dir)) != NULL)
{
if (( strcmp( de->d_name, ".") == 0) || ( strcmp( de->d_name, "..") == 0))
continue;
if ( stat( de->d_name, &file_stat) != 0)
continue;
if (((( file_stat.st_flags & FA_HIDDEN) != 0) || de->d_name[0] == '.') && !show_hidden)
continue;
/* allocate new memory for entries if needed */
if ( dirfile->nbr_icons >= allocated_entries)
{ /* allocate new entries */
if ( dirfile->nbr_icons == 0)
{ /* alloc for the first time */
if (( dirfile->entry = ( Entry *)gmalloc( ALLOC_NDIRENTRIES * sizeof( Entry))) == NULL)
{
errshow( "", ENOMEM);
goto abort;
}
}
else
{ /* expand allocated memory */
if (( entry = ( Entry *)grealloc( dirfile->entry, ( allocated_entries + ALLOC_NDIRENTRIES) * sizeof( Entry))) == NULL)
{
errshow( "", ENOMEM);
goto abort;
}
dirfile->entry = entry;
}
allocated_entries += ALLOC_NDIRENTRIES;
}
/* fill out and add new entry */
entry = &dirfile->entry[dirfile->nbr_icons];
entry->preview.image = NULL;
entry->preview.page = 0;
entry->preview.comments = NULL;
entry->next_selected = NULL;
entry->stat = file_stat;
strcpy( entry->name, de->d_name);
zstrncpy( entry->name_shown, de->d_name, 99);
/* Get Size */
size_to_text( entry->size, ( float)file_stat.st_size);
/* Get Time */
tmt = localtime(&file_stat.st_mtime);
strftime( entry->date, 28, "%A %d %B %Y", tmt);
strftime( entry->time, 12, "%H:%M:%S", tmt);
set_entry_icon( entry);
/* find if the entry name is bigger than the case width */
if (( entry->icon_txt_w = get_text_width( entry->name_shown)) >= dirfile->case_w - 4)
entry->icon_txt_w = name_shorter( dirfile->case_w - 6, entry->name_shown);
dirfile->nbr_icons++;
}
closedir( dir);
sort_entries( dirfile);
return TRUE;
abort:
closedir( dir);
if ( dirfile->nbr_icons > 0)
gfree( dirfile->entry);
return FALSE;
}
/*==================================================================================*
* scan_mini_drv: *
* Creates a list with the available drives. *
*----------------------------------------------------------------------------------*
* returns: TRUE if ok, FALSE if any error occured *
*==================================================================================*/
boolean scan_mini_drv( WINDOW *win)
{
int current_drv, drv, allocated_entries = 0;
uint32 drives, tmp_d;
Mini_Entry *entry;
WINDICON *dirlist = ( WINDICON *)DataSearch( win, WD_ICON);
/* initialise directory descriptor */
dirlist->nbr_child = 0;
dirlist->entry = NULL;
dirlist->mini_selected = NULL;
/* read contents of directory and build list */
drives = Drvmap();
tmp_d = drives;
for ( current_drv = 0; current_drv < 32; current_drv++, tmp_d >>= 1)
{
if ( tmp_d & 0x1)
{
drv = 'A' + current_drv;
if ( strchr( skip_drive, drv))
continue;
/* allocate new memory for entries if needed */
if ( dirlist->nbr_child >= allocated_entries)
{
if ( dirlist->nbr_child == 0)
{
if (( dirlist->root = ( Mini_Entry *)gmalloc( ALLOC_NDIRENTRIES * sizeof( Mini_Entry))) == NULL)
goto abort;
}
else
{
if (( entry = ( Mini_Entry *)grealloc( dirlist->root, ( allocated_entries + ALLOC_NDIRENTRIES) * sizeof( Mini_Entry))) == NULL)
goto abort;
dirlist->root = entry;
}
allocated_entries += ALLOC_NDIRENTRIES;
}
/* fill out and add new entry */
entry = &dirlist->root[dirlist->nbr_child];
sprintf( entry->foldername, "%c:\\", drv);
sprintf( entry->name, "%c", drv);
entry->parent = NULL;
entry->child = NULL;
entry->nbr_child = 0;
entry->icon_txt_w = get_text_width( entry->name);
entry->state = UNKNOWN;
dirlist->nbr_child++;
}
}
return TRUE;
abort:
if ( dirlist->nbr_child > 0)
gfree( dirlist->root);
errshow( "", ENOMEM);
return FALSE;
}
void check_mini_dir( int16 nbr_child, Mini_Entry *entry)
{
int16 i, next;
char old_dir[MAX_PATH];
DIR *dir;
struct dirent *de;
struct stat file_stat;
for ( i = 0 ; i < nbr_child; i++)
{
next = 0;
if ( dir_cd( entry[i].foldername, old_dir, ( int)( sizeof old_dir)))
{
if (( dir = opendir( entry[i].foldername)) != NULL)
{
while(( de = readdir( dir)) != NULL && next == 0)
{
if (( strcmp( de->d_name, ".") == 0) || ( strcmp( de->d_name, "..") == 0))
continue;
if ( stat( de->d_name, &file_stat) != 0)
continue;
if ( S_ISDIR( file_stat.st_mode))
{
next = 1;
entry[i].state = OFF;
}
}
closedir( dir);
}
dir_cd( old_dir, NULL, 0);
}
}
}
boolean scan_mini_dir( WINDOW *win, Mini_Entry *parent)
{
short allocated_entries = 0;
char old_dir[MAX_PATH];
Mini_Entry *entry;
DIR *dir;
struct dirent *de;
struct stat file_stat;
if ( dir_cd( parent->foldername, old_dir, ( int)( sizeof old_dir)))
{
if (( dir = opendir( ".")) != NULL)
{
while(( de = readdir( dir)) != NULL)
{
if (( strcmp( de->d_name, ".") == 0) || ( strcmp( de->d_name, "..") == 0))
continue;
if ( stat( de->d_name, &file_stat) != 0)
continue;
if ( !S_ISDIR( file_stat.st_mode))
continue;
if (( file_stat.st_flags & 2) == FA_HIDDEN && !show_hidden)
continue;
if ( parent->nbr_child >= allocated_entries)
{
if ( parent->nbr_child == 0)
{
if (( parent->child = ( Mini_Entry *)gmalloc( ALLOC_NDIRENTRIES * sizeof( Mini_Entry))) == NULL)
goto abort;
}
else
{
if (( entry = ( Mini_Entry *)grealloc( parent->child, ( allocated_entries + ALLOC_NDIRENTRIES) * sizeof( Mini_Entry))) == NULL)
goto abort;
parent->child = entry;
}
allocated_entries += ALLOC_NDIRENTRIES;
}
entry = &parent->child[parent->nbr_child];
strcpy( entry->foldername, parent->foldername);
strcat( entry->foldername, de->d_name);
strcat( entry->foldername, "\\");
strcpy( entry->name, de->d_name);
entry->parent = parent;
entry->child = NULL;
entry->nbr_child = 0;
entry->icon_txt_w = get_text_width( entry->name);
entry->state = UNKNOWN;
parent->nbr_child++;
}
closedir( dir);
}
dir_cd( old_dir, NULL, 0);
}
qsort( parent->child, parent->nbr_child, sizeof( Mini_Entry), cmp_entries_name);
return TRUE;
abort:
closedir( dir);
if ( parent->nbr_child > 0)
gfree( parent->child);
parent->nbr_child = 0;
return FALSE;
}