diff --git a/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changelog-master.xml b/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changelog-master.xml
index 4b434101ce1..a65363cfa37 100644
--- a/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changelog-master.xml
+++ b/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changelog-master.xml
@@ -12,5 +12,6 @@
+
diff --git a/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changeset-2.9.xml b/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changeset-2.9.xml
new file mode 100644
index 00000000000..50ac6dcd15e
--- /dev/null
+++ b/modules/chimera/src/main/resources/org/dcache/chimera/changelog/changeset-2.9.xml
@@ -0,0 +1,127 @@
+
+
+
+
+ use encode on bytea field
+
+ CREATE OR REPLACE FUNCTION
+ path2inode(root varchar, path varchar)
+ RETURNS varchar AS $$
+ DECLARE
+ id varchar := root;
+ elements varchar[] := string_to_array(path, '/');
+ child varchar;
+ itype INT;
+ link varchar;
+ BEGIN
+ FOR i IN 1..array_upper(elements,1) LOOP
+ SELECT dir.ipnfsid, inode.itype INTO child, itype FROM t_dirs dir, t_inodes inode WHERE dir.ipnfsid = inode.ipnfsid AND dir.iparent=id AND dir.iname=elements[i];
+ IF itype=40960 THEN
+ SELECT encode(ifiledata,'escape') INTO link FROM t_inodes_data WHERE ipnfsid=child;
+ IF link LIKE '/%' THEN
+ child := path2inode('000000000000000000000000000000000000',
+ substring(link from 2));
+ ELSE
+ child := path2inode(id, link);
+ END IF;
+ END IF;
+ IF child IS NULL THEN
+ RETURN NULL;
+ END IF;
+ id := child;
+ END LOOP;
+ RETURN id;
+ END;
+ $$ LANGUAGE plpgsql;
+
+
+ CREATE OR REPLACE FUNCTION
+ path2inodes(root varchar, path varchar, OUT inode t_inodes)
+ RETURNS SETOF t_inodes AS $$
+ DECLARE
+ dir varchar;
+ elements text[] := string_to_array(path, '/');
+ inodes t_inodes[];
+ link varchar;
+ BEGIN
+ -- Find the inode of the root
+ SELECT * INTO inode FROM t_inodes WHERE ipnfsid = root;
+ IF NOT FOUND THEN
+ RETURN;
+ END IF;
+
+ -- We build an array of the inodes for the path
+ inodes := ARRAY[inode];
+
+ -- For each path element
+ FOR i IN 1..array_upper(elements,1) LOOP
+ -- Return empty set if not a directory
+ IF inode.itype != 16384 THEN
+ RETURN;
+ END IF;
+
+ -- The PNFS ID of the directory
+ dir := inode.ipnfsid;
+
+ -- Lookup the next path element
+ SELECT t_inodes.* INTO inode
+ FROM t_inodes, t_dirs
+ WHERE t_inodes.ipnfsid = t_dirs.ipnfsid
+ AND t_dirs.iparent = dir AND iname = elements[i];
+
+ -- Return the empty set if not found
+ IF NOT FOUND THEN
+ RETURN;
+ END IF;
+
+ -- Append the inode to the result set
+ inodes := array_append(inodes, inode);
+
+ -- If inode is a symbolic link
+ IF inode.itype = 40960 THEN
+ -- Read the link
+ SELECT encode(ifiledata,'escape') INTO STRICT link
+ FROM t_inodes_data WHERE ipnfsid = inode.ipnfsid;
+
+ -- If absolute path then resolve from the file system root
+ IF link LIKE '/%' THEN
+ dir := '000000000000000000000000000000000000';
+ link := substring(link from 2);
+
+ -- Call recursively and add inodes to result set
+ FOR inode IN SELECT * FROM path2inodes(dir, link) LOOP
+ inodes := array_append(inodes, inode);
+ END LOOP;
+ ELSE
+ -- Call recursively and add inodes to result set; skip
+ -- first inode as it is the inode of dir
+ FOR inode IN SELECT * FROM path2inodes(dir, link) OFFSET 1 LOOP
+ inodes := array_append(inodes, inode);
+ END LOOP;
+ END IF;
+
+ -- Return empty set if link could not be resolved
+ IF NOT FOUND THEN
+ RETURN;
+ END IF;
+
+ -- Continue from the inode pointed to by the link
+ inode = inodes[array_upper(inodes,1)];
+ END IF;
+ END LOOP;
+
+ -- Output all inodes
+ FOR i IN 1..array_upper(inodes,1) LOOP
+ inode := inodes[i];
+ RETURN NEXT;
+ END LOOP;
+ END;
+ $$ LANGUAGE plpgsql;
+
+
+
+