Esempio n. 1
0
    def _create_tmp(self):
        global PEER
        logging.critical("PEER in queue: %s", PEER)
        now = time.time()
        uniq = "%s.M%sP%sQ%s-%s-%s-%s" % (
            int(now),
            int(now % 1 * 1e6),
            os.getpid(),
            mailbox.Maildir._count,
            PEER[0],
            sensorName,
            USER,
        )
        path = os.path.join(self._path, 'tmp', uniq)
        try:
            os.stat(path)
        except OSError as e:
            if e.errno == errno.ENOENT:
                mailbox.Maildir._count += 1
                try:
                    return mailbox._create_carefully(path)
                except OSError as e:
                    if e.errno != errno.EEXIST:
                        raise
            else:
                raise

        # Fall through to here if stat succeeded or open raised EEXIST.
        raise mailbox.ExternalClashError(
            'Name clash prevented file creation: %s' % path)
Esempio n. 2
0
 def _create_tmp(self):
     now = time.time()
     rand = binascii.hexlify(os.urandom(4)).decode()
     uniq = f"{now:.8f}.{rand}.eml"
     path = os.path.join(self._path, "tmp", uniq)
     try:
         os.stat(path)
     except FileNotFoundError:
         try:
             return mailbox._create_carefully(path)
         except FileExistsError:
             pass
     raise mailbox.ExternalClashError(
         f"name clash prevented file creation: {path}")
Esempio n. 3
0
    def add(self, message):
        """Add message and return assigned key."""
        key = self._encryption_key_func()
        es = None
        try:
            tmpdir = os.path.join(self._path, 'tmp')
            if not os.path.exists(tmpdir):
                os.mkdir(tmpdir, 0o700)
            if key:
                es = EncryptingStreamer(key,
                                        dir=tmpdir,
                                        name='WERVD',
                                        delimited=False)
            else:
                es = ChecksummingStreamer(dir=tmpdir, name='WERVD')
            self._dump_message(message, es)
            es.finish()

            # We are using the MAC to detect file system corruption, not in a
            # security context - so using as little as 40 bits should be fine.
            saved = False
            key = None
            outer_mac = es.outer_mac_sha256()
            for l in range(10, len(outer_mac)):
                key = outer_mac[:l]
                fn = os.path.join(self._path, 'new', key)
                if not os.path.exists(fn):
                    es.save(fn)
                    saved = self._toc[key] = os.path.join('new', key)
                    break
            if not saved:
                raise mailbox.ExternalClashError(
                    _('Could not find a filename '
                      'for the message.'))


# FIXME: Copies
#           for fn in self._copy_paths('new', key, copies):
#               with mailbox._create_carefully(fn) as ofd:
#                   es.save_copy(ofd)

            return key
        finally:
            if es is not None:
                es.close()
Esempio n. 4
0
    def _create_tmp(self):
        now = time.time()
        uniq = "%s.M%sP%sQ%s.%s" % (int(now), int(now % 1 * 1e6), os.getpid(),
                                    mailbox.Maildir._count, HASHED_HOSTNAME)
        path = os.path.join(self._path, 'tmp', uniq)
        try:
            os.stat(path)
        except OSError as e:
            if e.errno == errno.ENOENT:
                mailbox.Maildir._count += 1
                try:
                    return mailbox._create_carefully(path)
                except OSError as e:
                    if e.errno != errno.EEXIST:
                        raise
            else:
                raise

        # Fall through to here if stat succeeded or open raised EEXIST.
        raise mailbox.ExternalClashError('Name clash prevented file creation: %s' % path)
