📄 vfs-file-info.c
字号:
/** 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 + -