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

📄 directory.c

📁 linux下的MPEG1
💻 C
字号:
/*    $Id: directory.c,v 1.4 2006/09/26 19:26:57 dgp85 Exp $    Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>    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*/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <stdlib.h>#include <string.h>/* Public headers */#include <cdio/bytesex.h>#include <cdio/iso9660.h>#include <libvcd/logging.h>/* Private headers */#include "vcd_assert.h"#include "directory.h"#include "util.h"static const char _rcsid[] = "$Id: directory.c,v 1.4 2006/09/26 19:26:57 dgp85 Exp $";/* CD-ROM XA *//* tree data structure */typedef struct {  bool is_dir;  char *name;  uint16_t version;  uint16_t xa_attributes;  uint8_t xa_filenum;  uint32_t extent;  uint32_t size;  unsigned pt_id;} data_t;typedef VcdTreeNode VcdDirNode;#define EXTENT(anode) (DATAP(anode)->extent)#define SIZE(anode)   (DATAP(anode)->size)#define PT_ID(anode)  (DATAP(anode)->pt_id)#define DATAP(anode) ((data_t*) _vcd_tree_node_data (anode))/* important date to celebrate (for me at least =)   -- until user customization is implemented... */static const time_t _vcd_time = 269222400L;                                       /* implementation */static voidtraverse_get_dirsizes(VcdDirNode *node, void *data){  data_t *d = DATAP(node);  unsigned *sum = data;  if (d->is_dir)    {      vcd_assert (d->size % ISO_BLOCKSIZE == 0);      *sum += (d->size / ISO_BLOCKSIZE);    }}static unsignedget_dirsizes (VcdDirNode* dirnode){  unsigned result = 0;  _vcd_tree_node_traverse (dirnode, traverse_get_dirsizes, &result);  return result;}static voidtraverse_update_dirextents (VcdDirNode *dirnode, void *data){  data_t *d = DATAP(dirnode);  if (d->is_dir)     {      VcdDirNode* child;      unsigned dirextent = d->extent;            vcd_assert (d->size % ISO_BLOCKSIZE == 0);            dirextent += d->size / ISO_BLOCKSIZE;            _VCD_CHILD_FOREACH (child, dirnode)        {          data_t *d = DATAP(child);                    vcd_assert (d != NULL);                    if (d->is_dir)             {              d->extent = dirextent;              dirextent += get_dirsizes (child);            }        }    }}static void update_dirextents (VcdDirectory *dir, uint32_t extent){  data_t *dirdata = DATAP(_vcd_tree_root (dir));    dirdata->extent = extent;  _vcd_tree_node_traverse (_vcd_tree_root (dir),                           traverse_update_dirextents, NULL);}static voidtraverse_update_sizes(VcdDirNode *node, void *data){  data_t *dirdata = DATAP(node);  if (dirdata->is_dir)    {      VcdDirNode* child;      unsigned offset = 0;            offset += iso9660_dir_calc_record_size (1, sizeof(iso9660_xa_t)); /* '.' */      offset += iso9660_dir_calc_record_size (1, sizeof(iso9660_xa_t)); /* '..' */            _VCD_CHILD_FOREACH (child, node)        {          data_t *d = DATAP(child);          unsigned reclen;          char *pathname = (d->is_dir                             ? strdup (d->name)                            : iso9660_pathname_isofy (d->name, d->version));                    vcd_assert (d != NULL);                    reclen = iso9660_dir_calc_record_size (strlen (pathname),                                                  sizeof (iso9660_xa_t));          free (pathname);                    offset = _vcd_ofs_add (offset, reclen, ISO_BLOCKSIZE);        }      vcd_assert (offset > 0);      dirdata->size = _vcd_ceil2block (offset, ISO_BLOCKSIZE);    }}static void update_sizes (VcdDirectory *dir){  _vcd_tree_node_traverse (_vcd_tree_root(dir), traverse_update_sizes, NULL);}/* exported stuff: */VcdDirectory *_vcd_directory_new (void){  data_t *data;  VcdDirectory *dir = NULL;  vcd_assert (sizeof(iso9660_xa_t) == 14);  data = _vcd_malloc (sizeof (data_t));  dir = _vcd_tree_new (data);  data->is_dir = true;  data->name = _vcd_memdup("\0", 2);  data->xa_attributes = XA_FORM1_DIR;  data->xa_filenum = 0x00;  return dir;}static voidtraverse_vcd_directory_done (VcdDirNode *node, void *data){  data_t *dirdata = DATAP (node);  free (dirdata->name);}void_vcd_directory_destroy (VcdDirectory *dir){  vcd_assert (dir != NULL);  _vcd_tree_node_traverse (_vcd_tree_root (dir),                           traverse_vcd_directory_done, NULL);  _vcd_tree_destroy (dir, true);}static VcdDirNode* lookup_child (VcdDirNode* node, const char name[]){  VcdDirNode* child;  _VCD_CHILD_FOREACH (child, node)    {      data_t *d = DATAP(child);            if (!strcmp (d->name, name))        return child;    }    return child; /* NULL */}static int_iso_dir_cmp (VcdDirNode *node1, VcdDirNode *node2){  data_t *d1 = DATAP(node1);  data_t *d2 = DATAP(node2);  int result = 0;  result = strcmp (d1->name, d2->name);  return result;}int_vcd_directory_mkdir (VcdDirectory *dir, const char pathname[]){  char **splitpath;  unsigned level, n;  VcdDirNode* pdir = _vcd_tree_root (dir);  vcd_assert (dir != NULL);  vcd_assert (pathname != NULL);  splitpath = _vcd_strsplit (pathname, '/');  level = _vcd_strlenv (splitpath);  for (n = 0; n < level-1; n++)     if (!(pdir = lookup_child(pdir, splitpath[n])))       {        vcd_error("mkdir: parent dir `%s' (level=%d) for `%s' missing!",                  splitpath[n], n, pathname);        vcd_assert_not_reached ();      }  if (lookup_child (pdir, splitpath[level-1]))     {      vcd_error ("mkdir: `%s' already exists", pathname);      vcd_assert_not_reached ();    }  {    data_t *data = _vcd_malloc (sizeof (data_t));    _vcd_tree_node_append_child (pdir, data);    data->is_dir = true;    data->name = strdup(splitpath[level-1]);    data->xa_attributes = XA_FORM1_DIR;    data->xa_filenum = 0x00;    /* .. */  }  _vcd_tree_node_sort_children (pdir, _iso_dir_cmp);    _vcd_strfreev (splitpath);  return 0;}int_vcd_directory_mkfile (VcdDirectory *dir, const char pathname[],                        uint32_t start, uint32_t size,                       bool form2_flag, uint8_t filenum){  char **splitpath;  unsigned level, n;  const int file_version = 1;  VcdDirNode* pdir = NULL;  vcd_assert (dir != NULL);  vcd_assert (pathname != NULL);  splitpath = _vcd_strsplit (pathname, '/');  level = _vcd_strlenv (splitpath);  while (!pdir)    {      pdir = _vcd_tree_root (dir);            for (n = 0; n < level-1; n++)         if (!(pdir = lookup_child (pdir, splitpath[n])))           {            char *newdir = _vcd_strjoin (splitpath, n+1, "/");            vcd_info ("autocreating directory `%s' for file `%s'",                      newdir, pathname);                        _vcd_directory_mkdir (dir, newdir);                        free (newdir);                    vcd_assert (pdir == NULL);            break;          }        else if (!DATAP(pdir)->is_dir)          {            char *newdir = _vcd_strjoin (splitpath, n+1, "/");            vcd_error ("mkfile: `%s' not a directory", newdir);            free (newdir);            return -1;          }    }  if (lookup_child (pdir, splitpath[level-1]))     {      vcd_error ("mkfile: `%s' already exists", pathname);      _vcd_strfreev(splitpath);      return -1;    }    {    data_t *data = _vcd_malloc (sizeof (data_t));    _vcd_tree_node_append_child (pdir, data);    data->is_dir = false;    data->name = strdup (splitpath[level-1]);    data->version = file_version;    data->xa_attributes = form2_flag ? XA_FORM2_FILE : XA_FORM1_FILE;    data->xa_filenum = filenum;    data->size = size;    data->extent = start;    /* .. */  }  _vcd_tree_node_sort_children (pdir, _iso_dir_cmp);  _vcd_strfreev (splitpath);  return 0;}uint32_t_vcd_directory_get_size (VcdDirectory *dir){  vcd_assert (dir != NULL);  update_sizes (dir);  return get_dirsizes (_vcd_tree_root (dir));}static voidtraverse_vcd_directory_dump_entries (VcdDirNode *node, void *data){  data_t *d = DATAP(node);  iso9660_xa_t xa_su;  uint32_t root_extent = EXTENT(_vcd_tree_node_root (node));  uint32_t parent_extent =     (!_vcd_tree_node_is_root (node))    ? EXTENT(_vcd_tree_node_parent (node))    : EXTENT(node);  uint32_t parent_size =     (!_vcd_tree_node_is_root (node))    ? SIZE(_vcd_tree_node_parent (node))    : SIZE(node);  void *dirbufp = (char*) data + ISO_BLOCKSIZE * (parent_extent - root_extent);  iso9660_xa_init (&xa_su, 0, 0, d->xa_attributes, d->xa_filenum);  if (!_vcd_tree_node_is_root (node))    {      char *pathname = (d->is_dir                         ? strdup (d->name)                        : iso9660_pathname_isofy (d->name, d->version));      iso9660_dir_add_entry_su (dirbufp, pathname, d->extent, d->size,                                 d->is_dir ? ISO_DIRECTORY : ISO_FILE,                                &xa_su, sizeof (xa_su),                                &_vcd_time);      free (pathname);    }  /* if this is a directory, create the new directory node */  if (d->is_dir)     {      dirbufp = (char*)data + ISO_BLOCKSIZE * (d->extent - root_extent);      iso9660_dir_init_new_su (dirbufp,                                d->extent, d->size, &xa_su, sizeof (xa_su),                               parent_extent, parent_size, &xa_su,                                sizeof (xa_su), &_vcd_time);    }}void_vcd_directory_dump_entries (VcdDirectory *dir, void *buf, uint32_t extent){  vcd_assert (dir != NULL);  update_sizes (dir); /* better call it one time more than one less */  update_dirextents (dir, extent);  _vcd_tree_node_traverse (_vcd_tree_root (dir),                            traverse_vcd_directory_dump_entries, buf); }typedef struct {  void *ptl;  void *ptm;} _vcd_directory_dump_pathtables_t;static void_dump_pathtables_helper (_vcd_directory_dump_pathtables_t *args,                         data_t *d, uint16_t parent_id){  uint16_t id_l, id_m;  vcd_assert (args != NULL);  vcd_assert (d != NULL);  vcd_assert (d->is_dir);  id_l = iso9660_pathtable_l_add_entry (args->ptl, d->name, d->extent,                                         parent_id);    id_m = iso9660_pathtable_m_add_entry (args->ptm, d->name, d->extent,                                         parent_id);  vcd_assert (id_l == id_m);  d->pt_id = id_m;}static voidtraverse_vcd_directory_dump_pathtables (VcdDirNode *node, void *data){  _vcd_directory_dump_pathtables_t *args = data;  if (DATAP (node)->is_dir)    {      VcdDirNode* parent = _vcd_tree_node_parent (node);      uint16_t parent_id = parent ? PT_ID (parent) : 1;      _dump_pathtables_helper (args, DATAP (node), parent_id);    }}void_vcd_directory_dump_pathtables (VcdDirectory *dir, void *ptl, void *ptm){  _vcd_directory_dump_pathtables_t args;  vcd_assert (dir != NULL);  iso9660_pathtable_init (ptl);  iso9660_pathtable_init (ptm);  args.ptl = ptl;  args.ptm = ptm;  _vcd_tree_node_traverse_bf (_vcd_tree_root (dir),                              traverse_vcd_directory_dump_pathtables, &args); }/*  * Local variables: *  c-file-style: "gnu" *  tab-width: 8 *  indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

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