Esempio n. 5
0
    def add(self, message, copies=1):
        """Add message and return assigned key."""
        key = self._encryption_key_func()
        try:
            if key:
                es = EncryptingStreamer(key,
                                        dir=os.path.join(self._path, 'tmp'),
                                        name='WERVD',
                                        delimited=False)
            else:
                es = ChecksummingStreamer(dir=os.path.join(self._path, 'tmp'),
                                          name='WERVD')
            self._dump_message(message, es)
            es.finish()

            # We are using the MD5 to detect file system corruption, not in a
            # security context - so using as little as 40 bits should be fine.
            saved = False
            key = None
            for l in range(10, len(es.outer_md5sum)):
                key = es.outer_md5sum[:l]
                fn = os.path.join(self._path, 'new', key)
                if not os.path.exists(fn):
                    es.save(fn)
                    saved = self._toc[key] = os.path.join('new', key)
                    break
            if not saved:
                raise mailbox.ExternalClashError(_('Could not find a filename '
                                                   'for the message.'))

            for cpn in range(1, copies):
                fn = os.path.join(self._path, 'new', '%s.%s' % (key, cpn))
                with mailbox._create_carefully(fn) as ofd:
                    es.save_copy(ofd)

            return key
        finally:
            es.close()
Esempio n. 6
0
        path = os.path.join(self._path, 'tmp', uniq)
        try:
            os.stat(path)
        except OSError, e:
            if e.errno == errno.ENOENT:
                mailbox.Maildir._count += 1
                try:
                    return mailbox._create_carefully(path)
                except OSError, e:
                    if e.errno != errno.EEXIST:
                        raise
            else:
                raise

        # Fall through to here if stat succeeded or open raised EEXIST.
        raise mailbox.ExternalClashError(
            'Name clash prevented file creation: %s' % path)


class QueueError(Exception):
    def __init__(self, msg, data):
        Exception.__init__(self, msg)
        self._message = msg
        self.data = data


class Queue(object):
    """
    Provides a simplified API for dealing with 'queues' in Artemis.
    It currently just supports maildir queues since those are the 
    most robust, but could implement others later.
    """
Esempio n. 7
0
    def flush(self):
        """Write any pending changes to disk. This is called on mailbox
        close and is usually not called explicitly.

        .. note::

           This deletes messages via truncation. Interruptions may
           corrupt your mailbox.
        """

        # Appending and basic assertions are the same as in mailbox.mbox.flush.
        if not self._pending:
            if self._pending_sync:
                # Messages have only been added, so syncing the file
                # is enough.
                mailbox._sync_flush(self._file)
                self._pending_sync = False
            return

        # In order to be writing anything out at all, self._toc must
        # already have been generated (and presumably has been modified
        # by adding or deleting an item).
        assert self._toc is not None

        # Check length of self._file; if it's changed, some other process
        # has modified the mailbox since we scanned it.
        self._file.seek(0, 2)
        cur_len = self._file.tell()
        if cur_len != self._file_length:
            raise mailbox.ExternalClashError('Size of mailbox file changed '
                                             '(expected %i, found %i)' %
                                             (self._file_length, cur_len))

        self._file.seek(0)

        # Truncation logic begins here.  Mostly the same except we
        # can use tempfile because we're not doing rename(2).
        with tempfile.TemporaryFile() as new_file:
            new_toc = {}
            self._pre_mailbox_hook(new_file)
            for key in sorted(self._toc.keys()):
                start, stop = self._toc[key]
                self._file.seek(start)
                self._pre_message_hook(new_file)
                new_start = new_file.tell()
                while True:
                    buffer = self._file.read(min(4096,
                                                 stop - self._file.tell()))
                    if buffer == '':
                        break
                    new_file.write(buffer)
                new_toc[key] = (new_start, new_file.tell())
                self._post_message_hook(new_file)
            self._file_length = new_file.tell()

            self._file.seek(0)
            new_file.seek(0)

            # Copy back our messages
            if self._file_length <= self.maxmem:
                self._file.write(new_file.read())
            else:
                while True:
                    buffer = new_file.read(4096)
                    if not buffer:
                        break
                    self._file.write(buffer)

            # Delete the rest.
            self._file.truncate()

        # Same wrap up.
        self._toc = new_toc
        self._pending = False
        self._pending_sync = False
        if self._locked:
            mailbox._lock_file(self._file, dotlock=False)