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

📄 xdgmime.c

📁 linux下upnp的源码库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: C; c-file-style: "gnu" -*- *//* xdgmime.c: XDG Mime Spec mime resolver.  Based on version 0.11 of the spec. * * More info can be found at http://www.freedesktop.org/standards/ *  * Copyright (C) 2003,2004  Red Hat, Inc. * Copyright (C) 2003,2004  Jonathan Blandford <jrb@alum.mit.edu> * * Licensed under the Academic Free License version 2.0 * Or under the following terms: *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "xdgmime.h"#include "xdgmimeint.h"#include "xdgmimeglob.h"#include "xdgmimemagic.h"#include "xdgmimealias.h"#include "xdgmimeparent.h"#include "xdgmimecache.h"#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <unistd.h>#include <assert.h>typedef struct XdgDirTimeList XdgDirTimeList;typedef struct XdgCallbackList XdgCallbackList;static int need_reread = TRUE;static time_t last_stat_time = 0;static XdgGlobHash *global_hash = NULL;static XdgMimeMagic *global_magic = NULL;static XdgAliasList *alias_list = NULL;static XdgParentList *parent_list = NULL;static XdgDirTimeList *dir_time_list = NULL;static XdgCallbackList *callback_list = NULL;XdgMimeCache **_xdg_mime_caches = NULL;static int n_caches = 0;const char xdg_mime_type_unknown[] = "application/octet-stream";enum{  XDG_CHECKED_UNCHECKED,  XDG_CHECKED_VALID,  XDG_CHECKED_INVALID};struct XdgDirTimeList{  time_t mtime;  char *directory_name;  int checked;  XdgDirTimeList *next;  XdgMimeCache *cache;};struct XdgCallbackList{  XdgCallbackList *next;  XdgCallbackList *prev;  int              callback_id;  XdgMimeCallback  callback;  void            *data;  XdgMimeDestroy   destroy;};/* Function called by xdg_run_command_on_dirs.  If it returns TRUE, further * directories aren't looked at */typedef int (*XdgDirectoryFunc) (const char *directory,				 void       *user_data);static XdgDirTimeList *xdg_dir_time_list_new (void){  XdgDirTimeList *retval;  retval = calloc (1, sizeof (XdgDirTimeList));  retval->checked = XDG_CHECKED_UNCHECKED;  return retval;}static voidxdg_dir_time_list_free (XdgDirTimeList *list){  XdgDirTimeList *next;  while (list)    {      next = list->next;      free (list->directory_name);      free (list);      list = next;    }}static intxdg_mime_init_from_directory (const char *directory){  char *file_name;  struct stat st;  XdgDirTimeList *list;  assert (directory != NULL);  file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");  if (stat (file_name, &st) == 0)    {      XdgMimeCache *cache = _xdg_mime_cache_new_from_file (file_name);      if (cache != NULL)	{	  list = xdg_dir_time_list_new ();	  list->directory_name = file_name;	  list->mtime = st.st_mtime;	  list->next = dir_time_list;	  list->cache = cache;	  dir_time_list = list;	  _xdg_mime_caches = realloc (_xdg_mime_caches, sizeof (XdgMimeCache *) * (n_caches + 2));	  _xdg_mime_caches[n_caches] = cache;          _xdg_mime_caches[n_caches + 1] = NULL;	  n_caches++;	  return FALSE;	}    }  free (file_name);  file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/globs");  if (stat (file_name, &st) == 0)    {      _xdg_mime_glob_read_from_file (global_hash, file_name);      list = xdg_dir_time_list_new ();      list->directory_name = file_name;      list->mtime = st.st_mtime;      list->next = dir_time_list;      dir_time_list = list;    }  else    {      free (file_name);    }  file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/magic");  if (stat (file_name, &st) == 0)    {      _xdg_mime_magic_read_from_file (global_magic, file_name);      list = xdg_dir_time_list_new ();      list->directory_name = file_name;      list->mtime = st.st_mtime;      list->next = dir_time_list;      dir_time_list = list;    }  else    {      free (file_name);    }  file_name = malloc (strlen (directory) + strlen ("/mime/aliases") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/aliases");  _xdg_mime_alias_read_from_file (alias_list, file_name);  free (file_name);  file_name = malloc (strlen (directory) + strlen ("/mime/subclasses") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/subclasses");  _xdg_mime_parent_read_from_file (parent_list, file_name);  free (file_name);  return FALSE; /* Keep processing */}/* Runs a command on all the directories in the search path */static voidxdg_run_command_on_dirs (XdgDirectoryFunc  func,			 void             *user_data){  const char *xdg_data_home;  const char *xdg_data_dirs;  const char *ptr;  xdg_data_home = getenv ("XDG_DATA_HOME");  if (xdg_data_home)    {      if ((func) (xdg_data_home, user_data))	return;    }  else    {      const char *home;      home = getenv ("HOME");      if (home != NULL)	{	  char *guessed_xdg_home;	  int stop_processing;	  guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1);	  strcpy (guessed_xdg_home, home);	  strcat (guessed_xdg_home, "/.local/share/");	  stop_processing = (func) (guessed_xdg_home, user_data);	  free (guessed_xdg_home);	  if (stop_processing)	    return;	}    }  xdg_data_dirs = getenv ("XDG_DATA_DIRS");  if (xdg_data_dirs == NULL)    xdg_data_dirs = "/usr/local/share/:/usr/share/";  ptr = xdg_data_dirs;  while (*ptr != '\000')    {      const char *end_ptr;      char *dir;      int len;      int stop_processing;      end_ptr = ptr;      while (*end_ptr != ':' && *end_ptr != '\000')	end_ptr ++;      if (end_ptr == ptr)	{	  ptr++;	  continue;	}      if (*end_ptr == ':')	len = end_ptr - ptr;      else	len = end_ptr - ptr + 1;      dir = malloc (len + 1);      strncpy (dir, ptr, len);      dir[len] = '\0';      stop_processing = (func) (dir, user_data);      free (dir);      if (stop_processing)	return;      ptr = end_ptr;    }}static XdgMimeCache *xdg_lookup_cache_for_file (const char *file_path){  XdgDirTimeList *list;  for (list = dir_time_list; list; list = list->next)      if (! strcmp (list->directory_name, file_path))	 return list->cache;  return NULL;}/* Checks file_path to make sure it has the same mtime as last time it was * checked.  If it has a different mtime, or if the file doesn't exist, it * returns FALSE. * * FIXME: This doesn't protect against permission changes. */static intxdg_check_file (const char *file_path){  struct stat st;  /* If the file exists */  if (stat (file_path, &st) == 0)    {      XdgDirTimeList *list;      for (list = dir_time_list; list; list = list->next)	{	  if (! strcmp (list->directory_name, file_path) &&	      st.st_mtime == list->mtime)	    {	      if (list->checked == XDG_CHECKED_UNCHECKED)		list->checked = XDG_CHECKED_VALID;	      else if (list->checked == XDG_CHECKED_VALID)		list->checked = XDG_CHECKED_INVALID;	      return (list->checked != XDG_CHECKED_VALID);	    }	}      return TRUE;    }  return FALSE;}static intxdg_check_dir (const char *directory,	       int        *invalid_dir_list){  int invalid, has_cache;  char *file_name;  assert (directory != NULL);  /* Check the mime.cache file */  file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");  invalid = xdg_check_file (file_name);  has_cache = xdg_lookup_cache_for_file (file_name) != NULL;  free (file_name);  if (has_cache)    {      if (invalid)	{	  *invalid_dir_list = TRUE;	  return TRUE;	}      return FALSE;    }  /* Check the globs file */  file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/globs");  invalid = xdg_check_file (file_name);  free (file_name);  if (invalid)    {      *invalid_dir_list = TRUE;      return TRUE;    }  /* Check the magic file */  file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);  strcpy (file_name, directory); strcat (file_name, "/mime/magic");  invalid = xdg_check_file (file_name);  free (file_name);  if (invalid)    {      *invalid_dir_list = TRUE;      return TRUE;    }  return FALSE; /* Keep processing */}/* Walks through all the mime files stat()ing them to see if they've changed. * Returns TRUE if they have. */static intxdg_check_dirs (void){  XdgDirTimeList *list;  int invalid_dir_list = FALSE;  for (list = dir_time_list; list; list = list->next)    list->checked = XDG_CHECKED_UNCHECKED;  xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_check_dir,			   &invalid_dir_list);  if (invalid_dir_list)    return TRUE;  for (list = dir_time_list; list; list = list->next)    {      if (list->checked != XDG_CHECKED_VALID)	return TRUE;    }  return FALSE;}/* We want to avoid stat()ing on every single mime call, so we only look for * newer files every 5 seconds.  This will return TRUE if we need to reread the * mime data from disk. */static intxdg_check_time_and_dirs (void){  struct timeval tv;  time_t current_time;  int retval = FALSE;  gettimeofday (&tv, NULL);  current_time = tv.tv_sec;  if (current_time >= last_stat_time + 5)    {      retval = xdg_check_dirs ();      last_stat_time = current_time;    }  return retval;}/* Called in every public function.  It reloads the hash function if need be. */static voidxdg_mime_init (void){  if (xdg_check_time_and_dirs ())    {      xdg_mime_shutdown ();    }

⌨️ 快捷键说明

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