1/*
2 * Copyright (c) 2011  Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <sys/smb_apple.h>
25
26#include <netsmb/smb.h>
27#include <netsmb/smb_2.h>
28#include <netsmb/smb_conn.h>
29#include <netsmb/smb_rq.h>
30#include <smbfs/smbfs_node.h>
31#include <smbfs/smbfs_subr_2.h>
32#include <smbfs/smbfs.h>
33
34
35void
36smb2fs_smb_file_id_check(struct smb_share *share, uint64_t ino,
37                         char *network_name, uint32_t network_name_len)
38{
39    uint32_t no_file_ids = 0;
40
41    /*
42     * Check to see if server supports File IDs or not
43     * Watch out because the ".." in every Query Dir response has File ID of 0
44     * which is supposed to be illegal. Sigh.
45     */
46    if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) {
47        if (ino == 0) {
48            no_file_ids = 1;
49
50            if ((network_name != NULL) && (network_name_len > 0)) {
51                if ((network_name_len == 2 &&
52                     letohs(*(uint16_t * ) network_name) == 0x002e) ||
53                    (network_name_len == 4 &&
54                     letohl(*(uint32_t *) network_name) == 0x002e002e)) {
55                        /*
56                         * Its the ".." dir so allow the File ID of 0. "." and ".."
57                         * dirs are ignored by smbfs_findnext so we can safely leave
58                         * their fa_ino to be 0
59                         */
60                        no_file_ids = 0;
61                    }
62            }
63        }
64    }
65
66    if (no_file_ids == 1) {
67        SMBDEBUG("Server does not support File IDs \n");
68        SSTOVC(share)->vc_misc_flags &= ~SMBV_HAS_FILEIDS;
69    }
70}
71
72uint64_t
73smb2fs_smb_file_id_get(struct smbmount *smp, uint64_t ino, char *name)
74{
75    uint64_t ret_ino;
76
77    if (ino == smp->sm_root_ino) {
78        /* If its the root File ID, then return SMBFS_ROOT_INO */
79        ret_ino = SMBFS_ROOT_INO;
80    }
81    else {
82        /*
83         * If actual File ID is SMBFS_ROOT_INO, then return the root File ID
84         * instead.
85         */
86        if (ino == SMBFS_ROOT_INO) {
87            ret_ino = smp->sm_root_ino;
88        }
89        else {
90            if (ino == 0) {
91                /* This should never happen */
92                SMBERROR("File ID of 0 in <%s>? \n",
93                         ((name != NULL) ? name : "unknown name"));
94                ret_ino = SMBFS_ROOT_INO;
95            }
96            else {
97                ret_ino = ino;
98            }
99        }
100    }
101
102    return (ret_ino);
103}
104
105/*
106 * This differs from smbfs_fullpath in
107 * 1) no pad byte
108 * 2) Unicode is always used
109 * 3) no end null bytes
110 */
111int
112smb2fs_fullpath(struct mbchain *mbp, struct smbnode *dnp,
113                const char *namep, size_t in_name_len,
114                const char *strm_namep, size_t in_strm_name_len,
115                int name_flags, uint8_t sep_char)
116{
117	int error = 0;
118	const char *name = (namep ? namep : NULL);
119	const char *strm_name = (strm_namep ? strm_namep : NULL);
120	size_t name_len = in_name_len;
121	size_t strm_name_len = in_strm_name_len;
122    size_t len = 0;
123    uint8_t stream_sep_char = ':';
124
125	if (dnp != NULL) {
126		struct smbmount *smp = dnp->n_mount;
127
128		error = smb_fphelp(smp, mbp, dnp, TRUE, &len);
129		if (error) {
130			return error;
131        }
132	}
133
134	if (name) {
135        /* Add separator char only if we added a path from above */
136        if (len > 0) {
137            error = mb_put_uint16le(mbp, sep_char);
138            if (error) {
139                return error;
140            }
141        }
142
143		error = smb_put_dmem(mbp, name, name_len, name_flags, TRUE, NULL);
144		if (error) {
145			return error;
146        }
147	}
148
149    /* Add Stream Name */
150	if (strm_name) {
151        /* Add separator char */
152        error = mb_put_uint16le(mbp, stream_sep_char);
153        if (error) {
154            return error;
155        }
156
157		error = smb_put_dmem(mbp, strm_name, strm_name_len, name_flags, TRUE, NULL);
158		if (error) {
159			return error;
160        }
161	}
162
163	return error;
164}
165