Merge "Run lstat on correct path. Do not follow symlinks."
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index abc1fa0..6c324f2 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -40,21 +40,27 @@
   std::vector<std::string> queue{root_directory};
   while (!queue.empty()) {
     struct dirent* entry;
-    std::string filepath = queue.back();
+    std::string directory = queue.back();
     queue.pop_back();
-    DIR* dir = opendir(filepath.c_str());
-    filepath += "/";
+    DIR* dir = opendir(directory.c_str());
+    directory += "/";
     if (dir == nullptr)
       continue;
     while ((entry = readdir(dir)) != nullptr) {
       std::string filename = entry->d_name;
       if (filename == "." || filename == "..")
         continue;
+      std::string filepath = directory + filename;
 
       struct stat buf;
       if (lstat(filepath.c_str(), &buf) != 0)
         continue;
 
+      // This might happen on filesystems that do not return
+      // information in entry->d_type.
+      if (S_ISLNK(buf.st_mode))
+        continue;
+
       Inode inode_number = entry->d_ino;
       BlockDeviceID block_device_id = buf.st_dev;
 
@@ -63,13 +69,13 @@
       // Readdir and stat not guaranteed to have directory info for all systems
       if (entry->d_type == DT_DIR || S_ISDIR(buf.st_mode)) {
         // Continue iterating through files if current entry is a directory
-        queue.push_back(filepath + filename);
+        queue.push_back(filepath);
         type = protos::pbzero::InodeFileMap_Entry_Type_DIRECTORY;
       } else if (entry->d_type == DT_REG || S_ISREG(buf.st_mode)) {
         type = protos::pbzero::InodeFileMap_Entry_Type_FILE;
       }
 
-      fn(block_device_id, inode_number, filepath + filename, type);
+      fn(block_device_id, inode_number, filepath, type);
     }
     closedir(dir);
   }