code: def find_id3v1(fileobj, v2_version=4, known_frames=None):
      
  
      if v2_version not in (3, 4):
          raise ValueError("Only 3 and 4 possible for v2_version")
  
      # id3v1 is always at the end (after apev2)
  
      extra_read = b"APETAGEX".index(b"TAG")
  
      old_pos = fileobj.tell()
      try:
          fileobj.seek(-128 - extra_read, 2)
      except IOError as e:
          if e.errno == errno.EINVAL:
              # If the file is too small, might be ok since we wrote too small
              # tags at some point. let's see how the parsing goes..
              fileobj.seek(0, 0)
          else:
              raise
  
      data = fileobj.read(128 + extra_read)
      fileobj.seek(old_pos, 0)
      try:
          idx = data.index(b"TAG")
      except ValueError:
          return (None, 0)
      else:
          # FIXME: make use of the apev2 parser here
          # if TAG is part of APETAGEX assume this is an APEv2 tag
          try:
              ape_idx = data.index(b"APETAGEX")
          except ValueError:
              pass
          else:
              if idx == ape_idx + extra_read:
                  return (None, 0)
  
          tag = ParseID3v1(data[idx:], v2_version, known_frames)
          if tag is None:
              return (None, 0)
  
          offset = idx - len(data)
          return (tag, offset)
docs: Returns a tuple of (id3tag, offset_to_end) or (None, 0)
  
      offset mainly because we used to write too short tags in some cases and
      we need the offset to delete them.
  
      v2_version: Decides whether ID3v2.3 or ID3v2.4 tags
                  should be returned. Must be 3 or 4.
  
      known_frames (Dict[`mutagen.text`, `Frame`]): dict mapping frame
          IDs to Frame objects