Changeset 1021

Show
Ignore:
Timestamp:
12/23/07 03:05:00 (4 years ago)
Author:
rakshasa
Message:

* Added "d.set_directory_base" command that handles single and multi
file torrent equally.

* Fixed man page entry on 'umask', it should be 0022 not 0664.

* Cleaned up File and FileList? classes.

Location:
trunk
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • trunk/libtorrent/src/torrent/data/file.cc

    r1019 r1021  
    143143} 
    144144 
     145void 
     146File::set_match_depth(File* left, File* right) { 
     147  uint32_t level = 0; 
     148 
     149  Path::const_iterator itrLeft = left->path()->begin(); 
     150  Path::const_iterator itrRight = right->path()->begin(); 
     151 
     152  while (itrLeft != left->path()->end() && itrRight != right->path()->end() && *itrLeft == *itrRight) { 
     153    itrLeft++; 
     154    itrRight++; 
     155    level++; 
     156  } 
     157 
     158  left->m_matchDepthNext = level; 
     159  right->m_matchDepthPrev = level; 
     160} 
     161 
    145162bool 
    146163File::resize_file() { 
  • trunk/libtorrent/src/torrent/data/file.h

    r1019 r1021  
    4949  typedef std::pair<uint32_t, uint32_t> range_type; 
    5050 
    51   static const int flag_create_queued      = (1 << 0); 
    52   static const int flag_resize_queued      = (1 << 1); 
    53   static const int flag_previously_created = (1 << 2); 
     51  static const int flag_active             = (1 << 0); 
     52  static const int flag_create_queued      = (1 << 1); 
     53  static const int flag_resize_queued      = (1 << 2); 
     54  static const int flag_previously_created = (1 << 3); 
    5455 
    5556  File(); 
     
    6667  bool                is_previously_created() const            { return m_flags & flag_previously_created; } 
    6768 
     69  bool                has_flags(int flags)                     { return m_flags & flags; } 
     70 
    6871  void                set_flags(int flags); 
    6972  void                unset_flags(int flags); 
     
    7780 
    7881  uint32_t            completed_chunks() const                 { return m_completed; } 
     82  void                set_completed_chunks(uint32_t v); 
    7983 
    8084  const range_type&   range() const                            { return m_range; } 
     
    109113 
    110114protected: 
     115  void                set_flags_protected(int flags)           { m_flags |= flags; } 
     116  void                unset_flags_protected(int flags)         { m_flags &= ~flags; } 
     117 
    111118  void                set_frozen_path(const std::string& path) { m_frozenPath = path; } 
    112119 
     
    115122  void                set_range(uint32_t chunkSize); 
    116123 
    117   void                set_completed(uint32_t v)                { m_completed = v; } 
    118   void                inc_completed()                          { m_completed++; } 
     124  void                set_completed_protected(uint32_t v)      { m_completed = v; } 
     125  void                inc_completed_protected()                { m_completed++; } 
     126 
     127  static void         set_match_depth(File* left, File* right); 
    119128 
    120129  void                set_match_depth_prev(uint32_t l)         { m_matchDepthPrev = l; } 
     
    154163inline void 
    155164File::set_flags(int flags) { 
    156   m_flags |= flags & (flag_create_queued | flag_resize_queued); 
     165  set_flags_protected(flags & (flag_create_queued | flag_resize_queued)); 
    157166} 
    158167 
    159168inline void 
    160169File::unset_flags(int flags) { 
    161   m_flags |= flags & (flag_create_queued | flag_resize_queued); 
     170  unset_flags_protected(flags & (flag_create_queued | flag_resize_queued)); 
     171} 
     172 
     173inline void 
     174File::set_completed_chunks(uint32_t v) { 
     175  if (!has_flags(flag_active) && v <= size_chunks()) 
     176    m_completed = v; 
    162177} 
    163178 
  • trunk/libtorrent/src/torrent/data/file_list.cc

    r1019 r1021  
    275275    newFile->set_match_depth_prev(0); 
    276276  else 
    277     set_match_depth(*(first - 1), newFile); 
     277    File::set_match_depth(*(first - 1), newFile); 
    278278 
    279279  if (first + 1 == end()) 
    280280    newFile->set_match_depth_next(0); 
    281281  else 
    282     set_match_depth(newFile, *(first + 1)); 
     282    File::set_match_depth(newFile, *(first + 1)); 
    283283 
    284284  return first; 
     
    294294 
    295295  if (first != begin()) 
    296     set_match_depth(*(first - 1), *first); 
     296    File::set_match_depth(*(first - 1), *first); 
    297297 
    298298  while (first != last && ++first != end()) 
    299     set_match_depth(*(first - 1), *first); 
     299    File::set_match_depth(*(first - 1), *first); 
    300300 
    301301  verify_file_list(this); 
    302302} 
    303303 
    304 void 
    305 FileList::set_file_completed_chunks(iterator itr, uint32_t v) { 
    306   if (is_open()) 
    307     return; 
    308  
    309   (*itr)->set_completed(v); 
     304bool 
     305FileList::make_root_path() { 
     306  if (!is_open()) 
     307    return false; 
     308 
     309  return ::mkdir(m_rootDir.c_str(), 0777) == 0 || errno == EEXIST; 
     310} 
     311 
     312bool 
     313FileList::make_all_paths() { 
     314  if (!is_open()) 
     315    return false; 
     316 
     317  Path dummyPath; 
     318  const Path* lastPath = &dummyPath; 
     319 
     320  for (iterator itr = begin(), last = end(); itr != last; ++itr) { 
     321    File* entry = *itr; 
     322 
     323    // No need to create directories if the entry has already been 
     324    // opened. 
     325    if (entry->is_open()) 
     326      continue; 
     327 
     328    if (entry->path()->empty()) 
     329      throw storage_error("Found an empty filename."); 
     330 
     331    Path::const_iterator lastPathItr   = lastPath->begin(); 
     332    Path::const_iterator firstMismatch = entry->path()->begin(); 
     333 
     334    // Couldn't find a suitable stl algo, need to write my own. 
     335    while (firstMismatch != entry->path()->end() && lastPathItr != lastPath->end() && *firstMismatch == *lastPathItr) { 
     336      lastPathItr++; 
     337      firstMismatch++; 
     338    } 
     339 
     340    rak::error_number::clear_global(); 
     341 
     342    make_directory(entry->path()->begin(), entry->path()->end(), firstMismatch); 
     343     
     344    lastPath = entry->path(); 
     345  } 
     346 
     347  return true; 
    310348} 
    311349 
     
    354392 
    355393  try { 
    356     if (!(flags & open_no_create) && 
    357         ::mkdir(m_rootDir.c_str(), 0777) != 0 && errno != EEXIST) 
     394    if (!(flags & open_no_create) && !make_root_path()) 
    358395      throw storage_error("Could not create directory '" + m_rootDir + "': " + std::strerror(errno)); 
    359396   
     
    389426      // it here if necessary. 
    390427 
     428      entry->set_flags_protected(File::flag_active); 
     429 
    391430      if (!open_file(&*entry, lastPath, flags)) { 
    392431        // This needs to check if the error was due to open_no_create 
     
    404443 
    405444  } catch (local_error& e) { 
    406     for (iterator itr = begin(), last = end(); itr != last; ++itr) 
     445    for (iterator itr = begin(), last = end(); itr != last; ++itr) { 
     446      (*itr)->unset_flags_protected(File::flag_active); 
    407447      manager->file_manager()->close(*itr); 
     448    } 
    408449 
    409450    // Set to false here in case we tried to open the FileList for the 
     
    422463 
    423464  for (iterator itr = begin(), last = end(); itr != last; ++itr) { 
     465    (*itr)->unset_flags_protected(File::flag_active); 
    424466    manager->file_manager()->close(*itr); 
    425      
    426     // Keep the progress so the user can see it even though he closes 
    427     // the torrent. 
    428 //     (*itr)->set_completed(0); 
    429467  } 
    430468 
    431469  m_isOpen = false; 
    432470  m_indirectLinks.clear(); 
    433 } 
    434  
    435 bool 
    436 FileList::resize_all() { 
    437   bool success = true; 
    438  
    439   // Remove this function. 
    440  
    441 //   for (iterator itr = begin(); itr != end(); itr++) 
    442 //     if (!(*itr)->frozen_path().empty() && 
    443 //         !(*itr)->resize_file()) 
    444 //       success = false; 
    445  
    446   return success; 
    447471} 
    448472 
     
    476500bool 
    477501FileList::open_file(File* node, const Path& lastPath, int flags) { 
    478   const Path* path = node->path(); 
    479  
    480   Path::const_iterator lastItr = lastPath.begin(); 
    481   Path::const_iterator firstMismatch = path->begin(); 
    482  
    483   // Couldn't find a suitable stl algo, need to write my own. 
    484   while (firstMismatch != path->end() && lastItr != lastPath.end() && *firstMismatch == *lastItr) { 
    485     lastItr++; 
    486     firstMismatch++; 
    487   } 
    488  
    489502  rak::error_number::clear_global(); 
    490503 
    491   if (!(flags & open_no_create)) 
     504  if (!(flags & open_no_create)) { 
     505    const Path* path = node->path(); 
     506 
     507    Path::const_iterator lastItr = lastPath.begin(); 
     508    Path::const_iterator firstMismatch = path->begin(); 
     509 
     510    // Couldn't find a suitable stl algo, need to write my own. 
     511    while (firstMismatch != path->end() && lastItr != lastPath.end() && *firstMismatch == *lastItr) { 
     512      lastItr++; 
     513      firstMismatch++; 
     514    } 
     515 
    492516    make_directory(path->begin(), path->end(), firstMismatch); 
     517  } 
    493518 
    494519  // Some torrents indicate an empty directory by having a path with 
    495520  // an empty last element. This entry must be zero length. 
    496   if (path->back().empty()) 
     521  if (node->path()->back().empty()) 
    497522    return node->size_bytes() == 0; 
    498523 
     
    596621  std::for_each(firstItr, 
    597622                lastItr == end() ? end() : (lastItr + 1), 
    598                 std::mem_fun(&File::inc_completed)); 
     623                std::mem_fun(&File::inc_completed_protected)); 
    599624 
    600625  return lastItr; 
     
    608633  if (m_bitfield.is_all_set()) { 
    609634    for (iterator itr = begin(), last = end(); itr != last; ++itr) 
    610       (*itr)->set_completed((*itr)->size_chunks()); 
     635      (*itr)->set_completed_protected((*itr)->size_chunks()); 
    611636 
    612637  } else { 
     
    614639    // this on close, etc. 
    615640    for (iterator itr = begin(), last = end(); itr != last; ++itr) 
    616       (*itr)->set_completed(0); 
     641      (*itr)->set_completed_protected(0); 
    617642 
    618643    if (m_bitfield.is_all_unset()) 
     
    627652} 
    628653 
    629 void 
    630 FileList::set_match_depth(File* left, File* right) { 
    631   uint32_t level = 0; 
    632  
    633   Path::const_iterator itrLeft = left->path()->begin(); 
    634   Path::const_iterator itrRight = right->path()->begin(); 
    635  
    636   while (itrLeft != left->path()->end() && itrRight != right->path()->end() && *itrLeft == *itrRight) { 
    637     itrLeft++; 
    638     itrRight++; 
    639     level++; 
    640   } 
    641  
    642   left->set_match_depth_next(level); 
    643   right->set_match_depth_prev(level); 
    644 } 
    645  
    646 } 
     654} 
  • trunk/libtorrent/src/torrent/data/file_list.h

    r1017 r1021  
    142142  void                update_paths(iterator first, iterator last); 
    143143 
    144   void                set_file_completed_chunks(iterator itr, uint32_t v); 
     144  bool                make_root_path(); 
     145  bool                make_all_paths(); 
    145146 
    146147protected: 
     
    152153  void                open(int flags) LIBTORRENT_NO_EXPORT; 
    153154  void                close() LIBTORRENT_NO_EXPORT; 
    154  
    155   bool                resize_all() LIBTORRENT_NO_EXPORT; 
    156155 
    157156  Bitfield*           mutable_bitfield()                               { return &m_bitfield; } 
     
    170169  void                make_directory(Path::const_iterator pathBegin, Path::const_iterator pathEnd, Path::const_iterator startItr) LIBTORRENT_NO_EXPORT; 
    171170  MemoryChunk         create_chunk_part(FileList::iterator itr, uint64_t offset, uint32_t length, int prot) LIBTORRENT_NO_EXPORT; 
    172  
    173   void                set_match_depth(File* left, File* right); 
    174171 
    175172  bool                m_isOpen; 
  • trunk/libtorrent/src/torrent/resume.cc

    r1020 r1021  
    239239 
    240240    if (filesItr->has_key_value("completed")) 
    241       fileList->set_file_completed_chunks(listItr, std::max<int64_t>(filesItr->get_key_value("completed"), (*listItr)->size_chunks())); 
     241      (*listItr)->set_completed_chunks(filesItr->get_key_value("completed")); 
    242242  } 
    243243} 
  • trunk/rtorrent/doc/rtorrent.1.xml

    r1013 r1021  
    10131013 
    10141014      <varlistentry> 
    1015         <term>umask = <replaceable>0644</replaceable></term> 
     1015        <term>umask = <replaceable>0022</replaceable></term> 
    10161016        <listitem><para> 
    10171017 
  • trunk/rtorrent/src/command_download.cc

    r1017 r1021  
    176176} 
    177177 
     178void 
     179apply_d_directory(core::Download* download, const std::string& name) { 
     180  if (!download->file_list()->is_multi_file()) 
     181    download->set_root_directory(name); 
     182  else if (name.empty() || *name.rbegin() == '/') 
     183    download->set_root_directory(name + download->download()->name()); 
     184  else 
     185    download->set_root_directory(name + "/" + download->download()->name()); 
     186} 
     187 
    178188const char* 
    179189retrieve_d_connection_type(core::Download* download) { 
     
    508518  ADD_CD_VALUE_UNI("tracker_size",        std::mem_fun(&core::Download::tracker_list_size)); 
    509519 
    510   ADD_CD_STRING_BI("directory",           std::mem_fun(&core::Download::set_root_directory), rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir))); 
     520  ADD_CD_STRING_BI("directory",           std::ptr_fun(&apply_d_directory), rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir))); 
     521  ADD_CD_STRING_BI("directory_base",      std::mem_fun(&core::Download::set_root_directory), rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir))); 
     522 
    511523  ADD_CD_VALUE_BI("priority",             std::mem_fun(&core::Download::set_priority), std::mem_fun(&core::Download::priority)); 
    512524  ADD_CD_STRING_UNI("priority_str",       std::ptr_fun(&retrieve_d_priority_str)); 
  • trunk/rtorrent/src/core/download.cc

    r1012 r1021  
    156156} 
    157157 
    158 // Clean up. 
    159158void 
    160159Download::set_root_directory(const std::string& path) { 
     
    162161 
    163162  control->core()->download_list()->close_directly(this); 
    164  
    165   if (path.empty()) { 
    166     fileList->set_root_dir("./" + (fileList->is_multi_file() ? m_download.name() : std::string())); 
    167  
    168   } else { 
    169     std::string fullPath = rak::path_expand(path); 
    170  
    171     fileList->set_root_dir(fullPath + 
    172                            (*fullPath.rbegin() != '/' ? "/" : "") + 
    173                            (fileList->is_multi_file() ? m_download.name() : std::string())); 
    174   } 
     163  fileList->set_root_dir(rak::path_expand(path)); 
    175164 
    176165  bencode()->get_key("rtorrent").insert_key("directory", path);