diff --git a/.gitignore b/.gitignore
index 76ed1fcb..63f8076a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ cdist/version.py
 build
 .lock-*
 .git-current-branch
+.lock*
diff --git a/cdist/conf/type/__directory/explorer/owner b/cdist/conf/type/__directory/explorer/owner
deleted file mode 100644
index cebd199b..00000000
--- a/cdist/conf/type/__directory/explorer/owner
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
-#
-# This file is part of cdist.
-#
-# cdist is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# cdist is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with cdist. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# Check whether file exists or not
-#
-
-destination="/$__object_id"
-os=$("$__explorer/os")
-
-case "$os" in
-   "freebsd")
-      cmd="stat -f %Su"
-      ;;  
-   *)  
-      cmd="stat -c %U"
-      ;;  
-esac
-
-if [ -e "$destination" ]; then
-  $cmd "$destination"
-fi
-
diff --git a/cdist/conf/type/__directory/explorer/group b/cdist/conf/type/__directory/explorer/stat
old mode 100644
new mode 100755
similarity index 65%
rename from cdist/conf/type/__directory/explorer/group
rename to cdist/conf/type/__directory/explorer/stat
index e5be37da..d8cdbb9e
--- a/cdist/conf/type/__directory/explorer/group
+++ b/cdist/conf/type/__directory/explorer/stat
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,23 +17,27 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# Check whether file exists or not
-#
 
 destination="/$__object_id"
-os=$("$__explorer/os")
 
+# nothing to work with, nothing we could do
+[ -e "$destination" ] || exit 0
+
+os=$("$__explorer/os")
 case "$os" in
    "freebsd")
-      cmd="stat -f %Sg"
-      ;;
+      # FIXME: should be something like this based on man page, but can not test
+      stat -f "type: %ST
+owner: %Du %Su
+group: %Dg %Sg
+mode: %Op %Sp
+" "$destination"
+   ;;
    *)
-      cmd="stat -c %G"
-      ;;
+      stat --printf="type: %F
+owner: %u %U
+group: %g %G
+mode: %a %A
+" "$destination"
+   ;;
 esac
-
-if [ -e "$destination" ]; then
-  $cmd "$destination"
-fi
-
diff --git a/cdist/conf/type/__file/explorer/exists b/cdist/conf/type/__directory/explorer/type
similarity index 72%
rename from cdist/conf/type/__file/explorer/exists
rename to cdist/conf/type/__directory/explorer/type
index c319cb5d..e723047c 100755
--- a/cdist/conf/type/__file/explorer/exists
+++ b/cdist/conf/type/__directory/explorer/type
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,14 +17,17 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# Check whether file exists or not
-#
 
 destination="/$__object_id"
 
-if [ -e "$destination" ]; then
-    echo yes
+if [ ! -e "$destination" ]; then
+   echo none
+elif [ -h "$destination" ]; then
+   echo symlink
+elif [ -f "$destination" ]; then
+   echo file
+elif [ -d "$destination" ]; then
+   echo directory
 else
-    echo no
+   echo unknown
 fi
diff --git a/cdist/conf/type/__directory/gencode-remote b/cdist/conf/type/__directory/gencode-remote
index f46a5967..800fc6e4 100755
--- a/cdist/conf/type/__directory/gencode-remote
+++ b/cdist/conf/type/__directory/gencode-remote
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
-# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2011-2013 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -19,53 +20,84 @@
 #
 
 destination="/$__object_id"
+state_should="$(cat "$__object/parameter/state")"
+type="$(cat "$__object/explorer/type")"
+stat_file="$__object/explorer/stat"
 
-state_is="$(cat "$__object/explorer/state")"
-owner_is="$(cat "$__object/explorer/owner")"
-group_is="$(cat "$__object/explorer/group")"
-mode_is="$(cat "$__object/explorer/mode")"
+# variable to keep track if we have to set directory attributes
+set_attributes=
 
