/**
   * Returns true if the code was executed correctly. False if there was an error trying to share
   * the file. If the file was not supposed to be shared, and was not shared, true would still be
   * returned.
   */
  private boolean shareTorrentFile(File torrentFile) {
    if (torrentManager.isDownloadingTorrent(torrentFile)) {
      return true;
    }

    if (!SharingSettings.SHARE_DOWNLOADED_FILES_IN_NON_SHARED_DIRECTORIES.getValue()) {
      return true;
    }

    BTData btData = null;
    FileInputStream torrentInputStream = null;
    try {
      torrentInputStream = new FileInputStream(torrentFile);
      Map<?, ?> torrentFileMap = (Map<?, ?>) Token.parse(torrentInputStream.getChannel());
      btData = new BTDataImpl(torrentFileMap);
    } catch (IOException e) {
      LOG.error("Error reading torrent file: " + torrentFile, e);
      return false;
    } finally {
      FileUtils.close(torrentInputStream);
    }

    if (btData.isPrivate()) {
      gnutellaFileList.remove(torrentFile);
      return true;
    }

    File saveDir = SharingSettings.getSaveDirectory();
    File torrentParent = torrentFile.getParentFile();
    if (torrentParent.equals(saveDir)) {
      // already in saveDir
      gnutellaFileList.add(torrentFile);
      return true;
    }

    final File tFile = getSharedTorrentMetaDataFile(btData);
    if (tFile.equals(torrentFile)) {
      gnutellaFileList.add(tFile);
      return true;
    }

    gnutellaFileList.remove(tFile);
    File backup = null;
    if (tFile.exists()) {
      backup = new File(tFile.getParent(), tFile.getName().concat(".bak"));
      FileUtils.forceRename(tFile, backup);
    }

    if (FileUtils.copy(torrentFile, tFile)) {
      gnutellaFileList.add(tFile);
    } else {
      if (backup != null) {
        // restore backup
        if (FileUtils.forceRename(backup, tFile)) {
          gnutellaFileList.add(tFile);
        }
      }
    }
    return true;
  }
 private File getSharedTorrentMetaDataFile(BTData btData) {
   String fileName = btData.getName().concat(".torrent");
   File f = new File(SharingSettings.getSaveDirectory(), fileName);
   return f;
 }
  /**
   * Constructs the file system using the given BTData & hash information. If any of the information
   * is malformed, throws a ValueException.
   *
   * @param data contains all the data about a .torrent file
   * @param numHashes number of pieces the torrent was divided into
   * @param pieceLength size of divided up torrent file
   * @param infoHash a string of alphanumeric characters in the .torrent file that the client uses
   *     to verify the data that is being transferred
   * @throws ValueException
   */
  TorrentFileSystem(BTData data, int numHashes, long pieceLength, byte[] infoHash)
      throws IOException {
    // name of the torrent, also specifying the directory under which to save the torrents.
    _name = CommonUtils.convertFileName(data.getName());

    // we need to check the name of the torrent, security risk!
    if (_name.length() == 0) throw new ValueException("bad torrent name");

    _incompleteFile =
        new File(
            SharingSettings.INCOMPLETE_DIRECTORY.get(),
            Base32.encode(infoHash) + File.separator + _name);
    _completeFile = new File(SharingSettings.getSaveDirectory(_name), _name);

    if (!FileUtils.isReallyParent(SharingSettings.getSaveDirectory(_name), _completeFile)) {
      throw new SaveLocationException(LocationCode.SECURITY_VIOLATION, _completeFile);
    }

    if (data.getFiles() != null) {
      List<BTData.BTFileData> files = data.getFiles();
      List<TorrentFile> torrents = new ArrayList<TorrentFile>(files.size());
      long position = 0;
      for (BTData.BTFileData file : files) {
        String torrentPath = _name + file.getPath();
        TorrentFile f =
            new TorrentFile(
                file.getLength(),
                new File(_completeFile, file.getPath()).getAbsolutePath(),
                torrentPath);
        f.setBeginPiece((int) (position / pieceLength));
        f.setStartByte(position);
        position += f.length();
        f.setEndPiece((int) (position / pieceLength));
        f.setEndByte(position - 1);

        if (!FileUtils.isReallyInParentPath(_completeFile, f))
          throw new SaveLocationException(LocationCode.SECURITY_VIOLATION, f);
        torrents.add(f);
      }

      if (files.size() == 0) throw new ValueException("bad metainfo, no files!");

      _files = torrents;

      // add folders, for easier conflict checking later on
      for (String folderPath : data.getFolders()) _folders.add(new File(_completeFile, folderPath));
      _folders.add(_completeFile);
    } else {
      String torrentPath = data.getName();
      TorrentFile f =
          new TorrentFile(data.getLength(), _completeFile.getAbsolutePath(), torrentPath);
      f.setBeginPiece(0);
      f.setStartByte(0);
      f.setEndPiece(numHashes - 1);
      f.setEndByte(f.length());
      _files = new ArrayList<TorrentFile>(1);
      _files.add(f);
    }

    _unmodFiles = Collections.unmodifiableList(_files);
    _totalSize = calculateTotalSize(_files);
    if (_totalSize <= 0) throw new ValueException("invalid size " + _totalSize);
  }