<commit_before>/**
 *   (c) 2002-2005 <NAME> <<EMAIL>>
 *   v0.2.1 db.c
 *
 *   Routines for reading/writing the iPod's databases.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the Lesser GNU 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 Lesser GNU Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **/

#include "itunesdbi.h"

#include <stdlib.h>
#include <stdio.h>

#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <sys/uio.h>

#ifndef S_SPLINT_S
#include <unistd.h>
#endif

#include <fcntl.h>

#include <errno.h>

/*
  db_size_tree:

    Internal utility function for acumulating the total size of
  the database below an entry.
*/
static int db_size_tree (tree_node_t *ptr) {
  int i, size = ptr->size;

  for (i = 0 ; i < ptr->num_children ; i++)
    size += db_size_tree (ptr->children[i]);

  return size;
}

/*
  db_free_tree:

  Function to recursively free a tree.
*/
void db_free_tree (tree_node_t *ptr) {
  if (ptr == NULL)
    return;

  if (ptr->children != NULL) {
    while (--ptr->num_children > -1)
      db_free_tree(ptr->children[ptr->num_children]);

    free(ptr->children);
    ptr->children = NULL;
  }

  free(ptr->data);
  ptr->data = NULL;
  free (ptr);
}

/**
  db_free:

  Frees the memory that is allocated to an itunesdb

  Arguments:
   ipoddb_t *itunesdb - opened itunesdb

  Returns:
   nothing, void function
**/
void db_free (ipoddb_t *itunesdb) {
  if (itunesdb == NULL)
    return;

  db_free_tree(itunesdb->tree_root);

  itunesdb->tree_root = NULL;
  free (itunesdb->path);
  itunesdb->path = NULL;
}