-state_should="present"
-[ -f "$__object/parameter/state" ]     && state_should="$(cat "$__object/parameter/state")"
-mode=""
-[ -f "$__object/parameter/mode" ]      && mode="$(cat "$__object/parameter/mode")"
-owner=""
-[ -f "$__object/parameter/owner" ]     && owner="$(cat "$__object/parameter/owner")"
-group=""
-[ -f "$__object/parameter/group" ]     && group="$(cat "$__object/parameter/group")"
 mkdiropt=""
-[ -f "$__object/parameter/parents" ]   && mkdiropt="-p"
+[ -f "$__object/parameter/parents" ] && mkdiropt="-p"
+
 recursive=""
-[ -f "$__object/parameter/recursive" ] && recursive="-R"
+if [ -f "$__object/parameter/recursive" ]; then
+   recursive="-R"
+   # need to allways set attributes when recursive is given
+   # as we don't want to check all subfolders/files
+   set_attributes=1
+fi
+
+get_current_value() {
+   if [ -s "$stat_file" ]; then
+      _name="$1"
+      _value="$2"
+      case "$_value" in
+         [0-9]*)
+            _index=2
+         ;;
+         *)
+            _index=3
+         ;;
+      esac
+      awk '/'"$_name"':/ { print $'$_index' }' "$stat_file"
+      unset _name _value _index
+   fi
+}
+
+set_group() {
+   echo chgrp $recursive \"$1\" \"$destination\"
+}
+
+set_owner() {
+   echo chown $recursive \"$1\" \"$destination\"
+}
+
+set_mode() {
+   echo chmod $recursive \"$1\" \"$destination\"
+}
 
 case "$state_should" in
-    present)
-        if [ "$state_is" != "present" ]; then
-            echo mkdir $mkdiropt \"$destination\"
-        fi
+   present)
+      if [ "$type" != "directory" ]; then
+         # our destination is not a directory, remove whatever is there
+         # and then create our directory and set all attributes
+         set_attributes=1
+         cat << DONE
+rm -f "$destination"
+mkdir $mkdiropt "$destination"
+DONE
+      fi
 
-        # Mode settings
-        if [ "$mode" ] && [ "$mode_is" != "$mode" -o -n "$recursive" ]; then
-            echo chmod $recursive \"$mode\" \"$destination\"
-        fi
-
-        # Group
-        if [ "$group" ] && [ "$group_is" != "$group" -o -n "$recursive" ]; then
-            echo chgrp $recursive \"$group\" \"$destination\"
-        fi
-
-        # Owner
-        if [ "$owner" ] && [ "$owner_is" != "$owner" -o -n "$recursive" ]; then
-            echo chown $recursive \"$owner\" \"$destination\"
-        fi
-    ;;
-    absent)
-        if [ "$state_is" != "absent" ]; then
-          echo rm -rf \"$destination\"
-        fi
-    ;;
-    *)
-        echo "Unknown state: $state_should" >&2
-        exit 1
-    ;;
+      # Note: Mode - needs to happen last as a chown/chgrp can alter mode by
+      # clearing S_ISUID and S_ISGID bits (see chown(2))
+      for attribute in group owner mode; do
+         if [ -f "$__object/parameter/$attribute" ]; then
+            value_should="$(cat "$__object/parameter/$attribute")"
+            value_is="$(get_current_value "$attribute" "$value_should")"
+            if [ "$set_attributes" -o "$value_should" != "$value_is" ]; then
+               "set_$attribute" "$value_should"
+            fi
+         fi
+      done
+   ;;
+   absent)
+      if [ "$type" = "directory" ]; then
+         echo rm -rf \"$destination\"
+      fi
+   ;;
+   *)
+      echo "Unknown state: $state_should" >&2
+      exit 1
+   ;;
 esac
diff --git a/cdist/conf/type/__directory/parameter/default/state b/cdist/conf/type/__directory/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__directory/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__directory/explorer/mode b/cdist/conf/type/__file/explorer/stat
old mode 100644
new mode 100755
similarity index 63%
rename from cdist/conf/type/__directory/explorer/mode
rename to cdist/conf/type/__file/explorer/stat
index f75b282b..298221b7
--- a/cdist/conf/type/__directory/explorer/mode
+++ b/cdist/conf/type/__file/explorer/stat
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,23 +17,31 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# Check whether file exists or not
-#
 
 destination="/$__object_id"
