|
@@ -209,3 +209,37 @@ xfs_symlink_local_to_remote(
|
|
|
xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
|
|
|
ifp->if_bytes - 1);
|
|
|
}
|
|
|
+
|
|
|
+/* Verify the consistency of an inline symlink. */
|
|
|
+xfs_failaddr_t
|
|
|
+xfs_symlink_shortform_verify(
|
|
|
+ struct xfs_inode *ip)
|
|
|
+{
|
|
|
+ char *sfp;
|
|
|
+ char *endp;
|
|
|
+ struct xfs_ifork *ifp;
|
|
|
+ int size;
|
|
|
+
|
|
|
+ ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
|
|
|
+ ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
|
|
|
+ sfp = (char *)ifp->if_u1.if_data;
|
|
|
+ size = ifp->if_bytes;
|
|
|
+ endp = sfp + size;
|
|
|
+
|
|
|
+ /* Zero length symlinks can exist while we're deleting a remote one. */
|
|
|
+ if (size == 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ /* No negative sizes or overly long symlink targets. */
|
|
|
+ if (size < 0 || size > XFS_SYMLINK_MAXLEN)
|
|
|
+ return __this_address;
|
|
|
+
|
|
|
+ /* No NULLs in the target either. */
|
|
|
+ if (memchr(sfp, 0, size - 1))
|
|
|
+ return __this_address;
|
|
|
+
|
|
|
+ /* We /did/ null-terminate the buffer, right? */
|
|
|
+ if (*endp != 0)
|
|
|
+ return __this_address;
|
|
|
+ return NULL;
|
|
|
+}
|