def generate_png(self): """ Generate a PNG from current Graph content. """ graph = self._generate_pydot() tmp_fd, tmp_path = const_mkstemp(prefix="entropy.graph", suffix=".png") os.close(tmp_fd) graph.write_png(tmp_path) const_setup_file(tmp_path, etpConst['entropygid'], 0o644) return tmp_path
def generate_dot(self): """ Generate RAW dot file that can be used to feed graphviz """ graph = self._generate_pydot() tmp_fd, tmp_path = const_mkstemp(prefix="entropy.graph", suffix=".dot") os.close(tmp_fd) graph.write_raw(tmp_path) const_setup_file(tmp_path, etpConst['entropygid'], 0o644) return tmp_path
def _file_lock_create(self, lock_path, blocking=False, shared=False): """ Create and allocate the lock file pointed by lock_data structure. """ lock_dir = os.path.dirname(lock_path) try: os.makedirs(lock_dir, 0o775) except OSError as err: if err.errno != errno.EEXIST: raise const_setup_directory(lock_dir) try: fmode = 0o664 if shared: fd = os.open(lock_path, os.O_CREAT | os.O_RDONLY, fmode) else: fd = os.open(lock_path, os.O_CREAT | os.O_APPEND, fmode) except OSError as err: if err.errno in (errno.ENOENT, errno.EACCES): # cannot get lock or dir doesn't exist return False, None raise # ensure that entropy group can write on that try: const_setup_file(lock_path, etpConst['entropygid'], 0o664) except OSError: pass flock_f = FlockFile(lock_path, fd=fd) if blocking: if shared: flock_f.acquire_shared() else: flock_f.acquire_exclusive() else: acquired = False if shared: acquired = flock_f.try_acquire_shared() else: acquired = flock_f.try_acquire_exclusive() if not acquired: return False, None return True, flock_f
def save(self): """ Save currently loaded authentication configuration to disk. @return: True, if save was effectively run @rtype: bool """ with self.__dump_lock: auth_file = self._get_authfile() if auth_file is not None: entropy.dump.dumpobj(auth_file, self._authstore, complete_path = True, custom_permissions = 0o600) # make sure if auth_file is not None: try: const_setup_file(auth_file, etpConst['entropygid'], 0o600) return True except (OSError, IOError): return False
def _get_authfile(self): """ Try to get the auth file. If it fails, return None. """ # setup auth file path home = os.getenv("HOME") auth_file = None if home is not None: if const_dir_writable(home): auth_file = os.path.join(home, AuthenticationStorage._AUTH_FILE) auth_dir = os.path.dirname(auth_file) if not os.path.isdir(auth_dir): try: os.makedirs(auth_dir, 0o700) const_setup_file(auth_dir, etpConst['entropygid'], 0o700) except (OSError, IOError): # ouch, no permissions auth_file = None return auth_file
def save(self): """ Save currently loaded authentication configuration to disk. @return: True, if save was effectively run @rtype: bool """ with self.__dump_lock: auth_file = self._get_authfile() if auth_file is not None: entropy.dump.dumpobj(auth_file, self._authstore, complete_path=True, custom_permissions=0o600) # make sure if auth_file is not None: try: const_setup_file(auth_file, etpConst['entropygid'], 0o600) return True except (OSError, IOError): return False
def dumpobj(name, my_object, complete_path=False, ignore_exceptions=True, dump_dir=None, custom_permissions=None): """ Dump pickable object to file @param name: name of the object @type name: string @param my_object: object to dump @type my_object: any Python "pickable" object @keyword complete_path: consider "name" argument as a complete path (this overrides the default dump path given by etpConst['dumpstoragedir']) @type complete_path: bool @keyword ignore_exceptions: ignore any possible exception (EOFError, IOError, OSError,) @type ignore_exceptions: bool @keyword dump_dir: alternative dump directory @type dump_dir: string @keyword custom_permissions: give custom permission bits @type custom_permissions: octal @return: None @rtype: None @raise EOFError: could be caused by pickle.dump, ignored if ignore_exceptions is True @raise IOError: could be caused by pickle.dump, ignored if ignore_exceptions is True @raise OSError: could be caused by pickle.dump, ignored if ignore_exceptions is True """ if dump_dir is None: dump_dir = D_DIR if custom_permissions is None: custom_permissions = 0o664 while True: # trap ctrl+C tmp_fd, tmp_dmpfile = None, None try: if complete_path: dmpfile = name c_dump_dir = os.path.dirname(name) else: _dmp_path = os.path.join(dump_dir, name) dmpfile = _dmp_path + D_EXT c_dump_dir = os.path.dirname(_dmp_path) my_dump_dir = c_dump_dir d_paths = [] while not os.path.isdir(my_dump_dir): d_paths.append(my_dump_dir) my_dump_dir = os.path.dirname(my_dump_dir) if d_paths: d_paths = sorted(d_paths) for d_path in d_paths: os.mkdir(d_path) const_setup_file(d_path, E_GID, 0o775) dmp_name = os.path.basename(dmpfile) tmp_fd, tmp_dmpfile = const_mkstemp(dir=c_dump_dir, prefix=dmp_name) # WARNING: it has been observed that using # os.fdopen() below in multi-threaded scenarios # is causing EBADF. There is probably a race # condition down in the stack. with open(tmp_dmpfile, "wb") as dmp_f: if const_is_python3(): pickle.dump(my_object, dmp_f, protocol=COMPAT_PICKLE_PROTOCOL, fix_imports=True) else: pickle.dump(my_object, dmp_f) const_setup_file(tmp_dmpfile, E_GID, custom_permissions) os.rename(tmp_dmpfile, dmpfile) except RuntimeError: try: os.remove(dmpfile) except OSError: pass except (EOFError, IOError, OSError): if not ignore_exceptions: raise finally: if tmp_fd is not None: try: os.close(tmp_fd) except (IOError, OSError): pass if tmp_dmpfile is not None: try: os.remove(tmp_dmpfile) except (IOError, OSError): pass break
def _file_lock_create(self, lock_path, blocking=False, shared=False): """ Create and allocate the lock file pointed by lock_data structure. """ lock_dir = os.path.dirname(lock_path) try: const_setup_directory(lock_dir) except OSError as err: const_debug_write( __name__, "Error in const_setup_directory %s: %s" % (lock_dir, err)) # we may just not have the perms to create the dir. if err.errno != errno.EPERM: raise try: fmode = 0o664 if shared: fd = os.open(lock_path, os.O_CREAT | os.O_RDONLY, fmode) else: fd = os.open(lock_path, os.O_CREAT | os.O_APPEND, fmode) except OSError as err: if err.errno in (errno.ENOENT, errno.EACCES): # cannot get lock or dir doesn't exist return False, None raise # ensure that entropy group can write on that try: const_setup_file(lock_path, etpConst['entropygid'], 0o664) except OSError: pass acquired = False flock_f = None try: flock_f = FlockFile(lock_path, fd=fd) if blocking: if shared: flock_f.acquire_shared() else: flock_f.acquire_exclusive() acquired = True return True, flock_f # non blocking if shared: acquired = flock_f.try_acquire_shared() else: acquired = flock_f.try_acquire_exclusive() if not acquired: return False, None return True, flock_f except Exception: if flock_f is not None: try: flock_f.close() except (OSError, IOError): pass flock_f = None raise finally: if not acquired and flock_f is not None: try: flock_f.close() except (OSError, IOError): pass flock_f = None
def dumpobj(name, my_object, complete_path = False, ignore_exceptions = True, dump_dir = None, custom_permissions = None): """ Dump pickable object to file @param name: name of the object @type name: string @param my_object: object to dump @type my_object: any Python "pickable" object @keyword complete_path: consider "name" argument as a complete path (this overrides the default dump path given by etpConst['dumpstoragedir']) @type complete_path: bool @keyword ignore_exceptions: ignore any possible exception (EOFError, IOError, OSError,) @type ignore_exceptions: bool @keyword dump_dir: alternative dump directory @type dump_dir: string @keyword custom_permissions: give custom permission bits @type custom_permissions: octal @return: None @rtype: None @raise EOFError: could be caused by pickle.dump, ignored if ignore_exceptions is True @raise IOError: could be caused by pickle.dump, ignored if ignore_exceptions is True @raise OSError: could be caused by pickle.dump, ignored if ignore_exceptions is True """ if dump_dir is None: dump_dir = D_DIR if custom_permissions is None: custom_permissions = 0o664 while True: # trap ctrl+C tmp_fd, tmp_dmpfile = None, None try: if complete_path: dmpfile = name c_dump_dir = os.path.dirname(name) else: _dmp_path = os.path.join(dump_dir, name) dmpfile = _dmp_path+D_EXT c_dump_dir = os.path.dirname(_dmp_path) my_dump_dir = c_dump_dir d_paths = [] while not os.path.isdir(my_dump_dir): d_paths.append(my_dump_dir) my_dump_dir = os.path.dirname(my_dump_dir) if d_paths: d_paths = sorted(d_paths) for d_path in d_paths: os.mkdir(d_path) const_setup_file(d_path, E_GID, 0o775) dmp_name = os.path.basename(dmpfile) tmp_fd, tmp_dmpfile = const_mkstemp( dir=c_dump_dir, prefix=dmp_name) # WARNING: it has been observed that using # os.fdopen() below in multi-threaded scenarios # is causing EBADF. There is probably a race # condition down in the stack. with open(tmp_dmpfile, "wb") as dmp_f: if const_is_python3(): pickle.dump(my_object, dmp_f, protocol = COMPAT_PICKLE_PROTOCOL, fix_imports = True) else: pickle.dump(my_object, dmp_f) const_setup_file(tmp_dmpfile, E_GID, custom_permissions) os.rename(tmp_dmpfile, dmpfile) except RuntimeError: try: os.remove(dmpfile) except OSError: pass except (EOFError, IOError, OSError): if not ignore_exceptions: raise finally: if tmp_fd is not None: try: os.close(tmp_fd) except (IOError, OSError): pass if tmp_dmpfile is not None: try: os.remove(tmp_dmpfile) except (IOError, OSError): pass break
def _insert_generic_file(self, pkgkey, userid, username, file_path, file_name, doc_type, title, description, keywords): file_path = os.path.realpath(file_path) # do a virus check? virus_found, virus_type = self._scan_for_viruses(file_path) if virus_found: os.remove(file_path) return False, None # flood control flood_risk = self.insert_flood_control_check(userid) if flood_risk: return False, 'flooding detected' # validity check if doc_type == self.DOC_TYPES['image']: valid = False if os.path.isfile(file_path) and os.access(file_path, os.R_OK): valid = entropy.tools.is_supported_image_file(file_path) if not valid: return False, 'not a valid image' dest_path = os.path.join(self.STORE_PATH, file_name) # create dir if not exists dest_dir = os.path.dirname(dest_path) if not os.path.isdir(dest_dir): try: os.makedirs(dest_dir) except OSError as err: raise PermissionDenied(err) if etpConst['entropygid'] != None: const_setup_perms(dest_dir, etpConst['entropygid'], recursion=False) orig_dest_path = dest_path dcount = 0 while os.path.isfile(dest_path): dcount += 1 dest_path_name = "%s_%s" % ( dcount, os.path.basename(orig_dest_path), ) dest_path = os.path.join(os.path.dirname(orig_dest_path), dest_path_name) if os.path.dirname(file_path) != dest_dir: try: os.rename(file_path, dest_path) except OSError: # fallback to non atomic shutil.move(file_path, dest_path) if etpConst['entropygid'] != None: try: const_setup_file(dest_path, etpConst['entropygid'], 0o664) except OSError: pass # at least set chmod try: const_set_chmod(dest_path, 0o664) except OSError: pass title = title[:self.entropy_docs_title_len] description = description[:self.entropy_docs_description_len] # now store in db idkey = self._handle_pkgkey(pkgkey) self.execute_query( """ INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s) """, ( None, idkey, userid, username, doc_type, file_name, title, description, None, )) iddoc = self.lastrowid() self._insert_keywords(iddoc, keywords) store_url = os.path.basename(dest_path) if self._store_url: store_url = os.path.join(self._store_url, store_url) return True, (iddoc, store_url)
def _file_lock_create(self, lock_path, blocking=False, shared=False): """ Create and allocate the lock file pointed by lock_data structure. """ lock_dir = os.path.dirname(lock_path) try: const_setup_directory(lock_dir) except OSError as err: const_debug_write( __name__, "Error in const_setup_directory %s: %s" % ( lock_dir, err)) # we may just not have the perms to create the dir. if err.errno != errno.EPERM: raise try: fmode = 0o664 if shared: fd = os.open(lock_path, os.O_CREAT | os.O_RDONLY, fmode) else: fd = os.open(lock_path, os.O_CREAT | os.O_APPEND, fmode) except OSError as err: if err.errno in (errno.ENOENT, errno.EACCES): # cannot get lock or dir doesn't exist return False, None raise # ensure that entropy group can write on that try: const_setup_file(lock_path, etpConst['entropygid'], 0o664) except OSError: pass acquired = False flock_f = None try: flock_f = FlockFile(lock_path, fd=fd) if blocking: if shared: flock_f.acquire_shared() else: flock_f.acquire_exclusive() acquired = True return True, flock_f # non blocking if shared: acquired = flock_f.try_acquire_shared() else: acquired = flock_f.try_acquire_exclusive() if not acquired: return False, None return True, flock_f except Exception: if flock_f is not None: try: flock_f.close() except (OSError, IOError): pass flock_f = None raise finally: if not acquired and flock_f is not None: try: flock_f.close() except (OSError, IOError): pass flock_f = None
def _insert_generic_file(self, pkgkey, userid, username, file_path, file_name, doc_type, title, description, keywords): file_path = os.path.realpath(file_path) # do a virus check? virus_found, virus_type = self._scan_for_viruses(file_path) if virus_found: os.remove(file_path) return False, None # flood control flood_risk = self.insert_flood_control_check(userid) if flood_risk: return False, 'flooding detected' # validity check if doc_type == self.DOC_TYPES['image']: valid = False if os.path.isfile(file_path) and os.access(file_path, os.R_OK): valid = entropy.tools.is_supported_image_file(file_path) if not valid: return False, 'not a valid image' dest_path = os.path.join(self.STORE_PATH, file_name) # create dir if not exists dest_dir = os.path.dirname(dest_path) if not os.path.isdir(dest_dir): try: os.makedirs(dest_dir) except OSError as err: raise PermissionDenied(err) if etpConst['entropygid'] != None: const_setup_perms(dest_dir, etpConst['entropygid'], recursion = False) orig_dest_path = dest_path dcount = 0 while os.path.isfile(dest_path): dcount += 1 dest_path_name = "%s_%s" % (dcount, os.path.basename(orig_dest_path),) dest_path = os.path.join(os.path.dirname(orig_dest_path), dest_path_name) if os.path.dirname(file_path) != dest_dir: try: os.rename(file_path, dest_path) except OSError: # fallback to non atomic shutil.move(file_path, dest_path) if etpConst['entropygid'] != None: try: const_setup_file(dest_path, etpConst['entropygid'], 0o664) except OSError: pass # at least set chmod try: const_set_chmod(dest_path, 0o664) except OSError: pass title = title[:self.entropy_docs_title_len] description = description[:self.entropy_docs_description_len] # now store in db idkey = self._handle_pkgkey(pkgkey) self.execute_query(""" INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s) """, (None, idkey, userid, username, doc_type, file_name, title, description, None,)) iddoc = self.lastrowid() self._insert_keywords(iddoc, keywords) store_url = os.path.basename(dest_path) if self._store_url: store_url = os.path.join(self._store_url, store_url) return True, (iddoc, store_url)