-os=$("$__explorer/os")
 
+# nothing to work with, nothing we could do
+[ -e "$destination" ] || exit 0
+
+os=$("$__explorer/os")
 case "$os" in
    "freebsd")
-      cmd="stat -f %Op"
-      ;;
+      # FIXME: should be something like this based on man page, but can not test
+      stat -f "type: %ST
+owner: %Du %Su
+group: %Dg %Sg
+mode: %Op %Sp
+size: %Dz
+links: %Dl
+" "$destination"
+   ;;
    *)
-      cmd="stat -c %a"
-      ;;
+      stat --printf="type: %F
+owner: %u %U
+group: %g %G
+mode: %a %A
+size: %s
+links: %h
+" "$destination"
+   ;;
 esac
-
-if [ -e "$destination" ]; then
-  $cmd "$destination"
-fi
-
diff --git a/cdist/conf/type/__directory/explorer/state b/cdist/conf/type/__file/explorer/type
similarity index 72%
rename from cdist/conf/type/__directory/explorer/state
rename to cdist/conf/type/__file/explorer/type
index 9bdd9024..e723047c 100755
--- a/cdist/conf/type/__directory/explorer/state
+++ b/cdist/conf/type/__file/explorer/type
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,14 +17,17 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# Check whether file exists or not
-#
 
 destination="/$__object_id"
 
-if [ -e "$destination" ]; then
-   echo present
+if [ ! -e "$destination" ]; then
+   echo none
+elif [ -h "$destination" ]; then
+   echo symlink
+elif [ -f "$destination" ]; then
+   echo file
+elif [ -d "$destination" ]; then
+   echo directory
 else
-   echo absent
+   echo unknown
 fi
diff --git a/cdist/conf/type/__file/gencode-local b/cdist/conf/type/__file/gencode-local
index 8cd9b24e..a9eb6b10 100755
--- a/cdist/conf/type/__file/gencode-local
+++ b/cdist/conf/type/__file/gencode-local
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,35 +18,59 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# __file is a very basic type, which will probably be reused quite often
-#
 
 destination="/$__object_id"
-state_should=present
-[ -f "$__object/parameter/state" ] && state_should="$(cat "$__object/parameter/state")"
-exists="$(cat "$__object/explorer/exists")"
+state_should="$(cat "$__object/parameter/state")"
+type="$(cat "$__object/explorer/type")"
 
-[ "$state_should" = "exists" -a "$exists" = "yes" ] && exit 0 # nothing to do
+[ "$state_should" = "exists" -a "$type" = "file" ] && exit 0 # nothing to do
 
+upload_file=
+create_file=
 if [ "$state_should" = "present" -o "$state_should" = "exists" ]; then
-   if [ -f "$__object/parameter/source" ]; then
+   if [ ! -f "$__object/parameter/source" ]; then
+      create_file=1
+   else
       source="$(cat "$__object/parameter/source")"
       if [ "$source" = "-" ]; then
          source="$__object/stdin"
       fi
-
-      if [ -f "$source" ]; then
-         local_cksum="$(cksum < "$source")"
-         remote_cksum="$(cat "$__object/explorer/cksum")"
-
-         if [ "$local_cksum" != "$remote_cksum" ]; then
-            echo "$__remote_copy" "$source" "${__target_host}:${destination}"
-            echo "copy" >> "$__messages_out"
-         fi
-      else
+      if [ ! -f "$source" ]; then
          echo "Source \"$source\" does not exist." >&2
          exit 1
+      else
+         if [ "$type" != "file" ]; then
+            # destination is not a regular file, upload source to replace it
+            upload_file=1
+         else
+            local_cksum="$(cksum < "$source")"
+            remote_cksum="$(cat "$__object/explorer/cksum")"
+            if [ "$local_cksum" != "$remote_cksum" ]; then
+               # destination is a regular file, but not the right one
+               upload_file=1
+            fi
+         fi
       fi
    fi