static int dohm_contains_string (struct db_dohm *dohm_data) {
  if (dohm_data->type != 0x64 &&
      dohm_data->type != 0x33 &&
      dohm_data->type != 0x34)
    return 1;

  return 0;
}
/*
  db_build_tree:

  Internal function. 

  Purpose is to build up the iTunesDB tree from a buffer.
*/
static tree_node_t *db_build_tree (ipoddb_t *ipod_db, size_t *bytes_read,
				   /*@null@*/tree_node_t *parent, char **buffer) {
  tree_node_t *tnode_0;
  int *iptr = (int *)*buffer;

  int current_bytes_read = *bytes_read;
  int entry_size, cell_size, copy_size;

  tnode_0 = calloc (1, sizeof(tree_node_t));

  if (tnode_0 == NULL) {
    perror("db_build_tree|calloc");
    exit(EXIT_FAILURE);
  }

  tnode_0->parent = parent;

  /* swap the entry label, cell size and entry size */
  bswap_block(*buffer, 4, 3);

  entry_size = iptr[2];
  cell_size  = iptr[1];

  bswap_block (&((*buffer)[0x0c]), 4, cell_size/4 - 3);

  copy_size = cell_size;

  if ( (iptr[0] == DOHM) && (cell_size != entry_size) ) {
    struct db_dohm *dohm_data = (struct db_dohm *)*buffer;

    if (!((iptr[6] & 0x6d680000) == 0x6d680000)) {
      copy_size = entry_size;

      if (dohm_contains_string(dohm_data) == 0) {
	copy_size = entry_size;
	bswap_block (&((*buffer)[0x18]), 4, entry_size/4 - 6);
      } else {
	if (iptr[9] == 0)
	  tnode_0->string_header_size = 16;
	else
	  tnode_0->string_header_size = 12;

	bswap_block (&((*buffer)[0x18]), 4, tnode_0->string_header_size/4);

	if (tnode_0->string_header_size == 16) {
	  struct string_header_16 *string_header = (struct string_header_16 *)&((*buffer)[0x18]);
	  if (string_header->format != 1)
	    bswap_block (&((*buffer)[0x28]), 2, iptr[7]/2);
	} else {
	  struct string_header_12 *string_header = (struct string_header_12 *)&((*buffer)[0x18]);
	  if (string_header->format != 1)
	    bswap_block (&((*buffer)[0x24]), 2, iptr[7]/2);
	}
      }
    }
  } else if (iptr[0] == TIHM) {
    struct db_tihm *tihm_data = (struct db_tihm *)(*buffer);
    
    ipod_db->last_entry = ((ipod_db->last_entry < tihm_data->identifier)
			  ? tihm_data->identifier
			  : ipod_db->last_entry);
  } else if (iptr[0] == IIHM) {
    struct db_iihm *iihm_data = (struct db_iihm *)(*buffer);

    ipod_db->last_entry = ((ipod_db->last_entry < iihm_data->identifier)
			  ? iihm_data->identifier
			  : ipod_db->last_entry);
  }
  

  tnode_0->num_children = 0;
  tnode_0->size = copy_size;
  tnode_0->data = calloc (copy_size, 1);
<commit_msg>*** empty log message ***<commit_after>/**
 *   (c) 2002-2005 <NAME> <<EMAIL>>
 *   v0.2.1 db.c
 *
 *   Routines for reading/writing the iPod's databases.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the Lesser GNU 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 Lesser GNU Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **/

#include "itunesdbi.h"

#include <stdlib.h>
#include <stdio.h>

#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <sys/uio.h>

#ifndef S_SPLINT_S
#include <unistd.h>
#endif

#include <fcntl.h>

#include <errno.h>

/*
  db_size_tree:

    Internal utility function for acumulating the total size of
  the database below an entry.
*/
static int db_size_tree (tree_node_t *ptr) {
  int i, size = ptr->size;

  for (i = 0 ; i < ptr->num_children ; i++)
    size += db_size_tree (ptr->children[i]);

  return size;
}

/*
  db_free_tree:

  Function to recursively free a tree.
*/
void db_free_tree (tree_node_t *ptr) {
  if (ptr == NULL)
    return;

  if (ptr->children != NULL) {
    while (--ptr->num_children > -1)
      db_free_tree(ptr->children[ptr->num_children]);

    free(ptr->children);
    ptr->children = NULL;
  }

  free(ptr->data);
  ptr->data = NULL;
  free (ptr);
}

/**
  db_free:

  Frees the memory that is allocated to an itunesdb

  Arguments:
   ipoddb_t *itunesdb - opened itunesdb

  Returns:
   nothing, void function
**/
void db_free (ipoddb_t *itunesdb) {
  if (itunesdb == NULL)
    return;

  db_free_tree(itunesdb->tree_root);

  itunesdb->tree_root = NULL;
  free (itunesdb->path);
  itunesdb->path = NULL;
}

static int dohm_contains_string (struct db_dohm *dohm_data) {
  if (dohm_data->type != 0x64 &&
      dohm_data->type != 0x33 &&
      dohm_data->type != 0x34)
    return 1;

  return 0;
}
/*
  db_build_tree:

  Internal function. 

  Purpose is to build up the iTunesDB tree from a buffer.
*/
static tree_node_t *db_build_tree (ipoddb_t *ipod_db, size_t *bytes_read,
				   /*@null@*/tree_node_t *parent, char **buffer) {
  tree_node_t *tnode_0;
  int *iptr = (int *)*buffer;

  int current_bytes_read = *bytes_read;
  int entry_size, cell_size, copy_size;

  tnode_0 = calloc (1, sizeof(tree_node_t));

  if (tnode_0 == NULL) {
    perror("db_build_tree|calloc");
    exit(EXIT_FAILURE);
  }

  tnode_0->parent = parent;

  /* swap the entry label, cell size and entry size */
  bswap_block(*buffer, 4, 3);

  entry_size = iptr[2];
  cell_size  = iptr[1];

  bswap_block (&((*buffer)[0x0c]), 4, cell_size/4 - 3);

  copy_size = cell_size;

  if ( (iptr[0] == DOHM) && (cell_size != entry_size) ) {
    struct db_dohm *dohm_data = (struct db_dohm *)*buffer;

    /* A dohm cell can hold a string, data, or a sub-tree. Process data/string
       dohm cells in a different way than those that have subtrees. */
    if (!((iptr[6] & 0x6d680000) == 0x6d680000)) {
      copy_size = entry_size;

      if (dohm_contains_string(dohm_data) == 0) {
	/* Read a data dohm */
	copy_size = entry_size;
	bswap_block (&((*buffer)[0x18]), 4, entry_size/4 - 6);
      } else {
	/* Read a string dohm */
	if (iptr[9] == 0)
	  tnode_0->string_header_size = 16;
	else
	  /* ArtworkDB string dohms are smaller by four bytes than the comparable
	     iTunesdb string dohm. */
	  tnode_0->string_header_size = 12;

	bswap_block (&((*buffer)[0x18]), 4, tnode_0->string_header_size/4);

	/* Swap UTF-16 strings */
	if (tnode_0->string_header_size == 16) {
	  struct string_header_16 *string_header = (struct string_header_16 *)&((*buffer)[0x18]);
	  if (string_header->format != 1)
	    bswap_block (&((*buffer)[0x28]), 2, iptr[7]/2);
	} else {
	  struct string_header_12 *string_header = (struct string_header_12 *)&((*buffer)[0x18]);
	  if (string_header->format != 1)
	    bswap_block (&((*buffer)[0x24]), 2, iptr[7]/2);
	}
      }
    }
  } else if (iptr[0] == TIHM) {
    struct db_tihm *tihm_data = (struct db_tihm *)(*buffer);
    
    ipod_db->last_entry = ((ipod_db->last_entry < tihm_data->identifier)
			  ? tihm_data->identifier
			  : ipod_db->last_entry);
  } else if (iptr[0] == IIHM) {
    struct db_iihm *iihm_data = (struct db_iihm *)(*buffer);

    ipod_db->last_entry = ((ipod_db->last_entry < iihm_data->identifier)
			  ? iihm_data->identifier
			  : ipod_db->last_entry);
  }
  

  tnode_0->num_children = 0;
  tnode_0->size = copy_size;
  tnode_0->data = calloc (copy_size, 1);

{'fraction_non_alphanumeric': 0.1374671571203363, 'fraction_numerical': 0.02627430373095113, 'mean_word_length': 3.367140890316659, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3892330', 'n_tokens_mistral': 3818, 'n_tokens_neox': 3577, 'n_words': 939}