/*
 * Recursively create directory path
 * Returns 0 on success
 * NOTE: modifies path while in use
 */
int recursive_mkdir(char *dir)
{
        char *slash;
        int rc = 0;
        struct stat stat_buf;

        /* check if dir already exists */
        rc = stat(dir, &stat_buf);
        if (rc == 0) {
                if (S_ISDIR(stat_buf.st_mode)) {
                        return 0;
                } else {
                        fprintf(stderr,
                                "\"%s\" exists, but is not a directory\n", dir);
                        return 1;
                }
        }

        /* recursively check if parent directories exist */
        slash = strrchr(dir, '/');
        if (slash != NULL) {
                *slash = '\0';
                rc = recursive_mkdir(dir);
                *slash = '/';
                if (rc != 0)
                        return rc;
        }

        /* make directory */
        rc = mkdir(dir, 0777);
        if (rc != 0)
                fprintf(stderr, "mkdir(\"%s\", 0777) failed: %d\n", dir, errno);

        return rc;
}
Example #2
0
static int recursive_mkdir( vlc_object_t *p_this, const char *psz_dirname )
{/* stolen from config_CreateDir() */
    if( !psz_dirname || !*psz_dirname ) return -1;

    if( vlc_mkdir( psz_dirname, 0700 ) == 0 )
        return 0;

    switch( errno )
    {
        case EEXIST:
            return 0;

        case ENOENT:
        {
            /* Let's try to create the parent directory */
            char psz_parent[strlen( psz_dirname ) + 1], *psz_end;
            strcpy( psz_parent, psz_dirname );

            psz_end = strrchr( psz_parent, DIR_SEP_CHAR );
            if( psz_end && psz_end != psz_parent )
            {
                *psz_end = '\0';
                if( recursive_mkdir( p_this, psz_parent ) == 0 )
                {
                    if( !vlc_mkdir( psz_dirname, 0700 ) )
                        return 0;
                }
            }
        }
    }

    msg_Warn( p_this, "could not create %s: %m", psz_dirname );
    return -1;
}
int main(int argc, char **argv)
{
        int i;
        struct count_log_data log = {0, 0, NULL};

        /* Check for -h parameter before MPI_Init */
        for (i = 1; i < argc; i++) {
                if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
                        usage();
                }
        }

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
        MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);

        if (mpi_rank == 0) {
                printf("createabunch is running with %d process(es)\n", mpi_size);
                fflush(stdout);
        }


        parse_command_line(argc, argv);
        if (mpi_rank == 0 && recursive_mkdir(args.test_directory_name) != 0) {
                MPI_Abort(MPI_COMM_WORLD, 3);
        }
        enlarge_log(&log);
        createabunch(&log);
        dump_aggregate_log_data(&log);
        if (args.dump_all_tasks_data)
                dump_all_log_data(&log);

        MPI_Finalize();
        exit(0);
}
Example #4
0
struct SharedLibrary*
apk_get_shared_libraries(AndroidApk *apk, const char* libdir)
{
    assert(apk != NULL);

    char filename[PATH_MAX];
    FILE *result = NULL;
    char buf[64*1024];
    int read;
    struct SharedLibrary *libs = 0;
    struct SharedLibrary *head = 0;
    int libdirlen = strlen(libdir);

    if (unzGoToFirstFile(apk->zip) != UNZ_OK) {
        return NULL;
    }

    do {
        if (unzGetCurrentFileInfo(apk->zip, NULL, filename, sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
            if (memcmp(filename, libdir, libdirlen) == 0) {
                if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {

#if !defined(PANDORA)
                    strcpy(filename, "/home/user/.apkenv-XXXXXX");
                    int fd = mkstemp(filename);
                    result = fdopen(fd, "w+b");
#else
                    sprintf(filename,"./%s",strdup(filename));
                    recursive_mkdir(filename);
                    result = fopen(filename, "w+b");
#endif
                    while (!unzeof(apk->zip)) {
                        read = unzReadCurrentFile(apk->zip, buf, sizeof(buf));
                        if (read) {
                            assert(fwrite(buf, read, 1, result) == 1);
                        }
                    }
                    fclose(result);
                    unzCloseCurrentFile(apk->zip);
#if defined(PANDORA)
                    sync();
#endif
                    if (libs==0) {
                        libs = malloc(sizeof(struct SharedLibrary));
                        head = libs;
                        libs->next = 0;
                    } else {
                        libs->next = malloc(sizeof(struct SharedLibrary));
                        libs->next->next = 0;
                        libs = libs->next;
                    }
                    libs->filename = strdup(filename);
                }
            }
        }
    } while (unzGoToNextFile(apk->zip) == UNZ_OK);

    return head;
}
Example #5
0
/* A file in this case is a translation unit. Each .o file built with line
 * profiling enabled will emit to a different file. Only one file may be
 * started at a time.
 */
void llvm_gcda_start_file(const char *orig_filename, const char version[4],
                          uint32_t checksum) {
  const char *mode = "r+b";
  filename = mangle_filename(orig_filename);

  /* Try just opening the file. */
  new_file = 0;
  fd = open(filename, O_RDWR);

  if (fd == -1) {
    /* Try opening the file, creating it if necessary. */
    new_file = 1;
    mode = "w+b";
    fd = open(filename, O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
      /* Try creating the directories first then opening the file. */
      recursive_mkdir(filename);
      fd = open(filename, O_RDWR | O_CREAT, 0644);
      if (fd == -1) {
        /* Bah! It's hopeless. */
        int errnum = errno;
        fprintf(stderr, "profiling: %s: cannot open: %s\n", filename,
                strerror(errnum));
        return;
      }
    }
  }

  output_file = fdopen(fd, mode);

  /* Initialize the write buffer. */
  write_buffer = NULL;
  cur_buffer_size = 0;
  cur_pos = 0;

  if (new_file) {
    resize_write_buffer(WRITE_BUFFER_SIZE);
    memset(write_buffer, 0, WRITE_BUFFER_SIZE);
  } else {
    if (map_file() == -1) {
      /* mmap failed, try to recover by clobbering */
      new_file = 1;
      write_buffer = NULL;
      cur_buffer_size = 0;
      resize_write_buffer(WRITE_BUFFER_SIZE);
      memset(write_buffer, 0, WRITE_BUFFER_SIZE);
    }
  }

  /* gcda file, version, stamp checksum. */
  write_bytes("adcg", 4);
  write_bytes(version, 4);
  write_32bit_value(checksum);

#ifdef DEBUG_GCDAPROFILING
  fprintf(stderr, "llvmgcda: [%s]\n", orig_filename);
#endif
}
Example #6
0
int os_mkdirs(const char *dir)
{
	struct dstr dir_str;
	int ret;

	dstr_init_copy(&dir_str, dir);
	dstr_replace(&dir_str, "\\", "/");
	ret = recursive_mkdir(dir_str.array);
	dstr_free(&dir_str);
	return ret;
}
Example #7
0
static int InstallFile( addons_storage_t *p_this, const char *psz_downloadlink,
                        const char *psz_dest )
{
    stream_t *p_stream;
    FILE *p_destfile;
    char buffer[1<<10];
    int i_read = 0;

    p_stream = stream_UrlNew( p_this, psz_downloadlink );
    if( !p_stream )
    {
        msg_Err( p_this, "Failed to access Addon download url %s", psz_downloadlink );
        return VLC_EGENERIC;
    }

    char *psz_path = strdup( psz_dest );
    if ( !psz_path )
    {
        stream_Delete( p_stream );
        return VLC_ENOMEM;
    }
    char *psz_buf = strrchr( psz_path, DIR_SEP_CHAR );
    if( psz_buf )
    {
        *++psz_buf = '\0';
        /* ensure directory exists */
        if( !EMPTY_STR( psz_path ) ) recursive_mkdir( VLC_OBJECT(p_this), psz_path );
        free( psz_path );
    }

    p_destfile = vlc_fopen( psz_dest, "w" );
    if( !p_destfile )
    {
        msg_Err( p_this, "Failed to open Addon storage file %s", psz_dest );
        stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    while ( ( i_read = stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 )
    {
        if ( fwrite( &buffer, i_read, 1, p_destfile ) < 1 )
        {
            msg_Err( p_this, "Failed to write to Addon file" );
            fclose( p_destfile );
            stream_Delete( p_stream );
            return VLC_EGENERIC;
        }
    }

    fclose( p_destfile );
    stream_Delete( p_stream );
    return VLC_SUCCESS;
}
Example #8
0
// this function writes an IPv6 compliance warning, with its description and
// the current process stack, and writes the log
void write_problem(int is_an_error, char *title, char *content)
{
	FILE *file;
	char *directory_path_alloc, *directory_path;
	char *full_filename_alloc;

	directory_path = get_or_create_the_directory_related_to_the_thread();
	if (directory_path != NULL)
	{	
		asprintf(&directory_path_alloc, "%s/%s/%s", directory_path, 
			(is_an_error == ERROR) ? __IPV6_COMPLIANCE_ERRORS_DIR : __IPV6_COMPLIANCE_WARNINGS_DIR, 
			title);
	
		// try to create the directory
		if (recursive_mkdir(directory_path_alloc) != 0)
		{	// error already reported in recursive_mkdir()
			free(directory_path_alloc);
			return;
		}
		else
		{
			// write stack 
			write_stack_file(directory_path_alloc);

			// create problem description filename
			asprintf(&full_filename_alloc, "%s/%s", directory_path_alloc, __PROBLEM_DESCRIPTION_FILENAME); 
			free(directory_path_alloc);

			// open the file
			file = fopen(full_filename_alloc, "w");
			free(full_filename_alloc);
				
			// write content
			fprintf(file, "%s", content);
			if (interpreted_language == 1)
			{
				fprintf(file, "%s", WARNING_INTERPRETED_LANGUAGE);
			}
			
			// close
			fclose(file);

			log_if_needed();
		}
	}
}
Example #9
0
/* Returns:
 * 0  if everything was OK,
 * -1 for a general error (sets errno),
 * -2 if an existing path element was not a directory.
 */
static int
recursive_mkdir (const char *path)
{
  int loop = 0;
  int r;
  char *ppath, *p;
  struct stat buf;

 again:
  r = mkdir (path, 0777);
  if (r == -1) {
    if (errno == EEXIST) {	/* Something exists here, might not be a dir. */
      r = lstat (path, &buf);
      if (r == -1) return -1;
      if (!S_ISDIR (buf.st_mode)) return -2;
      return 0;			/* OK - directory exists here already. */
    }

    if (!loop && errno == ENOENT) {
      loop = 1;			/* Stops it looping forever. */

      /* If we're at the root, and we failed, just give up. */
      if (path[0] == '/' && path[1] == '\0') return -1;

      /* Try to make the parent directory first. */
      ppath = strdup (path);
      if (ppath == NULL) return -1;

      p = strrchr (ppath, '/');
      if (p) *p = '\0';

      r = recursive_mkdir (ppath);
      free (ppath);

      if (r != 0) return r;

      goto again;
    } else	  /* Failed for some other reason, so return error. */
      return -1;
  }
  return 0;
}
Example #10
0
int
do_mkdir_p (const char *path)
{
  int r;

  CHROOT_IN;
  r = recursive_mkdir (path);
  CHROOT_OUT;

  if (r == -1) {
    reply_with_perror ("%s", path);
    return -1;
  }
  if (r == -2) {
    reply_with_error ("%s: a path element was not a directory", path);
    return -1;
  }

  return 0;
}
Example #11
0
bool
recursive_mkdir(const string& dir, mode_t mode)
{
  struct stat sb;
  if (stat(dir.c_str(), &sb) == 0)
    return S_ISDIR(sb.st_mode);

  size_t sepIdx = dir.find_last_of('/');
  bool success = true;
  if (sepIdx != dir.npos)
    success = recursive_mkdir(dir.substr(0, sepIdx), mode);

  if (success)
  {
    success = mkdir(dir.c_str(), mode) == 0;
    success = success || (!success && errno != EEXIST);
  }

  return success;
}
Example #12
0
int
MakeDir( const char* path, int permissions )
{
    int retValue = recursive_mkdir( path, permissions );

    if ( retValue == 0 )
    {
        FLOGI( "created dir: %s", path );
    }
    else
    {
        if ( EEXIST == errno )
        {
            FLOGI( "found existing dir: %s", path );
            return 1;
        }
        else
        {
            FLOGI( "error %i creating dir: %s", errno, path );
        }
    }
    return retValue == 0 ? 1 : 0;
}
Example #13
0
static int recursive_mkdir(char *path)
{
	char *last_slash;
	int ret;

	ret = os_mkdir(path);
	if (ret != MKDIR_ERROR)
		return ret;

	last_slash = strrchr(path, '/');
	if (!last_slash)
		return MKDIR_ERROR;

	*last_slash = 0;
	ret = recursive_mkdir(path);
	*last_slash = '/';

	if (ret == MKDIR_ERROR)
		return MKDIR_ERROR;

	ret = os_mkdir(path);
	return ret;
}
Example #14
0
static FILE*
dir_fopen(const char *dir, const char *path, const char *mode)
{
    char outfn[512];
    char *p;
    int len;

    strcpy(outfn, "./");
    strcat(outfn, dir);
    len = strlen(outfn);
    if (outfn[len-1] != '/' && path[0] != '/')
        strcat(outfn, "/");
    strcat(outfn, path);

    /* If there's a directory path in there, create it */
    p = strrchr(outfn, '/');
    if (*p) {
        *p = '\0';
        recursive_mkdir(outfn);
        *p = '/';
    }

    return fopen(outfn, mode);
}
Example #15
0
static int WriteCatalog( addons_storage_t *p_storage,
                         addon_entry_t **pp_entries, int i_entries )
{
    addon_entry_t *p_entry;
    char *psz_file;
    char *psz_file_tmp;
    char *psz_tempstring;
    char *psz_userdir = config_GetUserDir( VLC_DATA_DIR );
    if ( !psz_userdir ) return VLC_ENOMEM;

    if ( asprintf( &psz_file, "%s%s", psz_userdir, ADDONS_CATALOG ) < 1 )
    {
        free( psz_userdir );
        return VLC_ENOMEM;
    }
    free( psz_userdir );

    if ( asprintf( &psz_file_tmp, "%s.tmp%"PRIu32, psz_file, (uint32_t)getpid() ) < 1 )
    {
        free( psz_file );
        return VLC_ENOMEM;
    }

    char *psz_path = strdup( psz_file );
    if ( !psz_path )
    {
        free( psz_file );
        free( psz_file_tmp );
        return VLC_ENOMEM;
    }

    char *psz_buf = strrchr( psz_path, DIR_SEP_CHAR );
    if( psz_buf )
    {
        *++psz_buf = '\0';
        /* ensure directory exists */
        if( !EMPTY_STR( psz_path ) ) recursive_mkdir( VLC_OBJECT(p_storage), psz_path );
    }
    free( psz_path );

    FILE *p_catalog = vlc_fopen( psz_file_tmp, "wt" );
    if ( !p_catalog )
    {
        free( psz_file );
        free( psz_file_tmp );
        return VLC_EGENERIC;
    }

    /* write XML header */
    fprintf( p_catalog, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
    fprintf( p_catalog, "<videolan xmlns=\"http://videolan.org/ns/vlc/addons/1.0\">\n" );
    fprintf( p_catalog, "\t<addons>\n" );

    for ( int i=0; i<i_entries; i++ )
    {
        p_entry = pp_entries[i];
        vlc_mutex_lock( &p_entry->lock );
        psz_tempstring = NULL;

        if ( ( p_entry->e_state != ADDON_INSTALLED ) ||
             !( p_entry->e_flags & ADDON_MANAGEABLE ) )
        {
            vlc_mutex_unlock( &p_entry->lock );
            continue;
        }

        if ( p_entry->psz_source_module )
            psz_tempstring = vlc_xml_encode( p_entry->psz_source_module );

        char *psz_uuid = addons_uuid_to_psz( ( const addon_uuid_t * ) & p_entry->uuid );
        fprintf( p_catalog, "\t\t<addon source=\"%s\" type=\"%s\" id=\"%s\" "
                                 "downloads=\"%ld\" score=\"%d\"",
                 ( psz_tempstring ) ? psz_tempstring : "",
                 getTypePsz( p_entry->e_type ),
                 psz_uuid,
                 p_entry->i_downloads,
                 p_entry->i_score );
        free( psz_uuid );
        free( psz_tempstring );

        WRITE_WITH_ENTITIES( " version=\"%s\"", p_entry->psz_version )
        fprintf( p_catalog, ">\n" );

        WRITE_WITH_ENTITIES( "\t\t\t<name>%s</name>\n", p_entry->psz_name )
        WRITE_WITH_ENTITIES( "\t\t\t<summary>%s</summary>\n", p_entry->psz_summary )

        if ( p_entry->psz_description )
        {
            psz_tempstring = p_entry->psz_description;
            /* FIXME: do real escaping */
            while( ( psz_tempstring = strstr( psz_tempstring, "]]>" ) ) )
                *psz_tempstring = ' ';
            fprintf( p_catalog, "\t\t\t<description><![CDATA[%s]]></description>\n", p_entry->psz_description );
        }

        WRITE_WITH_ENTITIES( "\t\t\t<image>%s</image>\n", p_entry->psz_image_data )
        WRITE_WITH_ENTITIES( "\t\t\t<archive>%s</archive>\n", p_entry->psz_archive_uri )

        fprintf( p_catalog, "\t\t\t<authorship>\n" );
        WRITE_WITH_ENTITIES( "\t\t\t\t<creator>%s</creator>\n", p_entry->psz_author )
        WRITE_WITH_ENTITIES( "\t\t\t\t<sourceurl>%s</sourceurl>\n", p_entry->psz_source_uri )
        fprintf( p_catalog, "\t\t\t</authorship>\n" );

        FOREACH_ARRAY( addon_file_t *p_file, p_entry->files )
            psz_tempstring = vlc_xml_encode( p_file->psz_filename );
            fprintf( p_catalog, "\t\t\t<resource type=\"%s\">%s</resource>\n",
                     getTypePsz( p_file->e_filetype ), psz_tempstring );
            free( psz_tempstring );
        FOREACH_END();

        fprintf( p_catalog, "\t\t</addon>\n" );

        vlc_mutex_unlock( &p_entry->lock );
    }

    fprintf( p_catalog, "\t</addons>\n" );
    fprintf( p_catalog, "</videolan>\n" );
    fclose( p_catalog );

    int i_ret = vlc_rename( psz_file_tmp, psz_file );
    free( psz_file );
    free( psz_file_tmp );

    if( i_ret == -1 )
    {
        msg_Err( p_storage, "could not rename temp catalog: %s",
                 vlc_strerror_c(errno) );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Example #16
0
int
nandroid_back_exe()
{
    SetDataState("Starting", "backup", 0, 0);

    if (ensure_path_mounted(SDCARD_ROOT) != 0) {
        ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT);
        SetDataState("Unable to mount", "/sdcard", 1, 1);
        return 1;
    }

    // Create backup folder
    struct tm *t;
    char timestamp[64];
    char image_dir[255];
    char exe[255];
    time_t start, stop;
    time_t seconds;
    seconds = time(0);
    t = localtime(&seconds);
    sprintf(timestamp,"%04d-%02d-%02d--%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); // make time stamp
    sprintf(image_dir,"%s/%s/%s/", backup_folder, device_id, timestamp); // for backup folder

    if (recursive_mkdir(image_dir))
    {
        LOGE("Unable to create folder: '%s'\n", backup_folder);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }

    // Record the start time
    time(&start);

    // Prepare operation
    ui_print("\n[BACKUP STARTED]\n");
    ui_print(" * Backup Folder: %s\n", backup_folder);
    ui_print(" * Verifying filesystems...\n");
    verifyFst();
    createFstab();
    ui_print(" * Verifying partition sizes...\n");
    updateUsedSized();
    unsigned long long sdc_free = sdcext.sze - sdcext.used;

    // Compute totals
    int total = 0;
    unsigned long long total_img_bytes = 0, total_file_bytes = 0;
    CalculateBackupDetails(&total, &total_img_bytes, &total_file_bytes);
    unsigned long long total_bytes = total_img_bytes + total_file_bytes;

    if (total == 0 || total_bytes == 0)
    {
        LOGE("Unable to compute target usage (%d partitions, %llu bytes)\n", total, total_bytes);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }

    ui_print(" * Total number of partition to back up: %d\n", total);
    ui_print(" * Total size of all data, in KB: %llu\n", total_bytes / 1024);
    ui_print(" * Available space on the SD card, in KB: %llu\n", sdc_free / 1024);

    // We can't verify sufficient space on devices where sdcard is a portion of the data partition
#ifndef RECOVERY_SDCARD_ON_DATA
    // Verify space
    if (sdc_free < (total_bytes + 0x2000000))       // We require at least 32MB of additional space
    {
        LOGE("Insufficient space on SDCARD. Required space is %lluKB, available %lluKB\n", (total_bytes + 0x2000000) / 1024, sdc_free / 1024);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }
#else
    ui_print(" * This device does not support verifying available free space.\n");
#endif

    // Prepare progress bar...
    unsigned long long img_bytes_remaining = total_img_bytes;
    unsigned long long file_bytes_remaining = total_file_bytes;
    unsigned long img_byte_time = 0, file_byte_time = 0;
    struct stat st;

    ui_set_progress(0.0);

    // SYSTEM
    if (phx_do_backup(VAR_BACKUP_SYSTEM_VAR, &sys, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))       return 1;

    // DATA
    if (phx_do_backup(VAR_BACKUP_DATA_VAR, &dat, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))         return 1;

    // BOOT
    if (phx_do_backup(VAR_BACKUP_BOOT_VAR, &boo, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))         return 1;

    // RECOVERY
    if (phx_do_backup(VAR_BACKUP_RECOVERY_VAR, &rec, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))     return 1;

    // CACHE
    if (phx_do_backup(VAR_BACKUP_CACHE_VAR, &cac, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))        return 1;

    // SP1
    if (phx_do_backup(VAR_BACKUP_SP1_VAR, &sp1, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // SP2
    if (phx_do_backup(VAR_BACKUP_SP2_VAR, &sp2, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // SP3
    if (phx_do_backup(VAR_BACKUP_SP3_VAR, &sp3, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // ANDROID-SECURE
    if (stat(ase.dev, &st) ==0)
        if (phx_do_backup(VAR_BACKUP_ANDSEC_VAR, &ase, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))       return 1;

    // SD-EXT
    if (stat(sde.dev, &st) ==0)
        if (phx_do_backup(VAR_BACKUP_SDEXT_VAR, &sde, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))        return 1;

    ui_print(" * Verifying filesystems...\n");
    verifyFst();
    createFstab();
    ui_print(" * Verifying partition sizes...\n");
    updateUsedSized();

    time(&stop);

    // Average BPS
    unsigned long int img_bps = total_img_bytes / img_byte_time;
    unsigned long int file_bps = total_file_bytes / file_byte_time;

    LOGI("img_bps = %lu  total_img_bytes = %llu  img_byte_time = %lu\n", img_bps, total_img_bytes, img_byte_time);
    ui_print("Average backup rate for file systems: %lu MB/sec\n", (file_bps / (1024 * 1024)));
    ui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));

    if (DataManager_GetIntValue(VAR_SKIP_MD5_GENERATE_VAR) == 1)
    {
        // If we're skipping MD5 generation, our BPS is faster by about 1.65
        file_bps = (unsigned long) (file_bps / 1.65);
        img_bps = (unsigned long) (img_bps / 1.65);
    }

    img_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_IMG_RATE) * 4);
    img_bps /= 5;

    if (DataManager_GetIntValue(VAR_USE_COMPRESSION_VAR))    file_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_COMP_RATE) * 4);
    else                                                    file_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_RATE) * 4);
    file_bps /= 5;

    DataManager_SetIntValue(VAR_BACKUP_AVG_IMG_RATE, img_bps);
    if (DataManager_GetIntValue(VAR_USE_COMPRESSION_VAR))    DataManager_SetIntValue(VAR_BACKUP_AVG_FILE_COMP_RATE, file_bps);
    else                                                    DataManager_SetIntValue(VAR_BACKUP_AVG_FILE_RATE, file_bps);

    int total_time = (int) difftime(stop, start);
    unsigned long long new_sdc_free = (sdcext.sze - sdcext.used) / (1024 * 1024);
    sdc_free /= (1024 * 1024);

    ui_print("[%lu MB TOTAL BACKED UP TO SDCARD]\n",(unsigned long) (sdc_free - new_sdc_free));
    ui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
    SetDataState("Backup Succeeded", "", 0, 1);
    return 0;
}
Example #17
0
File: tar.c Project: calccrypto/tar
int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
    V_PRINT(stdout, "%s\n", entry -> name);

    if ((entry -> type == REGULAR) || (entry -> type == NORMAL) || (entry -> type == CONTIGUOUS)){
        // create intermediate directories
        size_t len = strlen(entry -> name);
        char * path = calloc(len + 1, sizeof(char));
        strncpy(path, entry -> name, len);

        // remove file from path
        while (--len && (path[len] != '/'));
        path[len] = '\0';   // if nothing was found, path is terminated

        if (recursive_mkdir(path, DEFAULT_DIR_MODE, verbosity) < 0){
            V_PRINT(stderr, "Error: Could not make directory %s\n", path);
            free(path);
            return -1;
        }
        free(path);

        if ((entry -> type == REGULAR) || (entry -> type == NORMAL) || (entry -> type == CONTIGUOUS)){
            // create file
            const unsigned int size = oct2uint(entry -> size, 11);
            int f = open(entry -> name, O_WRONLY | O_CREAT | O_TRUNC, oct2uint(entry -> mode, 7) & 0777);
            if (f < 0){
                RC_ERROR(stderr, "Error: Unable to open file %s: %s\n", entry -> name, strerror(rc));
            }

            // move archive pointer to data location
            if (lseek(fd, 512 + entry -> begin, SEEK_SET) == (off_t) (-1)){
                RC_ERROR(stderr, "Error: Bad index: %s\n", strerror(rc));
            }

            // copy data to file
            char buf[512];
            int got = 0;
            while (got < size){
                int r;
                if ((r = read_size(fd, buf, MIN(size - got, 512))) < 0){
                    EXIST_ERROR(stderr, "Error: Unable to read from archive: %s\n", strerror(rc));
                }

                if (write(f, buf, r) != r){
                    EXIST_ERROR(stderr, "Error: Unable to write to %s: %s\n", entry -> name, strerror(rc));
                }

                got += r;
            }

            close(f);
        }
        else if ((entry -> type == CHAR) || (entry -> type == BLOCK)){
            if (mknod(entry -> name, oct2uint(entry -> mode, 7), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
                EXIST_ERROR(stderr, "Error: Unable to make device %s: %s\n", entry -> name, strerror(rc));
            }
        }
    }
    else if (entry -> type == HARDLINK){
        if (link(entry -> link_name, entry -> name) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create hardlink %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == SYMLINK){
        if (symlink(entry -> link_name, entry -> name) < 0){
            EXIST_ERROR(stderr, "Error: Unable to make symlink %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == CHAR){
        if (mknod(entry -> name, S_IFCHR | (oct2uint(entry -> mode, 7) & 0777), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == BLOCK){
        if (mknod(entry -> name, S_IFBLK | (oct2uint(entry -> mode, 7) & 0777), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == DIRECTORY){
        if (recursive_mkdir(entry -> name, oct2uint(entry -> mode, 7) & 0777, verbosity) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == FIFO){
        if (mkfifo(entry -> name, oct2uint(entry -> mode, 7) & 0777) < 0){
            EXIST_ERROR(stderr, "Error: Unable to make pipe %s: %s\n", entry -> name, strerror(rc));
        }
    }
    return 0;
}
Example #18
0
/* A file in this case is a translation unit. Each .o file built with line
 * profiling enabled will emit to a different file. Only one file may be
 * started at a time.
 */
void llvm_gcda_start_file(const char *orig_filename, const char version[4],
                          uint32_t checksum) {
  const char *mode = "r+b";
  filename = mangle_filename(orig_filename);

  /* Try just opening the file. */
  new_file = 0;
  fd = open(filename, O_RDWR);

  if (fd == -1) {
    /* Try opening the file, creating it if necessary. */
    new_file = 1;
    mode = "w+b";
    fd = open(filename, O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
      /* Try creating the directories first then opening the file. */
      recursive_mkdir(filename);
      fd = open(filename, O_RDWR | O_CREAT, 0644);
      if (fd == -1) {
        /* Bah! It's hopeless. */
        int errnum = errno;
        fprintf(stderr, "profiling: %s: cannot open: %s\n", filename,
                strerror(errnum));
        return;
      }
    }
  }

  /* Try to flock the file to serialize concurrent processes writing out to the
   * same GCDA. This can fail if the filesystem doesn't support it, but in that
   * case we'll just carry on with the old racy behaviour and hope for the best.
   */
  flock(fd, LOCK_EX);
  output_file = fdopen(fd, mode);

  /* Initialize the write buffer. */
  write_buffer = NULL;
  cur_buffer_size = 0;
  cur_pos = 0;

  if (new_file) {
    resize_write_buffer(WRITE_BUFFER_SIZE);
    memset(write_buffer, 0, WRITE_BUFFER_SIZE);
  } else {
    if (map_file() == -1) {
      /* mmap failed, try to recover by clobbering */
      new_file = 1;
      write_buffer = NULL;
      cur_buffer_size = 0;
      resize_write_buffer(WRITE_BUFFER_SIZE);
      memset(write_buffer, 0, WRITE_BUFFER_SIZE);
    }
  }

  /* gcda file, version, stamp checksum. */
  write_bytes("adcg", 4);
  write_bytes(version, 4);
  write_32bit_value(checksum);

#ifdef DEBUG_GCDAPROFILING
  fprintf(stderr, "llvmgcda: [%s]\n", orig_filename);
#endif
}
Example #19
0
int start_ripping_gui(int ripping_flags)
{
    char *albumdir, *musicfilename, *file_path = 0;
    sacd_reader_t   *sacd_reader;
    scarletbook_handle_t *handle;
    scarletbook_output_t *output;
    msgType          dialog_type;
    int              area_idx, i, ret;

    uint32_t prev_upper_progress = 0;
    uint32_t prev_lower_progress = 0;
    uint32_t delta;

    int prev_current_track = 0;
    uint32_t prev_stats_total_sectors_processed = 0;
    uint32_t prev_stats_current_file_sectors_processed = 0;
    uint64_t tb_start, tb_freq;
    uint64_t tmp_total_ripping_sectors = 0;

    char progress_message[64];

    sysAtomicSet(&stats_total_sectors, 0);
    sysAtomicSet(&stats_total_sectors_processed, 0);
    sysAtomicSet(&stats_current_file_total_sectors, 0);
    sysAtomicSet(&stats_current_file_sectors_processed, 0); 
    sysAtomicSet(&stats_current_track, 0);
    sysAtomicSet(&stats_total_tracks, 0);

    sacd_reader = sacd_open("/dev_bdvd");
    if (sacd_reader) 
    {
        handle = scarletbook_open(sacd_reader, 0);

        if (check_disc_space(sacd_reader, handle, ripping_flags))
        {
            ret = sacd_authenticate(sacd_reader);
            if (ret != 0)
            {
                LOG(lm_main, LOG_ERROR, ("authentication failed: %x", ret));
            }

            // select the channel area
            area_idx = ((has_multi_channel(handle) && ripping_flags & RIP_MCH) || !has_two_channel(handle)) ? handle->mulch_area_idx : handle->twoch_area_idx;

            albumdir = get_album_dir(handle);

            output = scarletbook_output_create(handle, handle_status_update_track_callback, handle_status_update_progress_callback, safe_fwprintf);

            if (ripping_flags & RIP_ISO)
            {
                #define FAT32_SECTOR_LIMIT 2090000
                uint32_t total_sectors = sacd_get_total_sectors(sacd_reader);
                uint32_t sector_size = FAT32_SECTOR_LIMIT;
                uint32_t sector_offset = 0;
                if (total_sectors > FAT32_SECTOR_LIMIT)
                 {
                    musicfilename = (char *) malloc(512);
                    file_path = make_filename(output_device, 0, albumdir, "iso");
                    for (i = 1; total_sectors != 0; i++)
                    {
                        sector_size = min(total_sectors, FAT32_SECTOR_LIMIT);
                        snprintf(musicfilename, 512, "%s.%03d", file_path, i);
                        scarletbook_output_enqueue_raw_sectors(output, sector_offset, sector_size, musicfilename, "iso");
                        sector_offset += sector_size;
                        total_sectors -= sector_size;
                    }
                    free(file_path);
                    free(musicfilename);
                }
                else
                {
                    file_path = make_filename(output_device, 0, albumdir, "iso");
                    scarletbook_output_enqueue_raw_sectors(output, 0, total_sectors, file_path, "iso");
                    free(file_path);
                }
                tmp_total_ripping_sectors = sacd_get_total_sectors(sacd_reader);
            }
            else 
            {
                // do not overwrite previous dump
                get_unique_dir(output_device, &albumdir);

                // fill the queue with items to rip
                for (i = 0; i < handle->area[area_idx].area_toc->track_count; i++) 
                {
                    musicfilename = get_music_filename(handle, area_idx, i, 0);
                    if (ripping_flags & RIP_DSF)
                    {
                        file_path = make_filename(output_device, albumdir, musicfilename, "dsf");
                        scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsf", 
                            1 /* always decode to DSD */);
                    }
                    else if (ripping_flags & RIP_DSDIFF)
                    {
                        file_path = make_filename(output_device, albumdir, musicfilename, "dff");
                        scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsdiff", 
                            ((ripping_flags & RIP_2CH_DST || ripping_flags & RIP_MCH_DST) ? 0 : 1));
                    }

                    tmp_total_ripping_sectors += handle->area[area_idx].area_tracklist_offset->track_length_lsn[i];

                    free(musicfilename);
                    free(file_path);
                }

                file_path = make_filename(output_device, albumdir, 0, 0);
                LOG(lm_main, LOG_NOTICE, ("setting output folder to: %s", file_path));
                recursive_mkdir(file_path, 0777);
                free(file_path);
            }

            scarletbook_output_start(output);

            tb_freq = sysGetTimebaseFrequency();
            tb_start = __gettime(); 

            {
                char *message = (char *) malloc(512);

                file_path = make_filename(output_device, albumdir, 0, 0);
                snprintf(message, 512, "Title: %s\nOutput: %s\nFormat: %s\nSize: %.2fGB\nArea: %s\nEncoding: %s", 
                        substr(albumdir, 0, 100), 
                        file_path, 
                        (ripping_flags & RIP_DSDIFF ? "DSDIFF" : (ripping_flags & RIP_DSF ? "DSF" : "ISO")),
                        ((double) ((tmp_total_ripping_sectors * SACD_LSN_SIZE) / 1073741824.00)),
                        (ripping_flags & RIP_2CH ? "2ch" : "mch"),
                        (ripping_flags & RIP_2CH_DST || ripping_flags & RIP_MCH_DST ? "DST" : (ripping_flags & RIP_ISO ? "DECRYPTED" : "DSD"))
                        );
                free(file_path);

                dialog_action = 0;
                dialog_type   = MSG_DIALOG_MUTE_ON | MSG_DIALOG_DOUBLE_PROGRESSBAR;
                msgDialogOpen2(dialog_type, message, dialog_handler, NULL, NULL);
                while (!user_requested_exit() && dialog_action == 0 && scarletbook_output_is_busy(output))
                {
                    uint32_t tmp_stats_total_sectors_processed = sysAtomicRead(&stats_total_sectors_processed);
                    uint32_t tmp_stats_total_sectors = sysAtomicRead(&stats_total_sectors);
                    uint32_t tmp_stats_current_file_sectors_processed = sysAtomicRead(&stats_current_file_sectors_processed);
                    uint32_t tmp_stats_current_file_total_sectors = sysAtomicRead(&stats_current_file_total_sectors);
                    int tmp_current_track = sysAtomicRead(&stats_current_track);

                    if (tmp_current_track != 0 && tmp_current_track != prev_current_track)
                    {
                        memset(progress_message, 0, 64);
       
                        musicfilename = get_music_filename(handle, area_idx, tmp_current_track - 1, 0);
                        // HACK: substr is not thread safe, but it's only used in this thread..
                        snprintf(progress_message, 63, "Track (%d/%d): [%s...]", tmp_current_track, sysAtomicRead(&stats_total_tracks), substr(musicfilename, 0, 40));
                        free(musicfilename);

                        msgDialogProgressBarReset(MSG_PROGRESSBAR_INDEX0);
                        msgDialogProgressBarSetMsg(MSG_PROGRESSBAR_INDEX1, progress_message);
                        prev_upper_progress = 0;
                        prev_stats_current_file_sectors_processed = 0;

                        prev_current_track = tmp_current_track;
                    }

                    if (tmp_stats_total_sectors != 0 && prev_stats_total_sectors_processed != tmp_stats_total_sectors_processed)
                    {
                        delta = (tmp_stats_current_file_sectors_processed + (tmp_stats_current_file_sectors_processed - prev_stats_current_file_sectors_processed)) * 100 / tmp_stats_current_file_total_sectors - prev_upper_progress;
                        prev_upper_progress += delta;
                        msgDialogProgressBarInc(MSG_PROGRESSBAR_INDEX0, delta);

                        delta = (tmp_stats_total_sectors_processed + (tmp_stats_total_sectors_processed - prev_stats_total_sectors_processed)) * 100 / tmp_stats_total_sectors - prev_lower_progress;
                        prev_lower_progress += delta;
                        msgDialogProgressBarInc(MSG_PROGRESSBAR_INDEX1, delta);

                        snprintf(progress_message, 64, "Ripping %.1fMB/%.1fMB at %.2fMB/sec", 
                                ((float)(tmp_stats_current_file_sectors_processed * SACD_LSN_SIZE) / 1048576.00),
                                ((float)(tmp_stats_current_file_total_sectors * SACD_LSN_SIZE) / 1048576.00),
                                (float)((float) tmp_stats_total_sectors_processed * SACD_LSN_SIZE / 1048576.00) / (float)((__gettime() - tb_start) / (float)(tb_freq)));
                        
                        msgDialogProgressBarSetMsg(MSG_PROGRESSBAR_INDEX0, progress_message);
                        
                        prev_stats_total_sectors_processed = tmp_stats_total_sectors_processed;
                        prev_stats_current_file_sectors_processed = tmp_stats_current_file_sectors_processed;
                    }

                    sysUtilCheckCallback();
                    flip();
                }
                msgDialogAbort();
                free(message);
            }
            free(albumdir);

            scarletbook_output_destroy(output);
        }
        scarletbook_close(handle);
    }
    sacd_close(sacd_reader);

    if (user_requested_exit())
    {
        return 0;
    }
    else if (1)
    {
        dialog_type = (MSG_DIALOG_NORMAL | MSG_DIALOG_BTN_TYPE_OK | MSG_DIALOG_DISABLE_CANCEL_ON);
        msgDialogOpen2(dialog_type, "ripping process completed.", dialog_handler, NULL, NULL);

        dialog_action = 0;
        while (!dialog_action && !user_requested_exit())
        {
            sysUtilCheckCallback();
            flip();
        }
        msgDialogAbort();
    }

    return 0;
}
Example #20
0
int main(int argc, char* argv[]) 
{
    char *albumdir = 0, *musicfilename, *file_path = 0;
    int i, area_idx;
    sacd_reader_t *sacd_reader;

#ifdef PTW32_STATIC_LIB
    pthread_win32_process_attach_np();
    pthread_win32_thread_attach_np();
#endif

    init();
    if (parse_options(argc, argv)) 
    {
        setlocale(LC_ALL, "");
        if (fwide(stdout, 1) < 0)
        {
            fprintf(stderr, "ERROR: Output not set to wide.\n");
        }

        // default to 2 channel
        if (opts.two_channel == 0 && opts.multi_channel == 0) 
        {
            opts.two_channel = 1;
        }

        sacd_reader = sacd_open(opts.input_device);
        if (sacd_reader) 
        {

            handle = scarletbook_open(sacd_reader, 0);
            if (handle)
            {
                if (opts.print)
                {
                    scarletbook_print(handle);
                }

                if (opts.output_dsf || opts.output_iso || opts.output_dsdiff || opts.output_dsdiff_em || opts.export_cue_sheet)
                {
                    output = scarletbook_output_create(handle, handle_status_update_track_callback, handle_status_update_progress_callback, safe_fwprintf);

                    // select the channel area
                    area_idx = ((has_multi_channel(handle) && opts.multi_channel) || !has_two_channel(handle)) ? handle->mulch_area_idx : handle->twoch_area_idx;

                    albumdir = (strlen(opts.output_file) > 0 ? strdup(opts.output_file) : get_album_dir(handle));

                    if (opts.output_iso)
                    {
                        uint32_t total_sectors = sacd_get_total_sectors(sacd_reader);
#ifdef SECTOR_LIMIT
#define FAT32_SECTOR_LIMIT 2090000
                        uint32_t sector_size = FAT32_SECTOR_LIMIT;
                        uint32_t sector_offset = 0;
                        if (total_sectors > FAT32_SECTOR_LIMIT)
                        {
                            musicfilename = (char *) malloc(512);
                            file_path = make_filename(0, 0, albumdir, "iso");
                            for (i = 1; total_sectors != 0; i++)
                            {
                                sector_size = min(total_sectors, FAT32_SECTOR_LIMIT);
                                snprintf(musicfilename, 512, "%s.%03d", file_path, i);
                                scarletbook_output_enqueue_raw_sectors(output, sector_offset, sector_size, musicfilename, "iso");
                                sector_offset += sector_size;
                                total_sectors -= sector_size;
                            }
                            free(musicfilename);
                        }
                        else
#endif
                        {
                            get_unique_filename(&albumdir, "iso");
                            file_path = make_filename(0, 0, albumdir, "iso");
                            scarletbook_output_enqueue_raw_sectors(output, 0, total_sectors, file_path, "iso");
                        }
                    }
                    else if (opts.output_dsdiff_em)
                    {
                        get_unique_filename(&albumdir, "dff");
                        file_path = make_filename(0, 0, albumdir, "dff");

                        scarletbook_output_enqueue_track(output, area_idx, 0, file_path, "dsdiff_edit_master", 
                            (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST));
                    }
                    else if (opts.output_dsf || opts.output_dsdiff)
                    {
                        // create the output folder
                        get_unique_dir(0, &albumdir);
                        recursive_mkdir(albumdir, 0774);

                        // fill the queue with items to rip
                        for (i = 0; i < handle->area[area_idx].area_toc->track_count; i++) 
                        {
                            if (opts.select_tracks && opts.selected_tracks[i] == 0)
                                continue;

                            musicfilename = get_music_filename(handle, area_idx, i, opts.output_file);

                            if (opts.output_dsf)
                            {
                                file_path = make_filename(0, albumdir, musicfilename, "dsf");
                                scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsf", 
                                    1 /* always decode to DSD */);
                            }
                            else if (opts.output_dsdiff)
                            {
                                file_path = make_filename(0, albumdir, musicfilename, "dff");
                                scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsdiff", 
                                    (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST));
                            }

                            free(musicfilename);
                            free(file_path);
                            file_path = 0;
                        }
                    }

                    if (opts.export_cue_sheet)
                    {
                        char *cue_file_path = make_filename(0, 0, albumdir, "cue");
#ifdef _WIN32
                        wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", sizeof(wchar_t) == 2 ? "UCS-2-INTERNAL" : "UCS-4-INTERNAL");
#else
                        wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", "WCHAR_T");
#endif
                        fwprintf(stdout, L"Exporting CUE sheet [%ls]\n", wide_filename);
                        if (!file_path)
                            file_path = make_filename(0, 0, albumdir, "dff");
                        write_cue_sheet(handle, file_path, area_idx, cue_file_path);
                        free(cue_file_path);
                        free(wide_filename);
                    }

                    free(file_path);

                    started_processing = time(0);
                    scarletbook_output_start(output);
                    scarletbook_output_destroy(output);

                    fprintf(stdout, "\rWe are done..                                                          \n");
                }
                scarletbook_close(handle);

                free(albumdir);
            }
        }

        sacd_close(sacd_reader);

#ifndef _WIN32
        freopen(0, "w", stdout);
#endif
        if (fwide(stdout, -1) >= 0)
        {
            fprintf(stderr, "ERROR: Output not set to byte oriented.\n");
        }
    }

    free_lock(g_fwprintf_lock);
    destroy_logging();

#ifdef PTW32_STATIC_LIB
    pthread_win32_process_detach_np();
    pthread_win32_thread_detach_np();
#endif

    printf("\n");
    return 0;
}
Example #21
0
void mkpath (char *path) {
    recursive_mkdir (path);
}
Example #22
0
struct SharedLibrary*
apk_get_shared_libraries(AndroidApk *apk, const char *libdir, const char *datadir)
{
    assert(apk != NULL);

    char filename[PATH_MAX];
    char pathname[PATH_MAX];
    FILE *result = NULL;
    char buf[64*1024];
    int read;
    struct SharedLibrary *libs = 0;
    struct SharedLibrary *head = 0;
    int libdirlen = strlen(libdir);
    char *p;

    if (unzGoToFirstFile(apk->zip) != UNZ_OK) {
        return NULL;
    }

    do {
        if (unzGetCurrentFileInfo(apk->zip, NULL, filename, sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
            if (memcmp(filename, libdir, libdirlen) == 0) {
                if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {

                    snprintf(pathname, sizeof(pathname), "%s%s", datadir, filename);
                    recursive_mkdir(pathname);
                    result = fopen(pathname, "w+b");
                    if (result == NULL) {
                        fprintf(stderr, "can't open %s for writing\n", pathname);
                        unzCloseCurrentFile(apk->zip);
                        break;
                    }
                    while (!unzeof(apk->zip)) {
                        read = unzReadCurrentFile(apk->zip, buf, sizeof(buf));
                        if (read) {
                            assert(fwrite(buf, read, 1, result) == 1);
                        }
                    }
                    fclose(result);
                    unzCloseCurrentFile(apk->zip);

                    if (libs==0) {
                        libs = malloc(sizeof(struct SharedLibrary));
                        head = libs;
                        libs->next = 0;
                    } else {
                        libs->next = malloc(sizeof(struct SharedLibrary));
                        libs->next->next = 0;
                        libs = libs->next;
                    }
                    libs->filename = strdup(pathname);
                    p = strrchr(pathname, '/');
                    *p = 0;
                    libs->dirname = strdup(pathname);
                }
            }
        }
    } while (unzGoToNextFile(apk->zip) == UNZ_OK);

    return head;
}