+   if [ "$create_file" -o "$upload_file" ]; then
+      # tell gencode-remote that we created or uploaded a file and that it must
+      # set all attributes no matter what the explorer retreived
+      mkdir "$__object/files"
+      touch "$__object/files/set-attributes"
+
+      # upload file to temp location
+      tempfile_template="${destination}.cdist.XXXXXXXXXX"
+      cat << DONE
+destination_upload="\$($__remote_exec $__target_host "mktemp $tempfile_template")"
+DONE
+      if [ "$upload_file" ]; then
+         cat << DONE
+$__remote_copy $source ${__target_host}:\$destination_upload
+DONE
+      fi
+# move uploaded file into place
+cat << DONE
+$__remote_exec $__target_host "rm -rf \"$destination\"; mv \"\$destination_upload\" \"$destination\""
+DONE
+   fi
 fi
diff --git a/cdist/conf/type/__file/gencode-remote b/cdist/conf/type/__file/gencode-remote
index 6e1fa5be..e80d5fae 100755
--- a/cdist/conf/type/__file/gencode-remote
+++ b/cdist/conf/type/__file/gencode-remote
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -17,59 +18,66 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# __file is a very basic type, which will probably be reused quite often
-#
 
 destination="/$__object_id"
-state_should=present
-[ -f "$__object/parameter/state" ] && state_should="$(cat "$__object/parameter/state")"
-exists="$(cat "$__object/explorer/exists")"
+state_should="$(cat "$__object/parameter/state")"
+type="$(cat "$__object/explorer/type")"
+stat_file="$__object/explorer/stat"
 
+
+get_current_value() {
+   if [ -s "$stat_file" ]; then
+      _name="$1"
+      _value="$2"
+      case "$_value" in
+         [0-9]*)
+            _index=2
+         ;;
+         *)
+            _index=3
+         ;;
+      esac
+      awk '/'"$_name"':/ { print $'$_index' }' "$stat_file"
+      unset _name _value _index
+   fi
+}
+
+set_group() {
+   echo chgrp \"$1\" \"$destination\"
+}
+
+set_owner() {
+   echo chown \"$1\" \"$destination\"
+}
+
+set_mode() {
+   echo chmod \"$1\" \"$destination\"
+}
+
+set_attributes=
 case "$state_should" in
    present|exists)
-      # No source? Create empty file
-      if [ ! -f "$__object/parameter/source" ]; then
-         if [ "$exists" = "no" ]; then
-            echo touch \"$destination\"
+      # Note: Mode - needs to happen last as a chown/chgrp can alter mode by
+      #  clearing S_ISUID and S_ISGID bits (see chown(2))
+      for attribute in group owner mode; do
+         if [ -f "$__object/parameter/$attribute" ]; then
+            value_should="$(cat "$__object/parameter/$attribute")"
+            value_is="$(get_current_value "$attribute" "$value_should")"
+            if [ -f "$__object/files/set-attributes" -o "$value_should" != "$value_is" ]; then
+               "set_$attribute" "$value_should"
+            fi
          fi
-      fi
-
-      # Group
-      if [ -f "$__object/parameter/group" ]; then
-         echo chgrp \"$(cat "$__object/parameter/group")\" \"$destination\"
-# FIXME: only if necessary, not if parameter is present
-#         echo "chgrp" >> "$__object/notifications"
-      fi
-
-      # Owner
-      if [ -f "$__object/parameter/owner" ]; then
-         echo chown \"$(cat "$__object/parameter/owner")\" \"$destination\"
-# FIXME: only if necessary, not if parameter is present
-#         echo "chown" >> "$__object/notifications"
-      fi
-
-      # Mode - needs to happen last as a chown/chgrp can alter mode by
-      # clearing S_ISUID and S_ISGID bits (see chown(2))
-      if [ -f "$__object/parameter/mode" ]; then
-         echo chmod \"$(cat "$__object/parameter/mode")\" \"$destination\"
-# FIXME: only if necessary, not if parameter is present
-#         echo "chmod" >> "$__object/notifications"
-      fi
+      done
    ;;
 
    absent)
-
-      if [ "$exists" = "yes" ]; then
+      if [ "$type" = "file" ]; then
          echo rm -f \"$destination\"
