⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfs-file-info.c

📁 台湾人开发的Linux下的文件管理器
💻 C
📖 第 1 页 / 共 2 页
字号:
/**  C Implementation: vfs-file-info** Description: File information*** Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006** Copyright: See COPYING file that comes with this distribution**/#include "vfs-file-info.h"#include "xdgmime.h"#include <glib.h>#include "glib-mem.h"#include <glib/gi18n.h>#include <grp.h> /* Query group name */#include <pwd.h> /* Query user name */#include <string.h>#include "vfs-app-desktop.h"#include "md5.h"    /* for thumbnails */#define _MAX( x, y )     (x > y ? x : y)static int big_thumb_size = 48, small_thumb_size = 20;static gboolean utf8_file_name = FALSE;void vfs_file_info_set_utf8_filename( gboolean is_utf8 ){    utf8_file_name = is_utf8;}VFSFileInfo* vfs_file_info_new (){    VFSFileInfo * fi = g_slice_new0( VFSFileInfo );    fi->n_ref = 1;    return fi;}static void vfs_file_info_clear( VFSFileInfo* fi ){    if ( fi->disp_name && fi->disp_name != fi->name )    {        g_free( fi->disp_name );        fi->disp_name = NULL;    }    if ( fi->name )    {        g_free( fi->name );        fi->name = NULL;    }    if ( fi->disp_size )    {        g_free( fi->disp_size );        fi->disp_size = NULL;    }    if ( fi->disp_owner )    {        g_free( fi->disp_owner );        fi->disp_owner = NULL;    }    if ( fi->disp_mtime )    {        g_free( fi->disp_mtime );        fi->disp_mtime = NULL;    }    if ( fi->big_thumbnail )    {        gdk_pixbuf_unref( fi->big_thumbnail );        fi->big_thumbnail = NULL;    }    if ( fi->small_thumbnail )    {        gdk_pixbuf_unref( fi->small_thumbnail );        fi->small_thumbnail = NULL;    }    fi->disp_perm[ 0 ] = '\0';    if ( fi->mime_type )    {        vfs_mime_type_unref( fi->mime_type );        fi->mime_type = NULL;    }    fi->flags = VFS_FILE_INFO_NONE;}void vfs_file_info_ref( VFSFileInfo* fi ){    ++fi->n_ref;}void vfs_file_info_unref( VFSFileInfo* fi ){    --fi->n_ref;    if ( fi->n_ref <= 0 )    {        vfs_file_info_clear( fi );        g_slice_free( VFSFileInfo, fi );    }}gboolean vfs_file_info_get( VFSFileInfo* fi,                            const char* file_path,                            const char* base_name ){    struct stat file_stat;    vfs_file_info_clear( fi );    if ( base_name )        fi->name = g_strdup( base_name );    else        fi->name = g_path_get_basename( file_path );    if ( lstat( file_path, &file_stat ) == 0 )    {        /* This is time-consuming but can save much memory */        fi->mode = file_stat.st_mode;        fi->dev = file_stat.st_dev;        fi->uid = file_stat.st_uid;        fi->gid = file_stat.st_gid;        fi->size = file_stat.st_size;        fi->mtime = file_stat.st_mtime;        fi->atime = file_stat.st_atime;        fi->blksize = file_stat.st_blksize;        fi->blocks = file_stat.st_blocks;        if ( G_LIKELY( utf8_file_name && g_utf8_validate ( fi->name, -1, NULL ) ) )        {            fi->disp_name = fi->name;   /* Don't duplicate the name and save memory */        }        else        {            fi->disp_name = g_filename_display_name( fi->name );        }        fi->mime_type = vfs_mime_type_get_from_file( file_path,                                                     fi->disp_name,                                                     &file_stat );        return TRUE;    }    else        fi->mime_type = vfs_mime_type_get_from_type( XDG_MIME_TYPE_UNKNOWN );    return FALSE;}const char* vfs_file_info_get_name( VFSFileInfo* fi ){    return fi->name;}/* Get displayed name encoded in UTF-8 */const char* vfs_file_info_get_disp_name( VFSFileInfo* fi ){    return fi->disp_name;}void vfs_file_info_set_disp_name( VFSFileInfo* fi, const char* name ){    if ( fi->disp_name && fi->disp_name != fi->name )        g_free( fi->disp_name );    fi->disp_name = g_strdup( name );}void vfs_file_info_set_name( VFSFileInfo* fi, const char* name ){    g_free( fi->name );    fi->name = g_strdup( name );}off_t vfs_file_info_get_size( VFSFileInfo* fi ){    return fi->size;}const char* vfs_file_info_get_disp_size( VFSFileInfo* fi ){    if ( G_UNLIKELY( !fi->disp_size ) )    {        char buf[ 64 ];        file_size_to_string( buf, fi->size );        fi->disp_size = g_strdup( buf );    }    return fi->disp_size;}off_t vfs_file_info_get_blocks( VFSFileInfo* fi ){    return fi->blocks;}VFSMimeType* vfs_file_info_get_mime_type( VFSFileInfo* fi ){    vfs_mime_type_ref( fi->mime_type );    return fi->mime_type;}void vfs_file_info_reload_mime_type( VFSFileInfo* fi,                                     const char* full_path ){    VFSMimeType * old_mime_type;    struct stat file_stat;    /* convert VFSFileInfo to struct stat */    /* In current implementation, only st_mode is used in       mime-type detection, so let's save some CPU cycles       and don't copy unused fields.    */    file_stat.st_mode = fi->mode;    /*    file_stat.st_dev = fi->dev;    file_stat.st_uid = fi->uid;    file_stat.st_gid = fi->gid;    file_stat.st_size = fi->size;    file_stat.st_mtime = fi->mtime;    file_stat.st_atime = fi->atime;    file_stat.st_blksize = fi->blksize;    file_stat.st_blocks = fi->blocks;    */    old_mime_type = fi->mime_type;    fi->mime_type = vfs_mime_type_get_from_file( full_path,                                                 fi->name, &file_stat );    vfs_mime_type_unref( old_mime_type );  /* FIXME: is vfs_mime_type_unref needed ?*/}const char* vfs_file_info_get_mime_type_desc( VFSFileInfo* fi ){    return vfs_mime_type_get_description( fi->mime_type );}GdkPixbuf* vfs_file_info_get_big_icon( VFSFileInfo* fi ){    /* get special icons for special files, especially for       some desktop icons */    if ( G_UNLIKELY( fi->flags != VFS_FILE_INFO_NONE ) )    {        int w, h;        int icon_size;        vfs_mime_type_get_icon_size( &icon_size, NULL );        if ( fi->big_thumbnail )        {            w = gdk_pixbuf_get_width( fi->big_thumbnail );            h = gdk_pixbuf_get_height( fi->big_thumbnail );        }        else            w = h = 0;        if ( _MAX( w, h ) != icon_size )        {            char * icon_name = NULL;            if ( fi->big_thumbnail )            {                icon_name = ( char* ) g_object_steal_data(                                G_OBJECT(fi->big_thumbnail), "name" );                gdk_pixbuf_unref( fi->big_thumbnail );                fi->big_thumbnail = NULL;            }            if ( G_LIKELY( icon_name ) )            {                if ( G_UNLIKELY( icon_name[ 0 ] == '/' ) )                    fi->big_thumbnail = gdk_pixbuf_new_from_file( icon_name, NULL );                else                    fi->big_thumbnail = gtk_icon_theme_load_icon(                                            gtk_icon_theme_get_default(),                                            icon_name,                                            icon_size, 0, NULL );            }            if ( fi->big_thumbnail )                g_object_set_data_full( G_OBJECT(fi->big_thumbnail), "name", icon_name, g_free );            else                g_free( icon_name );        }        return fi->big_thumbnail ? gdk_pixbuf_ref( fi->big_thumbnail ) : NULL;    }    if( G_UNLIKELY(!fi->mime_type) )        return NULL;    return vfs_mime_type_get_icon( fi->mime_type, TRUE );}GdkPixbuf* vfs_file_info_get_small_icon( VFSFileInfo* fi ){    return vfs_mime_type_get_icon( fi->mime_type, FALSE );}GdkPixbuf* vfs_file_info_get_big_thumbnail( VFSFileInfo* fi ){    return fi->big_thumbnail ? gdk_pixbuf_ref( fi->big_thumbnail ) : NULL;}GdkPixbuf* vfs_file_info_get_small_thumbnail( VFSFileInfo* fi ){    return fi->small_thumbnail ? gdk_pixbuf_ref( fi->small_thumbnail ) : NULL;}const char* vfs_file_info_get_disp_owner( VFSFileInfo* fi ){    struct passwd * puser;    struct group* pgroup;    char uid_str_buf[ 32 ];    char* user_name;    char gid_str_buf[ 32 ];    char* group_name;    /* FIXME: user names should be cached */    if ( ! fi->disp_owner )    {        puser = getpwuid( fi->uid );        if ( puser && puser->pw_name && *puser->pw_name )            user_name = puser->pw_name;        else        {            sprintf( uid_str_buf, "%d", fi->uid );            user_name = uid_str_buf;        }        pgroup = getgrgid( fi->gid );        if ( pgroup && pgroup->gr_name && *pgroup->gr_name )            group_name = pgroup->gr_name;        else        {            sprintf( gid_str_buf, "%d", fi->gid );            group_name = gid_str_buf;        }        fi->disp_owner = g_strdup_printf ( "%s:%s", user_name, group_name );    }    return fi->disp_owner;}const char* vfs_file_info_get_disp_mtime( VFSFileInfo* fi ){    if ( ! fi->disp_mtime )    {        char buf[ 64 ];        strftime( buf, sizeof( buf ),                  "%Y-%m-%d %H:%M",                  localtime( &fi->mtime ) );        fi->disp_mtime = g_strdup( buf );    }    return fi->disp_mtime;}time_t* vfs_file_info_get_mtime( VFSFileInfo* fi ){    return & fi->mtime;}time_t* vfs_file_info_get_atime( VFSFileInfo* fi ){    return & fi->atime;}static void get_file_perm_string( char* perm, mode_t mode ){    perm[ 0 ] = S_ISDIR( mode ) ? 'd' : ( S_ISLNK( mode ) ? 'l' : '-' );    perm[ 1 ] = ( mode & S_IRUSR ) ? 'r' : '-';    perm[ 2 ] = ( mode & S_IWUSR ) ? 'w' : '-';    perm[ 3 ] = ( mode & S_IXUSR ) ? 'x' : '-';    perm[ 4 ] = ( mode & S_IRGRP ) ? 'r' : '-';    perm[ 5 ] = ( mode & S_IWGRP ) ? 'w' : '-';    perm[ 6 ] = ( mode & S_IXGRP ) ? 'x' : '-';    perm[ 7 ] = ( mode & S_IROTH ) ? 'r' : '-';    perm[ 8 ] = ( mode & S_IWOTH ) ? 'w' : '-';    perm[ 9 ] = ( mode & S_IXOTH ) ? 'x' : '-';    perm[ 10 ] = '\0';}const char* vfs_file_info_get_disp_perm( VFSFileInfo* fi ){    if ( ! fi->disp_perm[ 0 ] )        get_file_perm_string( fi->disp_perm,                              fi->mode );    return fi->disp_perm;}void file_size_to_string( char* buf, guint64 size ){    char * unit;    /* guint point; */    gfloat val;    /*       FIXME: Is floating point calculation slower than integer division?              Some profiling is needed here.    */    if ( size > ( ( guint64 ) 1 ) << 30 )    {        if ( size > ( ( guint64 ) 1 ) << 40 )        {            /*            size /= ( ( ( guint64 ) 1 << 40 ) / 10 );            point = ( guint ) ( size % 10 );            size /= 10;            */            val = ((gfloat)size) / ( ( guint64 ) 1 << 40 );            unit = "TB";        }        else        {            /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -