예제 #1
0
/* Called by ares library for upload state changes. */
static as_bool up_state_cb (ASUpMan *man, ASUpload *up,
                            ASUploadState state)
{
	Share *share = up->share->udata;
	Chunk *chunk;
	Transfer *transfer;

#if 1
	AS_HEAVY_DBG_2("Upload state for %s: %s", net_ip_str (up->host),
	               as_upload_state_str (up));
#endif

	switch (state)
	{
	case UPLOAD_ACTIVE:
		transfer = PROTO->upload_start (PROTO, &chunk, upload_to_user (up),
		                                share, up->start, up->stop);

		if (!transfer)
		{
			AS_ERR_1 ("Failed to create giFT transfer object for upload to %s",
			          net_ip_str (up->host));
			as_upman_cancel (AS->upman, up);
			as_upman_remove (AS->upman, up);
			return FALSE; /* Upload was freed. */
		}

		assert (chunk->transfer == transfer);
		
		up->udata = chunk;
		chunk->udata = up;

		/* Register send progress and throttle callbacks. */
		as_upload_set_data_cb (up, up_data_cb);
		as_upload_set_throttle_cb (up, up_throttle_cb);

		break;
	case UPLOAD_COMPLETE:
		/* This should never happen since we return FALSE from up_data_cb. */
		assert (0);
		/* May make giFT call asp_giftcb_upload_stop. */
		send_progress (up);
		break;
	case UPLOAD_FAILED:
	case UPLOAD_CANCELLED:
		/* Makes giFT call asp_giftcb_upload_stop. */
		wrote (up, 0);
		return FALSE;
	default:
		abort ();
	}

	return TRUE;
}
예제 #2
0
파일: worker.c 프로젝트: EQ4/samplecat
static gpointer
worker_thread(gpointer data)
{
	//TODO consider replacing the main loop with a blocking call on the async queue,
	//(g_async_queue_pop) waiting for messages.

	dbg(1, "new worker thread.");

	g_async_queue_ref(msg_queue);

	bool done(gpointer _message)
	{
		Message* message = _message;
		message->done(message->sample, message->user_data);

		send_progress(GINT_TO_POINTER(g_list_length(msg_list)));

		sample_unref(message->sample);
		g_free(message);
		return G_SOURCE_REMOVE;
	}
예제 #3
0
void recurse_dir(MediaScan *s, const char *path, int recurse_count) {
  char *dir, *p;
  char tmp_full_path[MAX_PATH_STR_LEN];
  DIR *dirp;
  struct dirent *dp;
  struct dirq *subdirq;         // list of subdirs of the current directory
  struct dirq_entry *parent_entry = NULL; // entry for current dir in s->_dirq
  char redirect_dir[MAX_PATH_STR_LEN];

  if (recurse_count > RECURSE_LIMIT) {
    LOG_ERROR("Hit recurse limit of %d scanning path %s\n", RECURSE_LIMIT, path);
    return;
  }

  if (path[0] != '/') {         // XXX Win32
    // Get full path
    char *buf = (char *)malloc((size_t)MAX_PATH_STR_LEN);
    if (buf == NULL) {
      FATAL("Out of memory for directory scan\n");
      return;
    }

    dir = getcwd(buf, (size_t)MAX_PATH_STR_LEN);
    strcat(dir, "/");
    strcat(dir, path);
  }
  else {
#ifdef USING_TCMALLOC
    // strdup will cause tcmalloc to crash on free
    dir = (char *)malloc((size_t)MAX_PATH_STR_LEN);
    strcpy(dir, path);
#else
    dir = strdup(path);
#endif
  }

  // Strip trailing slash if any
  p = &dir[0];
  while (*p != 0) {
    if (p[1] == 0 && *p == '/')
      *p = 0;
    p++;
  }

  LOG_INFO("Recursed into %s\n", dir);

#if defined(__APPLE__)
  if (isAlias(dir)) {
    if (CheckMacAlias(dir, redirect_dir)) {
      LOG_INFO("Resolving Alias %s to %s\n", dir, redirect_dir);
      strcpy(dir, redirect_dir);
    }
    else {
      LOG_ERROR("Failure to follow symlink or alias, skipping directory\n");
      goto out;
    }
  }
#elif defined(__linux__)
  if (isAlias(dir)) {
    FollowLink(dir, redirect_dir);
    LOG_INFO("Resolving symlink %s to %s\n", dir, redirect_dir);
    strcpy(dir, redirect_dir);
  }
#endif

  if ((dirp = opendir(dir)) == NULL) {
    LOG_ERROR("Unable to open directory %s: %s\n", dir, strerror(errno));
    goto out;
  }

  subdirq = malloc(sizeof(struct dirq));
  SIMPLEQ_INIT(subdirq);

  while ((dp = readdir(dirp)) != NULL) {
    char *name = dp->d_name;

    // skip all dot files
    if (name[0] != '.') {
      // Check if scan should be aborted
      if (unlikely(s->_want_abort))
        break;

      // XXX some platforms may be missing d_type/DT_DIR
      if (dp->d_type == DT_DIR) {
        // Add to list of subdirectories we need to recurse into
        struct dirq_entry *subdir_entry = malloc(sizeof(struct dirq_entry));

        // Construct full path
        //*tmp_full_path = 0;
        strcpy(tmp_full_path, dir);
        strcat(tmp_full_path, "/");
        strcat(tmp_full_path, name);

        if (_should_scan_dir(s, tmp_full_path)) {
          subdir_entry->dir = strdup(tmp_full_path);
          SIMPLEQ_INSERT_TAIL(subdirq, subdir_entry, entries);

          LOG_INFO(" subdir: %s\n", tmp_full_path);
        }
        else {
          LOG_INFO(" skipping subdir: %s\n", tmp_full_path);
        }
      }
      else {
        enum media_type type = _should_scan(s, name);

        LOG_INFO("name %s = type %d\n", name, type);

        if (type) {
          struct fileq_entry *entry;

          // Check if this file is a shortcut and if so resolve it
#if defined(__APPLE__)
          if (isAlias(name)) {
            char full_name[MAX_PATH_STR_LEN];

            LOG_INFO("Mac Alias detected\n");

            strcpy(full_name, dir);
            strcat(full_name, "\\");
            strcat(full_name, name);
            parse_lnk(full_name, redirect_dir, MAX_PATH_STR_LEN);
            if (PathIsDirectory(redirect_dir)) {
              struct dirq_entry *subdir_entry = malloc(sizeof(struct dirq_entry));

              subdir_entry->dir = strdup(redirect_dir);
              SIMPLEQ_INSERT_TAIL(subdirq, subdir_entry, entries);

              LOG_INFO(" subdir: %s\n", tmp_full_path);
              type = 0;
            }

          }
#elif defined(__linux__)
          if (isAlias(name)) {
            char full_name[MAX_PATH_STR_LEN];

            printf("Linux Alias detected\n");

            strcpy(full_name, dir);
            strcat(full_name, "\\");
            strcat(full_name, name);
            FollowLink(full_name, redirect_dir);
            if (PathIsDirectory(redirect_dir)) {
              struct dirq_entry *subdir_entry = malloc(sizeof(struct dirq_entry));

              subdir_entry->dir = strdup(redirect_dir);
              SIMPLEQ_INSERT_TAIL(subdirq, subdir_entry, entries);

              LOG_INFO(" subdir: %s\n", tmp_full_path);
              type = 0;
            }

          }
#endif
          if (parent_entry == NULL) {
            // Add parent directory to list of dirs with files
            parent_entry = malloc(sizeof(struct dirq_entry));
            parent_entry->dir = strdup(dir);
            parent_entry->files = malloc(sizeof(struct fileq));
            SIMPLEQ_INIT(parent_entry->files);
            SIMPLEQ_INSERT_TAIL((struct dirq *)s->_dirq, parent_entry, entries);
          }

          // Add scannable file to this directory list
          entry = malloc(sizeof(struct fileq_entry));
          entry->file = strdup(name);
          entry->type = type;
          SIMPLEQ_INSERT_TAIL(parent_entry->files, entry, entries);

          s->progress->total++;

          LOG_INFO(" [%5d] file: %s\n", s->progress->total, entry->file);
        }
      }
    }
  }

  closedir(dirp);

  // Send progress update
  if (s->on_progress && !s->_want_abort)
    if (progress_update(s->progress, dir))
      send_progress(s);

  // process subdirs
  while (!SIMPLEQ_EMPTY(subdirq)) {
    struct dirq_entry *subdir_entry = SIMPLEQ_FIRST(subdirq);
    SIMPLEQ_REMOVE_HEAD(subdirq, entries);
    if (!s->_want_abort)
      recurse_dir(s, subdir_entry->dir, recurse_count);
    free(subdir_entry);
  }

  free(subdirq);

out:
  free(dir);
}
예제 #4
0
// Called by ms_scan either in a thread or synchronously
static void *do_scan(void *userdata) {
  MediaScan *s = ((thread_data_type *)userdata)->s;
  int i;
  struct dirq *dir_head = (struct dirq *)s->_dirq;
  struct dirq_entry *dir_entry = NULL;
  struct fileq *file_head = NULL;
  struct fileq_entry *file_entry = NULL;
  char tmp_full_path[MAX_PATH_STR_LEN];

  // Initialize the cache database
  if (!init_bdb(s)) {
    MediaScanError *e = error_create("", MS_ERROR_CACHE, "Unable to initialize libmediascan cache");
    send_error(s, e);
    goto out;
  }

  if (s->flags & MS_CLEARDB) {
    reset_bdb(s);
  }

  if (s->progress == NULL) {
    MediaScanError *e = error_create("", MS_ERROR_TYPE_INVALID_PARAMS, "Progress object not created");
    send_error(s, e);
    goto out;
  }

  // Build a list of all directories and paths
  // We do this first so we can present an accurate scan eta later
  progress_start_phase(s->progress, "Discovering");

  for (i = 0; i < s->npaths; i++) {
    LOG_INFO("Scanning %s\n", s->paths[i]);
    recurse_dir(s, s->paths[i], 0);
  }

  // Scan all files found
  progress_start_phase(s->progress, "Scanning");

  while (!SIMPLEQ_EMPTY(dir_head)) {
    dir_entry = SIMPLEQ_FIRST(dir_head);

    file_head = dir_entry->files;
    while (!SIMPLEQ_EMPTY(file_head)) {
      // check if the scan has been aborted
      if (s->_want_abort) {
        LOG_DEBUG("Aborting scan\n");
        goto aborted;
      }

      file_entry = SIMPLEQ_FIRST(file_head);

      // Construct full path
      strcpy(tmp_full_path, dir_entry->dir);
#ifdef WIN32
      strcat(tmp_full_path, "\\");
#else
      strcat(tmp_full_path, "/");
#endif
      strcat(tmp_full_path, file_entry->file);

      ms_scan_file(s, tmp_full_path, file_entry->type);

      // Send progress update if necessary
      if (s->on_progress) {
        s->progress->done++;

        if (progress_update(s->progress, tmp_full_path))
          send_progress(s);
      }

      SIMPLEQ_REMOVE_HEAD(file_head, entries);
      free(file_entry->file);
      free(file_entry);
    }

    SIMPLEQ_REMOVE_HEAD(dir_head, entries);
    free(dir_entry->dir);
    free(dir_entry->files);
    free(dir_entry);
  }

  // Send final progress callback
  if (s->on_progress) {
    progress_update(s->progress, NULL);
    send_progress(s);
  }

  LOG_DEBUG("Finished scanning\n");

out:
  if (s->on_finish)
    send_finish(s);

aborted:
  if (s->async) {
    LOG_MEM("destroy thread_data @ %p\n", userdata);
    free(userdata);
  }

  return NULL;
}
예제 #5
0
    virtual void process()
    {
        // This happens in the installer thread, so we cannot mess with
        // anything else.

        HZIP zip = NULL;

        try
        {
            g_debug( "STARTING INSTALL OF %s", info.source_file.c_str() );

            //.................................................................

            if ( ! verify_and_strip_signatures() )
            {
                throw String( "SIGNATURE CHECK FAILED" );
            }

            //.................................................................
            // Open the source file to make sure it is ok

            zip = OpenZip( info.source_file.c_str(), NULL );

            if ( ! zip )
            {
                throw String( "FAILED TO OPEN ZIP FILE" );
            }

            ZIPENTRY entry;

            //.................................................................
            // Figure out how many items are in the zip file

            if ( ZR_OK != GetZipItem( zip, -1, &entry ) )
            {
                throw String( "FAILED TO GET ZIP ENTRY COUNT" );
            }

            int entry_count = entry.index;

            if ( entry_count <= 0 )
            {
                throw String( "ZIP FILE HAS TOO FEW ENTRIES" );
            }

            //.................................................................
            // Now go through all the items in the zip file, figure out
            // their total uncompressed size and find the 'app' file.

            guint64 total_uncompressed_size = 0;

            String app_file_zip_path;

            int app_file_zip_index = -1;

            guint64 app_file_uncompressed_size = 0;

            for ( int i = 0; i < entry_count; ++i )
            {
                if ( ZR_OK != GetZipItem( zip, i, &entry ) )
                {
                    throw String( "FAILED TO GET ZIP ENTRY" );
                }

                total_uncompressed_size += entry.unc_size;

                // See if this is the app file

                if ( app_file_zip_path.empty() )
                {
                    // THIS IS PLATFORM SPECIFIC

                    if ( ! ( entry.attr & S_IFDIR ) )
                    {
                        gchar * basename = g_path_get_basename( entry.name );

                        if ( ! strcmp( basename , "app" ) )
                        {
                            app_file_zip_path = entry.name;

                            app_file_zip_index = i;

                            app_file_uncompressed_size = entry.unc_size;
                        }

                        g_free( basename );
                    }
                }
            }

            if ( app_file_zip_path.empty() )
            {
                throw String( "ZIP FILE IS MISSING APP FILE" );
            }

            if ( app_file_uncompressed_size == 0 )
            {
                throw String( "APP FILE UNCOMPRESSED SIZE IS INCORRECT" );
            }

            g_debug( "FOUND APP FILE IN ZIP AT %s", app_file_zip_path.c_str() );

            //.................................................................
            // Uncompress the app file to memory and load its metadata.
            // We must ensure it is valid and its app_id is the same as the
            // one passed in.

            // g_new0 serves to NULL-terminate the contents, which
            // load_metadata_from_data expects.

            gchar * app_file_buffer = g_new0( gchar, app_file_uncompressed_size * 2 );

            if ( ! app_file_buffer )
            {
                throw String( "FAILED TO ALLOCATE MEMORY TO UNCOMPRESS APP FILE" );
            }

            FreeLater free_later;

            free_later( app_file_buffer );

            if ( ZR_OK != UnzipItem( zip, app_file_zip_index, app_file_buffer, app_file_uncompressed_size * 2 ) )
            {
                throw String( "FAILED TO UNCOMPRESS APP FILE" );
            }

            App::Metadata metadata;

            if ( ! App::load_metadata_from_data( app_file_buffer, metadata ) )
            {
                throw String( "FAILED TO READ METADATA" );
            }

            if ( metadata.id != info.app_id )
            {
                throw String( "APP ID DOES NOT MATCH" );
            }

            //.................................................................
            // Figure out where to unzip it to
            // - should be in the same volume as the app's data directory
            //
            // The app may already live in  trickplay/apps/<id hash>/source
            //
            // We could unzip it to         trickplay/apps/installing/<id hash>
            //      The benefit of this is that it would be easy to clean up unfinished
            //      installations by deleting everything in "installing".
            //
            // We could unzip it to         trickplay/apps/<id hash>/installing
            //      This puts it event closer to its final destination, but we would
            //      have to do more work to clean up. CHOOSING THIS ONE FOR NOW

            gchar * unzip_path = g_build_filename( info.app_directory.c_str(), "installing", NULL );

            free_later( unzip_path );

            //.................................................................
            // If our destination directory already exists, it is probably
            // from a failed attempt to install this app. We need to get rid of it.

            if ( g_file_test( unzip_path, G_FILE_TEST_EXISTS ) )
            {
                g_debug( "DELETING OLD INSTALL DIRECTORY %s", unzip_path );

                if ( ! recursive_delete_path( unzip_path ) )
                {
                    throw String( "FAILED TO DELETE OLD INSTALL DIRECTORY" );
                }
            }

            if ( 0 != g_mkdir_with_parents( unzip_path, 0700 ) )
            {
                throw String( "FAILED TO CREATE INSTALL DIRECTORY" );
            }

            //.................................................................
            // TODO: We should now check for free space - and make sure we have at
            // least total_uncompressed_size available.


            //.................................................................
            // OK, everything seems to be in order.
            // We get the dirname of the path to the app file in the zip.
            // So, for example, inside the zip, the app file might be in
            // "foor/bar/app". We have to take all the files in the zip that
            // are in "foo/bar" and unzip them to our real destination.

            gchar * app_file_zip_dirname = g_path_get_dirname( app_file_zip_path.c_str() );
            g_assert(app_file_zip_dirname);

            free_later( app_file_zip_dirname );

            guint app_file_zip_dirname_length = strlen( app_file_zip_dirname );

            // If there is no dirname, the above gets set to "."

            bool no_zip_root = ! strcmp( app_file_zip_dirname, "." );

            // Now, it is time to unzip

            g_debug( "UNZIPPING TO %s", unzip_path );

            guint64 total_processed = 0;

            Util::GTimer progress_timer;

#ifndef TP_PRODUCTION

            static float slow = -1;

            if ( slow == -1 )
            {
                if ( const char * e = g_getenv( "TP_INSTALL_DELAY" ) )
                {
                    slow = atof( e );
                }
                else
                {
                    slow = 0;
                }
            }

#endif

            for ( int i = 0; i < entry_count; ++i )
            {

#ifndef TP_PRODUCTION

                if ( slow )
                {
                    usleep( slow * G_USEC_PER_SEC );
                }

#endif

                if ( ZR_OK != GetZipItem( zip, i, &entry ) )
                {
                    throw String( "FAILED TO GET ZIP ENTRY" );
                }

                gchar * destination_file_name = NULL;

                if ( no_zip_root )
                {
                    destination_file_name = g_build_filename( unzip_path, entry.name, NULL );
                }
                else if ( g_str_has_prefix( entry.name, app_file_zip_dirname ) )
                {
                    destination_file_name = g_build_filename( unzip_path, entry.name + app_file_zip_dirname_length, NULL );
                }

                if ( ! destination_file_name )
                {
                    g_debug( "  SKIPPING %s", entry.name );
                }
                else
                {
                    free_later( destination_file_name );

                    g_debug( "  UNZIPPING %s", entry.name );

                    if ( ZR_OK != UnzipItem( zip, i, destination_file_name ) )
                    {
                        throw String( "FAILED TO UNZIP" );
                    }
                }

                // Report progress

                total_processed += entry.unc_size;

                if ( progress_timer.elapsed() >= 1 )
                {
                    progress_timer.reset();

                    info.status = Installer::Info::INSTALLING;
                    info.percent_installed = gdouble( total_processed ) / gdouble( total_uncompressed_size ) * 100.0;

                    send_progress();
                }
            }

            //.................................................................
            // At this point, the app should be uncompressed to the "installing"
            // directory and ready to go.

            //.................................................................
            // Finally, under the right conditions, we delete the existing install
            // of the app and move the "installing" directory over it.

            info.moved = false;

            gchar * source_path = g_build_filename( info.app_directory.c_str(), "source", NULL );

            free_later( source_path );

            bool source_exists = g_file_test( source_path, G_FILE_TEST_EXISTS );

            // If the source directory exists and the app is locked, we can
            // delete the source directory

            if ( source_exists && info.locked )
            {
                if ( ! recursive_delete_path( source_path ) )
                {
                    throw String( "FAILED TO DELETE PREVIOUS APP SOURCE" );
                }

                source_exists = false;
            }

            // If the source directory does not already exist, or we deleted in the
            // previous step, we can rename the install directory.

            if ( ! source_exists )
            {
                if ( 0 != g_rename( unzip_path, source_path ) )
                {
                    throw String( "FAILED TO RENAME INSTALL DIRECTORY TO SOURCE DIRECTORY" );
                }

                info.moved = true;
            }

            // Once this is done, the caller needs to call 'complete_install'. This will
            // move the app to its final resting place (if necessary) and also add its
            // entry to the system database.

            g_debug( "FINISHED INSTALL OF %s TO %s", info.app_id.c_str(), info.moved ? source_path : unzip_path );

            info.status = Installer::Info::FINISHED;

            info.install_directory = unzip_path;

            info.app_directory = source_path;

            send_progress();

            // Caller is also reponsible for getting rid of the original zip file.
        }
        catch( const String & e )
        {
            g_warning( "FAILED TO INSTALL %s FROM %s : %s", info.app_id.c_str(), info.source_file.c_str(), e.c_str() );

            info.status = Installer::Info::FAILED;

            send_progress( );
        }

        // Close the zip file

        if ( zip )
        {
            CloseZip( zip );
        }

        // Always return true - to keep the thread running
    }