-         echo "remove" >> "$__messages_out"
       fi
-
    ;;
 
    *)
       echo "Unknown state: $state_should" >&2
       exit 1
    ;;
-
 esac
diff --git a/cdist/conf/type/__file/man.text b/cdist/conf/type/__file/man.text
index 9ac82d0f..b76573bb 100644
--- a/cdist/conf/type/__file/man.text
+++ b/cdist/conf/type/__file/man.text
@@ -13,6 +13,15 @@ DESCRIPTION
 This cdist type allows you to create files, remove files and set file
 attributes on the target.
 
+If the file already exists on the target, then if it is a:
+- regular file, and state is:
+   present: replace it with the source file if they are not equal
+   exists: do nothing
+- symlink: replace it with the source file
+- directory: replace it with the source file
+
+In any case, make sure that the file attributes are as specified.
+
 
 REQUIRED PARAMETERS
 -------------------
diff --git a/cdist/conf/type/__file/parameter/default/state b/cdist/conf/type/__file/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__file/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__link/explorer/type b/cdist/conf/type/__link/explorer/type
new file mode 100755
index 00000000..579fd081
--- /dev/null
+++ b/cdist/conf/type/__link/explorer/type
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# Mostly a wrapper for ln
+#
+
+destination="/$__object_id"
+
+if [ ! -e "$destination" ]; then
+   echo none
+elif [ -h "$destination" ]; then
+   echo symlink
+elif [ -f "$destination" ]; then
+   type="$(cat "$__object/parameter/type")"
+   case "$type" in
+      hard)
+         link_count=$(ls -l "$destination" | awk '{ print $2 }')
+         if [ $link_count -gt 1 ]; then
+            echo hardlink
+            exit 0
+         fi
+      ;;
+   esac
+   echo file
+elif [ -d "$destination" ]; then
+   echo directory
+else
+   echo unknown
+fi
diff --git a/cdist/conf/type/__link/gencode-remote b/cdist/conf/type/__link/gencode-remote
index 2975ef69..cbdfd30f 100755
--- a/cdist/conf/type/__link/gencode-remote
+++ b/cdist/conf/type/__link/gencode-remote
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist at armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -40,17 +41,30 @@ case "$type" in
 esac
 
 state_is="$(cat "$__object/explorer/state")"
-state_should=present
-[ -f "$__object/parameter/state" ] && state_should="$(cat "$__object/parameter/state")"
+state_should="$(cat "$__object/parameter/state")"
 
 [ "$state_should" = "$state_is" ] && exit 0
 
+file_type="$(cat "$__object/explorer/type")"
 case "$state_should" in
     present)
-        echo ln ${lnopt} -f \"$source\" \"$destination\"
+        if [ "$file_type" = "directory" ]; then
+            # our destination is currently a directory, delete it
+            cat << DONE
+rm -rf "$destination"
+DONE
+        fi
+
+        # create our link
+        cat << DONE
+ln ${lnopt} -f "$source" "$destination"
+DONE
     ;;
     absent)
-        echo rm -f \"$destination\"
+        # only delete if it is a sym/hard link
+        if [ "$file_type" = "symlink" -o "$file_type" = "hardlink" ]; then
+            echo rm -f \"$destination\"
+        fi
     ;;
     *)
         echo "Unknown state: $state_should" >&2
diff --git a/cdist/conf/type/__link/parameter/default/state b/cdist/conf/type/__link/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__link/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__package_zypper/explorer/pkg_version b/cdist/conf/type/__package_zypper/explorer/pkg_version
old mode 100755
new mode 100644
index fb3b7753..655b464d
--- a/cdist/conf/type/__package_zypper/explorer/pkg_version
+++ b/cdist/conf/type/__package_zypper/explorer/pkg_version
@@ -27,4 +27,4 @@ else
    name="$__object_id"
 fi
 
