15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
2212508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw */
245331Samw
255331Samw #include <sys/types.h>
268934SJose.Borrego@Sun.COM #include <sys/param.h>
275331Samw #include <sys/sunddi.h>
285331Samw #include <sys/errno.h>
295331Samw #include <smbsrv/string.h>
305331Samw #include <smbsrv/smb_vops.h>
3110966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
325331Samw #include <smbsrv/smb_fsops.h>
335331Samw
348934SJose.Borrego@Sun.COM /*
358934SJose.Borrego@Sun.COM * Characters we don't allow in DOS file names.
368934SJose.Borrego@Sun.COM * If a filename contains any of these chars, it should get mangled.
378934SJose.Borrego@Sun.COM *
388934SJose.Borrego@Sun.COM * '.' is also an invalid DOS char but since it's a special
398934SJose.Borrego@Sun.COM * case it doesn't appear in the list.
408934SJose.Borrego@Sun.COM */
418934SJose.Borrego@Sun.COM static char *invalid_dos_chars =
428934SJose.Borrego@Sun.COM "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
438934SJose.Borrego@Sun.COM "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
448934SJose.Borrego@Sun.COM " \"/\\:|<>*?";
458934SJose.Borrego@Sun.COM
468934SJose.Borrego@Sun.COM /*
478934SJose.Borrego@Sun.COM * According to MSKB article #142982, Windows deletes invalid chars and
488934SJose.Borrego@Sun.COM * spaces from file name in mangling process; and invalid chars include:
498934SJose.Borrego@Sun.COM * ."/\[]:;=,
508934SJose.Borrego@Sun.COM *
518934SJose.Borrego@Sun.COM * But some of these chars and some other chars (e.g. +) are replaced
528934SJose.Borrego@Sun.COM * with underscore (_). They are introduced here as special chars.
538934SJose.Borrego@Sun.COM */
548934SJose.Borrego@Sun.COM static char *special_chars = "[];=,+";
558934SJose.Borrego@Sun.COM
568934SJose.Borrego@Sun.COM #define isinvalid(c) (strchr(invalid_dos_chars, c) || (c & 0x80))
578934SJose.Borrego@Sun.COM
5812508Samw@Sun.COM static int smb_generate_mangle(uint64_t, char *, size_t);
5912508Samw@Sun.COM static char smb_mangle_char(char);
605331Samw
615331Samw /*
628934SJose.Borrego@Sun.COM * Return true if name contains characters that are invalid in a file
638934SJose.Borrego@Sun.COM * name or it is a reserved DOS device name. Otherwise, returns false.
645331Samw *
658934SJose.Borrego@Sun.COM * Control characters (values 0 - 31) and the following characters are
668934SJose.Borrego@Sun.COM * invalid:
678934SJose.Borrego@Sun.COM * < > : " / \ | ? *
685331Samw */
698934SJose.Borrego@Sun.COM boolean_t
smb_is_invalid_filename(const char * name)708934SJose.Borrego@Sun.COM smb_is_invalid_filename(const char *name)
715331Samw {
728934SJose.Borrego@Sun.COM const char *p;
735331Samw
748934SJose.Borrego@Sun.COM if ((p = strpbrk(name, invalid_dos_chars)) != NULL) {
758934SJose.Borrego@Sun.COM if (*p != ' ')
768934SJose.Borrego@Sun.COM return (B_TRUE);
778934SJose.Borrego@Sun.COM }
788934SJose.Borrego@Sun.COM
798934SJose.Borrego@Sun.COM return (smb_is_reserved_dos_name(name));
805331Samw }
815331Samw
825331Samw /*
835331Samw * smb_is_reserved_dos_name
845331Samw *
858934SJose.Borrego@Sun.COM * This function checks if the name is a reserved DOS device name.
868934SJose.Borrego@Sun.COM * The device name should not be followed immediately by an extension,
878934SJose.Borrego@Sun.COM * for example, NUL.txt.
885331Samw */
89*12890SJoyce.McIntosh@Sun.COM boolean_t
smb_is_reserved_dos_name(const char * name)908934SJose.Borrego@Sun.COM smb_is_reserved_dos_name(const char *name)
915331Samw {
928934SJose.Borrego@Sun.COM static char *cnames[] = { "CLOCK$", "COM1", "COM2", "COM3", "COM4",
938934SJose.Borrego@Sun.COM "COM5", "COM6", "COM7", "COM8", "COM9", "CON" };
948934SJose.Borrego@Sun.COM static char *lnames[] = { "LPT1", "LPT2", "LPT3", "LPT4", "LPT5",
958934SJose.Borrego@Sun.COM "LPT6", "LPT7", "LPT8", "LPT9" };
968934SJose.Borrego@Sun.COM static char *others[] = { "AUX", "NUL", "PRN" };
978934SJose.Borrego@Sun.COM char **reserved;
985331Samw char ch;
998934SJose.Borrego@Sun.COM int n_reserved;
1008934SJose.Borrego@Sun.COM int len;
1018934SJose.Borrego@Sun.COM int i;
1025331Samw
10310966SJordan.Brown@Sun.COM ch = smb_toupper(*name);
1045331Samw
1055331Samw switch (ch) {
1065331Samw case 'A':
1078934SJose.Borrego@Sun.COM case 'N':
1088934SJose.Borrego@Sun.COM case 'P':
1098934SJose.Borrego@Sun.COM reserved = others;
1108934SJose.Borrego@Sun.COM n_reserved = sizeof (others) / sizeof (others[0]);
1115331Samw break;
1128934SJose.Borrego@Sun.COM case 'C':
1138934SJose.Borrego@Sun.COM reserved = cnames;
1148934SJose.Borrego@Sun.COM n_reserved = sizeof (cnames) / sizeof (cnames[0]);
1155331Samw break;
1168934SJose.Borrego@Sun.COM case 'L':
1178934SJose.Borrego@Sun.COM reserved = lnames;
1188934SJose.Borrego@Sun.COM n_reserved = sizeof (lnames) / sizeof (lnames[0]);
1195331Samw break;
1208934SJose.Borrego@Sun.COM default:
1218934SJose.Borrego@Sun.COM return (B_FALSE);
1225331Samw }
1235331Samw
1248934SJose.Borrego@Sun.COM for (i = 0; i < n_reserved; ++i) {
1258934SJose.Borrego@Sun.COM len = strlen(reserved[i]);
1268934SJose.Borrego@Sun.COM
12710966SJordan.Brown@Sun.COM if (smb_strcasecmp(reserved[i], name, len) == 0) {
1288934SJose.Borrego@Sun.COM ch = *(name + len);
1298934SJose.Borrego@Sun.COM if ((ch == '\0') || (ch == '.'))
1308934SJose.Borrego@Sun.COM return (B_TRUE);
1315331Samw }
1325331Samw }
1335331Samw
1348934SJose.Borrego@Sun.COM return (B_FALSE);
1355331Samw }
1365331Samw
1375331Samw /*
13812508Samw@Sun.COM * smb_needs_mangled
1395331Samw *
14012508Samw@Sun.COM * A name needs to be mangled if any of the following are true:
14112508Samw@Sun.COM * - the first character is dot (.) and the name is not "." or ".."
14212508Samw@Sun.COM * - the name contains illegal or special charsacter
14312508Samw@Sun.COM * - the name name length > 12
14412508Samw@Sun.COM * - the number of dots == 0 and length > 8
14512508Samw@Sun.COM * - the number of dots > 1
14612508Samw@Sun.COM * - the number of dots == 1 and name is not 8.3
1475331Samw */
14812508Samw@Sun.COM boolean_t
smb_needs_mangled(const char * name)14912508Samw@Sun.COM smb_needs_mangled(const char *name)
1505331Samw {
15112508Samw@Sun.COM int len, extlen, ndots;
15212508Samw@Sun.COM const char *p;
15312508Samw@Sun.COM const char *last_dot;
1545331Samw
15512508Samw@Sun.COM if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
15612508Samw@Sun.COM return (B_FALSE);
1575331Samw
1585331Samw if (*name == '.')
15912508Samw@Sun.COM return (B_TRUE);
1605331Samw
16112508Samw@Sun.COM len = 0;
16212508Samw@Sun.COM ndots = 0;
16312508Samw@Sun.COM last_dot = NULL;
16412508Samw@Sun.COM for (p = name; *p != '\0'; ++p) {
16512508Samw@Sun.COM if (smb_iscntrl(*p) ||
16612508Samw@Sun.COM (strchr(special_chars, *p) != NULL) ||
16712508Samw@Sun.COM (strchr(invalid_dos_chars, *p)) != NULL)
16812508Samw@Sun.COM return (B_TRUE);
1695331Samw
17012508Samw@Sun.COM if (*p == '.') {
17112508Samw@Sun.COM ++ndots;
17212508Samw@Sun.COM last_dot = p;
17312508Samw@Sun.COM }
17412508Samw@Sun.COM ++len;
1755331Samw }
1765331Samw
17712508Samw@Sun.COM if ((len > SMB_NAME83_LEN) ||
17812508Samw@Sun.COM (ndots == 0 && len > SMB_NAME83_BASELEN) ||
17912508Samw@Sun.COM (ndots > 1)) {
18012508Samw@Sun.COM return (B_TRUE);
1815331Samw }
1825331Samw
18312508Samw@Sun.COM if (last_dot != NULL) {
18412508Samw@Sun.COM extlen = strlen(last_dot + 1);
18512508Samw@Sun.COM if ((extlen == 0) || (extlen > SMB_NAME83_EXTLEN))
18612508Samw@Sun.COM return (B_TRUE);
1875331Samw
18812508Samw@Sun.COM if ((len - extlen - 1) > SMB_NAME83_BASELEN)
18912508Samw@Sun.COM return (B_TRUE);
1905331Samw }
1915331Samw
19212508Samw@Sun.COM return (B_FALSE);
1935331Samw }
1945331Samw
1955331Samw /*
1965331Samw * smb_mangle_char
1975331Samw *
19812508Samw@Sun.COM * If c is an invalid DOS character or non-ascii, it should
19912508Samw@Sun.COM * not be used in the mangled name. We return -1 to indicate
20012508Samw@Sun.COM * an invalid character.
2015331Samw *
20212508Samw@Sun.COM * If c is a special chars, it should be replaced with '_'.
2035331Samw *
20412508Samw@Sun.COM * Otherwise c is returned as uppercase.
2055331Samw */
20612508Samw@Sun.COM static char
smb_mangle_char(char c)20712508Samw@Sun.COM smb_mangle_char(char c)
2085331Samw {
20912508Samw@Sun.COM if (isinvalid(c))
21012508Samw@Sun.COM return (-1);
2115331Samw
21212508Samw@Sun.COM if (strchr(special_chars, c))
2135331Samw return ('_');
2145331Samw
21512508Samw@Sun.COM return (smb_toupper(c));
2165331Samw }
2175331Samw
2185331Samw /*
2195331Samw * smb_generate_mangle
2205331Samw *
22112508Samw@Sun.COM * Generate a mangle string containing at least 2 characters and
22212508Samw@Sun.COM * at most (buflen - 1) characters.
2235331Samw *
2245331Samw * Returns the number of chars in the generated mangle.
2255331Samw */
2265331Samw static int
smb_generate_mangle(uint64_t fid,char * buf,size_t buflen)22712508Samw@Sun.COM smb_generate_mangle(uint64_t fid, char *buf, size_t buflen)
2285331Samw {
2295331Samw static char *base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
23012508Samw@Sun.COM char *p = buf;
2319437SJoyce.McIntosh@Sun.COM int i;
2329437SJoyce.McIntosh@Sun.COM
2339437SJoyce.McIntosh@Sun.COM if (fid == 0)
2349437SJoyce.McIntosh@Sun.COM fid = (uint64_t)-1;
2355331Samw
2369437SJoyce.McIntosh@Sun.COM *p++ = '~';
2379437SJoyce.McIntosh@Sun.COM for (i = 2; (i < buflen) && (fid > 0); fid /= 36, ++i)
2389437SJoyce.McIntosh@Sun.COM *p++ = base36[fid % 36];
2399437SJoyce.McIntosh@Sun.COM *p = '\0';
2405331Samw
2419437SJoyce.McIntosh@Sun.COM return (i - 1);
2425331Samw }
2435331Samw
2445331Samw /*
24512508Samw@Sun.COM * smb_maybe_mangled
2465331Samw *
2478934SJose.Borrego@Sun.COM * Mangled names should be valid DOS file names: less than 12 characters
2488934SJose.Borrego@Sun.COM * long, contain at least one tilde character and conform to an 8.3 name
2498934SJose.Borrego@Sun.COM * format.
2505331Samw *
2518934SJose.Borrego@Sun.COM * Returns true if the name looks like a mangled name.
2525331Samw */
25312508Samw@Sun.COM boolean_t
smb_maybe_mangled(char * name)25412508Samw@Sun.COM smb_maybe_mangled(char *name)
2555331Samw {
2568934SJose.Borrego@Sun.COM const char *p;
2578934SJose.Borrego@Sun.COM boolean_t has_tilde = B_FALSE;
2588934SJose.Borrego@Sun.COM int ndots = 0;
2598934SJose.Borrego@Sun.COM int i;
2608934SJose.Borrego@Sun.COM
2618934SJose.Borrego@Sun.COM for (p = name, i = 0; (*p != '\0') && (i < SMB_NAME83_LEN); i++, p++) {
2628934SJose.Borrego@Sun.COM if ((strchr(special_chars, *p) != NULL) ||
2638934SJose.Borrego@Sun.COM (strchr(invalid_dos_chars, *p) != NULL))
2648934SJose.Borrego@Sun.COM return (B_FALSE);
2655331Samw
2668934SJose.Borrego@Sun.COM if (*p == '.') {
2678934SJose.Borrego@Sun.COM if ((++ndots) > 1)
2688934SJose.Borrego@Sun.COM return (B_FALSE);
2698934SJose.Borrego@Sun.COM }
2705331Samw
2718934SJose.Borrego@Sun.COM if ((*p == '~') && (i < SMB_NAME83_BASELEN))
2728934SJose.Borrego@Sun.COM has_tilde = B_TRUE;
2738934SJose.Borrego@Sun.COM
2748934SJose.Borrego@Sun.COM if (*p == '.' && !has_tilde)
2758934SJose.Borrego@Sun.COM return (B_FALSE);
2765331Samw }
2775331Samw
27812508Samw@Sun.COM return ((*p == '\0') && has_tilde);
2795331Samw }
2805331Samw
2815331Samw /*
28212508Samw@Sun.COM * smb_mangle
2835331Samw *
2845331Samw * Microsoft knowledge base article #142982 describes how Windows
2855331Samw * generates 8.3 filenames from long file names. Some other details
2865331Samw * can be found in article #114816.
2875331Samw *
28812508Samw@Sun.COM * This function will mangle the name whether mangling is required
28912508Samw@Sun.COM * or not. Callers should use smb_needs_mangled() to determine whether
29012508Samw@Sun.COM * mangling is required.
2915331Samw *
29212508Samw@Sun.COM * name original file name
29312508Samw@Sun.COM * fid inode number to generate unique mangle
29412508Samw@Sun.COM * buf output buffer (buflen bytes) to contain mangled name
2955331Samw */
29612508Samw@Sun.COM void
smb_mangle(const char * name,ino64_t fid,char * buf,size_t buflen)29712508Samw@Sun.COM smb_mangle(const char *name, ino64_t fid, char *buf, size_t buflen)
29812508Samw@Sun.COM {
29912508Samw@Sun.COM int i, avail;
30012508Samw@Sun.COM const char *p;
30112508Samw@Sun.COM char c;
30212508Samw@Sun.COM char *pbuf;
30312508Samw@Sun.COM char mangle_buf[SMB_NAME83_BASELEN];
3045331Samw
30512508Samw@Sun.COM ASSERT(name && buf && (buflen >= SMB_SHORTNAMELEN));
30612508Samw@Sun.COM
30712508Samw@Sun.COM avail = SMB_NAME83_BASELEN -
30812508Samw@Sun.COM smb_generate_mangle(fid, mangle_buf, SMB_NAME83_BASELEN);
30912508Samw@Sun.COM name += strspn(name, ".");
3105331Samw
3115331Samw /*
31212508Samw@Sun.COM * Copy up to avail characters from the base part of name
31312508Samw@Sun.COM * to buf then append the generated mangle string.
3145331Samw */
31512508Samw@Sun.COM p = name;
31612508Samw@Sun.COM pbuf = buf;
31712508Samw@Sun.COM for (i = 0; (i < avail) && (*p != '\0') && (*p != '.'); ++i, ++p) {
31812508Samw@Sun.COM if ((c = smb_mangle_char(*p)) == -1)
31912508Samw@Sun.COM continue;
32012508Samw@Sun.COM *pbuf++ = c;
3215331Samw }
32212508Samw@Sun.COM *pbuf = '\0';
32312508Samw@Sun.COM (void) strlcat(pbuf, mangle_buf, SMB_NAME83_BASELEN);
32412508Samw@Sun.COM pbuf = strchr(pbuf, '\0');
3255331Samw
3265331Samw /*
32712508Samw@Sun.COM * Find the last dot in the name. If there is a dot and an
32812508Samw@Sun.COM * extension, append '.' and up to SMB_NAME83_EXTLEN extension
32912508Samw@Sun.COM * characters to the mangled name.
3305331Samw */
33112508Samw@Sun.COM if (((p = strrchr(name, '.')) != NULL) && (*(++p) != '\0')) {
33212508Samw@Sun.COM *pbuf++ = '.';
33312508Samw@Sun.COM for (i = 0; (i < SMB_NAME83_EXTLEN) && (*p != '\0'); ++i, ++p) {
33412508Samw@Sun.COM if ((c = smb_mangle_char(*p)) == -1)
33512508Samw@Sun.COM continue;
33612508Samw@Sun.COM *pbuf++ = c;
3375331Samw }
3385331Samw }
3395331Samw
34012508Samw@Sun.COM *pbuf = '\0';
3415331Samw }
3425331Samw
3435331Samw /*
34412508Samw@Sun.COM * smb_unmangle
3455331Samw *
3465331Samw * Given a mangled name, try to find the real file name as it appears
3479231SAfshin.Ardakani@Sun.COM * in the directory entry.
3489231SAfshin.Ardakani@Sun.COM *
34912508Samw@Sun.COM * smb_unmangle should only be called on names for which
35012508Samw@Sun.COM * smb_maybe_mangled() is true
3519231SAfshin.Ardakani@Sun.COM *
3529231SAfshin.Ardakani@Sun.COM * File systems which support VFSFT_EDIRENT_FLAGS will return the
3539231SAfshin.Ardakani@Sun.COM * directory entries as a buffer of edirent_t structure. Others will
3549231SAfshin.Ardakani@Sun.COM * return a buffer of dirent64_t structures. A union is used for the
3559231SAfshin.Ardakani@Sun.COM * the pointer into the buffer (bufptr, edp and dp).
3569231SAfshin.Ardakani@Sun.COM * The ed_name/d_name is NULL terminated by the file system.
3575331Samw *
3589231SAfshin.Ardakani@Sun.COM * Returns:
3599231SAfshin.Ardakani@Sun.COM * 0 - SUCCESS. Unmangled name is returned in namebuf.
3609231SAfshin.Ardakani@Sun.COM * EINVAL - a parameter was invalid.
3619231SAfshin.Ardakani@Sun.COM * ENOTDIR - dnode is not a directory node.
3629231SAfshin.Ardakani@Sun.COM * ENOENT - an unmangled name could not be found.
3635331Samw */
3649231SAfshin.Ardakani@Sun.COM #define SMB_UNMANGLE_BUFSIZE (4 * 1024)
3659231SAfshin.Ardakani@Sun.COM int
smb_unmangle(smb_node_t * dnode,char * name,char * namebuf,int buflen,uint32_t flags)36612508Samw@Sun.COM smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
36710504SKeyur.Desai@Sun.COM int buflen, uint32_t flags)
3689231SAfshin.Ardakani@Sun.COM {
3699231SAfshin.Ardakani@Sun.COM int err, eof, bufsize, reclen;
3709231SAfshin.Ardakani@Sun.COM uint64_t offset;
3719231SAfshin.Ardakani@Sun.COM ino64_t ino;
3729231SAfshin.Ardakani@Sun.COM boolean_t is_edp;
3739231SAfshin.Ardakani@Sun.COM char *namep, *buf;
3749231SAfshin.Ardakani@Sun.COM char shortname[SMB_SHORTNAMELEN];
3759231SAfshin.Ardakani@Sun.COM vnode_t *vp;
3769231SAfshin.Ardakani@Sun.COM union {
3779231SAfshin.Ardakani@Sun.COM char *bufptr;
3789231SAfshin.Ardakani@Sun.COM edirent_t *edp;
3799231SAfshin.Ardakani@Sun.COM dirent64_t *dp;
3809231SAfshin.Ardakani@Sun.COM } u;
3819231SAfshin.Ardakani@Sun.COM #define bufptr u.bufptr
3829231SAfshin.Ardakani@Sun.COM #define edp u.edp
3839231SAfshin.Ardakani@Sun.COM #define dp u.dp
3845331Samw
3859231SAfshin.Ardakani@Sun.COM if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
3865331Samw return (EINVAL);
3875331Samw
38812508Samw@Sun.COM ASSERT(smb_maybe_mangled(name) == B_TRUE);
3899231SAfshin.Ardakani@Sun.COM
39011963SAfshin.Ardakani@Sun.COM if (!smb_node_is_dir(dnode))
3919231SAfshin.Ardakani@Sun.COM return (ENOTDIR);
3929231SAfshin.Ardakani@Sun.COM
39311963SAfshin.Ardakani@Sun.COM vp = dnode->vp;
3949231SAfshin.Ardakani@Sun.COM *namebuf = '\0';
3959231SAfshin.Ardakani@Sun.COM is_edp = vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS);
3965331Samw
3979231SAfshin.Ardakani@Sun.COM buf = kmem_alloc(SMB_UNMANGLE_BUFSIZE, KM_SLEEP);
3989231SAfshin.Ardakani@Sun.COM bufsize = SMB_UNMANGLE_BUFSIZE;
3999231SAfshin.Ardakani@Sun.COM offset = 0;
4009231SAfshin.Ardakani@Sun.COM
4019231SAfshin.Ardakani@Sun.COM while ((err = smb_vop_readdir(vp, offset, buf, &bufsize,
40210504SKeyur.Desai@Sun.COM &eof, flags, kcred)) == 0) {
4039231SAfshin.Ardakani@Sun.COM if (bufsize == 0) {
4049231SAfshin.Ardakani@Sun.COM err = ENOENT;
4059231SAfshin.Ardakani@Sun.COM break;
4065331Samw }
4075331Samw
4089231SAfshin.Ardakani@Sun.COM bufptr = buf;
4099231SAfshin.Ardakani@Sun.COM reclen = 0;
4109231SAfshin.Ardakani@Sun.COM
4119231SAfshin.Ardakani@Sun.COM while ((bufptr += reclen) < buf + bufsize) {
4129231SAfshin.Ardakani@Sun.COM if (is_edp) {
4139231SAfshin.Ardakani@Sun.COM reclen = edp->ed_reclen;
4149231SAfshin.Ardakani@Sun.COM offset = edp->ed_off;
4159231SAfshin.Ardakani@Sun.COM ino = edp->ed_ino;
4169231SAfshin.Ardakani@Sun.COM namep = edp->ed_name;
4179231SAfshin.Ardakani@Sun.COM } else {
4189231SAfshin.Ardakani@Sun.COM reclen = dp->d_reclen;
4199231SAfshin.Ardakani@Sun.COM offset = dp->d_off;
4209231SAfshin.Ardakani@Sun.COM ino = dp->d_ino;
4219231SAfshin.Ardakani@Sun.COM namep = dp->d_name;
4229231SAfshin.Ardakani@Sun.COM }
4235331Samw
42410966SJordan.Brown@Sun.COM /* skip non utf8 filename */
42510966SJordan.Brown@Sun.COM if (u8_validate(namep, strlen(namep), NULL,
42610966SJordan.Brown@Sun.COM U8_VALIDATE_ENTIRE, &err) < 0)
42710966SJordan.Brown@Sun.COM continue;
42810966SJordan.Brown@Sun.COM
42912508Samw@Sun.COM smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
4305331Samw
43110966SJordan.Brown@Sun.COM if (smb_strcasecmp(name, shortname, 0) == 0) {
4329231SAfshin.Ardakani@Sun.COM (void) strlcpy(namebuf, namep, buflen);
4339231SAfshin.Ardakani@Sun.COM kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
4349231SAfshin.Ardakani@Sun.COM return (0);
4359231SAfshin.Ardakani@Sun.COM }
4369231SAfshin.Ardakani@Sun.COM }
4379231SAfshin.Ardakani@Sun.COM
4389231SAfshin.Ardakani@Sun.COM if (eof) {
4399231SAfshin.Ardakani@Sun.COM err = ENOENT;
4409231SAfshin.Ardakani@Sun.COM break;
4419231SAfshin.Ardakani@Sun.COM }
4429231SAfshin.Ardakani@Sun.COM
4439231SAfshin.Ardakani@Sun.COM bufsize = SMB_UNMANGLE_BUFSIZE;
4445331Samw }
4455331Samw
4469231SAfshin.Ardakani@Sun.COM kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
4479231SAfshin.Ardakani@Sun.COM return (err);
4485331Samw }
449