docs: def check_info(info):
      """ Validate info dict.
  
          Raise ValueError if validation fails.
      """
      if not isinstance(info, dict):
          raise ValueError("bad metainfo - not a dictionary")
  
      pieces = info.get("pieces")
      if not isinstance(pieces, basestring) or len(pieces) % 20 != 0:
          raise ValueError("bad metainfo - bad pieces key")
  
      piece_size = info.get("piece length")
      if not isinstance(piece_size, (int, long)) or piece_size <= 0:
          raise ValueError("bad metainfo - illegal piece length")
  
      name = info.get("name")
      if not isinstance(name, basestring):
          raise ValueError("bad metainfo - bad name (type is %r)" % type(name).__name__)
      if not ALLOWED_ROOT_NAME.match(name):
          raise ValueError("name %s disallowed for security reasons" % name)
  
      if ("files" in info) == ("length" in info):
          raise ValueError("single/multiple file mix")
  
      if "length" in info:
          length = info.get("length")
          if not isinstance(length, (int, long)) or length < 0:
              raise ValueError("bad metainfo - bad length")
      else:
          files = info.get("files")
          if not isinstance(files, (list, tuple)):
              raise ValueError("bad metainfo - bad file list")
  
          for item in files:
              if not isinstance(item, dict):
                  raise ValueError("bad metainfo - bad file value")
  
              length = item.get("length")
              if not isinstance(length, (int, long)) or length < 0:
                  raise ValueError("bad metainfo - bad length")
  
              path = item.get("path")
              if not isinstance(path, (list, tuple)) or not path:
                  raise ValueError("bad metainfo - bad path")
  
              for part in path:
                  if not isinstance(part, basestring):
                      raise ValueError("bad metainfo - bad path dir")
                  part = fmt.to_unicode(part)
                  if part == '..':
                      raise ValueError("relative path in %s disallowed for security reasons" % '/'.join(path))
                  if part and not ALLOWED_PATH_NAME.match(part):
                      raise ValueError("path %s disallowed for security reasons" % part)
  
          file_paths = [os.sep.join(item["path"]) for item in files]
          if len(set(file_paths)) != len(file_paths):
              raise ValueError("bad metainfo - duplicate path")
  
      return info