-rpm -q --whatprovides "$name" 2>/dev/null || true
+rpm -q --whatprovides "$name"  | grep -v 'no package provides' || true
diff --git a/cdist/conf/type/__package_zypper/gencode-remote b/cdist/conf/type/__package_zypper/gencode-remote
old mode 100755
new mode 100644
index ca9aec33..d1766126
--- a/cdist/conf/type/__package_zypper/gencode-remote
+++ b/cdist/conf/type/__package_zypper/gencode-remote
@@ -39,15 +39,22 @@ else
    state_should="present"
 fi
 
+pkg_version="$(cat "$__object/explorer/pkg_version")"
+if [ -z "$pkg_version" ]; then
+    state_is="absent"
+else
+    state_is="present"
+fi
+
 # Exit if nothing is needed to be done
 [ "$state_is" = "$state_should" ] && exit 0
 
 case "$state_should" in
    present)
-         echo zypper "$globalopts" install --auto-agree-with-licenses \"$name\"
+         echo zypper $globalopts install --auto-agree-with-licenses \"$name\" ">/dev/null"
    ;;
    absent)
-         echo pacman "$globalopts" remove \"$name\"
+         echo zypper $globalopts remove \"$name\" ">/dev/null"
    ;;
    *)
       echo "Unknown state: $state_should" >&2
diff --git a/cdist/config.py b/cdist/config.py
index 7e003835..3f8a7fc6 100644
--- a/cdist/config.py
+++ b/cdist/config.py
@@ -249,7 +249,7 @@ class Config(object):
         cdist_type = cdist_object.cdist_type
 
         # Generate
-        self.log.info("Generating and executing code for %s" % (cdist_object.name))
+        self.log.info("Generating code for %s" % (cdist_object.name))
         cdist_object.code_local = self.code.run_gencode_local(cdist_object)
         cdist_object.code_remote = self.code.run_gencode_remote(cdist_object)
         if cdist_object.code_local or cdist_object.code_remote:
@@ -257,6 +257,8 @@ class Config(object):
 
         # Execute
         if not self.dry_run:
+            if cdist_object.code_local or cdist_object.code_remote:
+                self.log.info("Executing code for %s" % (cdist_object.name))
             if cdist_object.code_local:
                 self.code.run_code_local(cdist_object)
             if cdist_object.code_remote:
diff --git a/cdist/exec/local.py b/cdist/exec/local.py
index f1313eea..72c7e70f 100644
--- a/cdist/exec/local.py
+++ b/cdist/exec/local.py
@@ -196,8 +196,13 @@ class Local(object):
     def save_cache(self):
         destination = os.path.join(self.cache_path, self.target_host)
         self.log.debug("Saving " + self.base_path + " to " + destination)
-        if os.path.exists(destination):
-            shutil.rmtree(destination)
+
+        try:
+            if os.path.exists(destination):
+                shutil.rmtree(destination)
+        except PermissionError as e:
+            raise cdist.Error("Cannot delete old cache %s: %s" % (destination, e))
+
         shutil.move(self.base_path, destination)
 
     def _create_messages(self):
