예제 #1
0
static bool
preallocate_file_sparse (tr_sys_file_t fd, uint64_t length, tr_error ** error)
{
  tr_error * my_error = NULL;

  if (length == 0)
    return true;

  if (tr_sys_file_preallocate (fd, length, TR_SYS_FILE_PREALLOC_SPARSE, &my_error))
    return true;

  dbgmsg ("Preallocating (sparse, normal) failed (%d): %s", my_error->code, my_error->message);

  if (!TR_ERROR_IS_ENOSPC (my_error->code))
    {
      const char zero = '\0';

      tr_error_clear (&my_error);

      /* fallback: the old-style seek-and-write */
      if (tr_sys_file_write_at (fd, &zero, 1, length - 1, NULL, &my_error) &&
          tr_sys_file_truncate (fd, length, &my_error))
        return true;

      dbgmsg ("Preallocating (sparse, fallback) failed (%d): %s", my_error->code, my_error->message);
    }

  tr_error_propagate (error, &my_error);
  return false;
}
예제 #2
0
파일: inout.c 프로젝트: Kengi/Transmission
/* returns 0 on success, or an errno on failure */
static int
readOrWriteBytes (tr_session       * session,
                  tr_torrent       * tor,
                  int                ioMode,
                  tr_file_index_t    fileIndex,
                  uint64_t           fileOffset,
                  void             * buf,
                  size_t             buflen)
{
  tr_sys_file_t fd;
  int err = 0;
  const bool doWrite = ioMode >= TR_IO_WRITE;
  const tr_info * const info = &tor->info;
  const tr_file * const file = &info->files[fileIndex];

  assert (fileIndex < info->fileCount);
  assert (!file->length || (fileOffset < file->length));
  assert (fileOffset + buflen <= file->length);

  if (!file->length)
    return 0;

  /***
  ****  Find the fd
  ***/

  fd = tr_fdFileGetCached (session, tr_torrentId (tor), fileIndex, doWrite);
  if (fd == TR_BAD_SYS_FILE)
    {
      /* it's not cached, so open/create it now */
      char * subpath;
      const char * base;

      /* see if the file exists... */
      if (!tr_torrentFindFile2 (tor, fileIndex, &base, &subpath, NULL))
        {
          /* we can't read a file that doesn't exist... */
          if (!doWrite)
            err = ENOENT;

          /* figure out where the file should go, so we can create it */
          base = tr_torrentGetCurrentDir (tor);
          subpath = tr_sessionIsIncompleteFileNamingEnabled (tor->session)
                  ? tr_torrentBuildPartial (tor, fileIndex)
                  : tr_strdup (file->name);

        }

      if (!err)
        {
          /* open (and maybe create) the file */
          char * filename = tr_buildPath (base, subpath, NULL);
          const int prealloc = file->dnd || !doWrite
                             ? TR_PREALLOCATE_NONE
                             : tor->session->preallocationMode;
          if (((fd = tr_fdFileCheckout (session, tor->uniqueId, fileIndex,
                                        filename, doWrite,
                                        prealloc, file->length))) == TR_BAD_SYS_FILE)
            {
              err = errno;
              tr_logAddTorErr (tor, "tr_fdFileCheckout failed for \"%s\": %s",
                         filename, tr_strerror (err));
            }
          else if (doWrite)
            {
              /* make a note that we just created a file */
              tr_statsFileCreated (tor->session);
            }

          tr_free (filename);
        }

      tr_free (subpath);
    }

  /***
  ****  Use the fd
  ***/

  if (!err)
    {
      tr_error * error = NULL;

      if (ioMode == TR_IO_READ)
        {
          if (!tr_sys_file_read_at (fd, buf, buflen, fileOffset, NULL, &error))
            {
              err = error->code;
              tr_logAddTorErr (tor, "read failed for \"%s\": %s", file->name, error->message);
              tr_error_free (error);
            }
        }
      else if (ioMode == TR_IO_WRITE)
        {
          if (!tr_sys_file_write_at (fd, buf, buflen, fileOffset, NULL, &error))
            {
              err = error->code;
              tr_logAddTorErr (tor, "write failed for \"%s\": %s", file->name, error->message);
              tr_error_free (error);
            }
        }
      else if (ioMode == TR_IO_PREFETCH)
        {
          tr_sys_file_prefetch (fd, fileOffset, buflen, NULL);
        }
      else
        {
          abort ();
        }
    }

  return err;
}