+/* Type check. The correct error return for type mismatches does not seem to be
+ * generally agreed upon. SunOS seems to use EISDIR if file isn't S_IFREG; a
+ * comment in the NFSv3 spec says this is incorrect (implementation notes for
+ * the write call).
+ */
+static inline int
+nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
+{
+ /* Type can be negative when creating hardlinks - not to a dir */
+ if (type > 0 && (mode & S_IFMT) != type) {
+ if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
+ return nfserr_symlink;
+ else if (type == S_IFDIR)
+ return nfserr_notdir;
+ else if ((mode & S_IFMT) == S_IFDIR)
+ return nfserr_isdir;
+ else
+ return nfserr_inval;
+ }
+ if (type < 0 && (mode & S_IFMT) == -type) {
+ if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
+ return nfserr_symlink;
+ else if (type == -S_IFDIR)
+ return nfserr_isdir;
+ else
+ return nfserr_notdir;
+ }
+ return 0;
+}