diff --git a/doc/dev/logs/2012-05-24.preos b/doc/dev/logs/2012-05-24.preos
new file mode 100644
index 00000000..e4f988a7
--- /dev/null
+++ b/doc/dev/logs/2012-05-24.preos
@@ -0,0 +1,72 @@
+Todo for preos:
+
+get debian installer (?)
+    x86, amd64
+configure sshd
+    add authorized_keys
+output files
+    tftp: cuni:    curl -s "http://http.us.debian.org/debian/dists/$version/main/installer-$arch/current/images/netboot/netboot.tar.gz" | tar xz
+    iso
+
+
+http://wiki.debian.org/DebianInstaller/
+--------------------------------------------------------------------------------
+debootstrap:
+    [19:33] brief:hack% sudo debootstrap squeeze ./debian-squeeze
+    [19:30] brief:hack# du -sh .
+    213M    .
+
+install kernel
+    [19:35] brief:hack# chroot debian-squeeze/ apt-get -y install linux-image-amd64 
+    [19:37] brief:debian-squeeze# ls boot/initrd*                   
+    boot/initrd.img-2.6.32-5-amd64
+    [19:37] brief:debian-squeeze# ls boot/vmlinuz*
+    boot/vmlinuz-2.6.32-5-amd64
+
+install sshd
+    [19:37] brief:hack# chroot debian-squeeze/ apt-get -y --force-yes install openssh-server 
+
+    - connect back?
+    - generate sshd keys?
+
+--------------------------------------------------------------------------------
+initramfs:
+       find . -print0 | bsdcpio $( (( QUIET )) && echo '--quiet' ) -R 0:0 -0oH newc | $COMPRESSION $COMPRESSION_OPTIONS > "$IMGPATH"
+
+    /init for booting
+    find . -print0 | cpio --null -ov --format=newc | gzip -9 > /boot/my-initramfs.cpio.gz
+    cpio -H newc -o
+    find . | cpio -H newc -o > ../initramfs.cpio # <-- this is the actual initramfs
+
+
+[19:39] brief:debian-squeeze# find . | bsdcpio -H newc -o > ../initramfs.cpio 
+[19:43] brief:debian-squeeze# xz ../initramfs.cpio
+
+
+--------------------------------------------------------------------------------
+cdrom:
+    http://tldp.org/HOWTO/Bootdisk-HOWTO/cd-roms.html
+
+--------------------------------------------------------------------------------
+
+[19:34] brief:hack# chroot debian-squeeze/ apt-cache search kernel | grep linux-image
+linux-image-2.6.32-5-amd64-dbg - Debugging infos for Linux 2.6.32-5-amd64
+linux-image-2.6.32-5-amd64 - Linux 2.6.32 for 64-bit PCs
+linux-image-2.6.32-5-openvz-amd64-dbg - Debugging infos for Linux 2.6.32-5-openvz-amd64
+linux-image-2.6.32-5-openvz-amd64 - Linux 2.6.32 for 64-bit PCs, OpenVZ support
+linux-image-2.6.32-5-vserver-amd64-dbg - Debugging infos for Linux 2.6.32-5-vserver-amd64
+linux-image-2.6.32-5-vserver-amd64 - Linux 2.6.32 for 64-bit PCs, Linux-VServer support
+linux-image-2.6.32-5-xen-amd64-dbg - Debugging infos for Linux 2.6.32-5-xen-amd64
+linux-image-2.6.32-5-xen-amd64 - Linux 2.6.32 for 64-bit PCs, Xen dom0 support
+linux-image-2.6-amd64 - Linux 2.6 for 64-bit PCs (meta-package)
+linux-image-2.6-openvz-amd64 - Linux 2.6 for 64-bit PCs (meta-package), OpenVZ support
+linux-image-2.6-vserver-amd64 - Linux 2.6 for 64-bit PCs (meta-package), Linux-VServer support
+linux-image-2.6-xen-amd64 - Linux 2.6 for 64-bit PCs (meta-package), Xen dom0 support
+linux-image-amd64 - Linux for 64-bit PCs (meta-package)
+linux-image-openvz-amd64 - Linux for 64-bit PCs (meta-package), OpenVZ support
+linux-image-vserver-amd64 - Linux for 64-bit PCs (meta-package), Linux-VServer support
+linux-image-xen-amd64 - Linux for 64-bit PCs (meta-package), Xen dom0 support
+[19:34] brief:hack# 
+
+--------------------------------------------------------------------------------
+
diff --git a/docs/changelog b/docs/changelog
index e7d90609..b6122bec 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -4,6 +4,14 @@ Changelog
 	* Changes are always commented with their author in (braces)
 	* Exception: No braces means author == Nico Schottelius
 
+2.3.7: 2013-12-02
+	* Type __file: Secure the file transfer by using mktemp (Steven Armstrong)
+	* Type __file: Only remove file when state is absent (Steven Armstrong)
+	* Type __link: Only remove link when state is absent (Steven Armstrong)
+	* Type __directory: Only remove directory when state is absent (Steven Armstrong)
+	* Type __package_zypper: Fix explorer and parameter issue (Daniel Heule)
+	* Core: Fix backtrace when cache cannot be deleted
+
 2.3.6: 2013-11-25
 	* New Type: __locale
 	* Type __line: Ensure special characters are not interpreted