rx: Don't crash when emptying an empty identity
[openafs.git] / src / rx / rx_identity.c
1 /*
2  * Copyright (c) 2010 Your File System Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include <afsconfig.h>
26 #include <afs/param.h>
27
28 #ifndef KERNEL
29 # include <roken.h>
30 # include <sys/types.h>
31 # include <string.h>
32 #else
33 # include "afs/sysincludes.h"
34 # include "afsincludes.h"
35 #endif
36
37 #include <rx/rx.h>
38 #include <rx/rx_identity.h>
39
40 /*!
41  * Check to see if two rx identities match
42  *
43  * @param a
44  *      First identity
45  * @param b
46  *      Second identity
47  * @returns
48  *      True if a and b are identical, otherwise false
49  */
50 int
51 rx_identity_match(struct rx_identity *a, struct rx_identity *b)
52 {
53     return (a->kind == b->kind && a->exportedName.len == b->exportedName.len
54             && (memcmp(a->exportedName.val, b->exportedName.val,
55                        a->exportedName.len) == 0));
56 }
57
58 /*!
59  * Populate an identity
60  *
61  * Populate an existing identity with copies of the data passed to the
62  * function. This will replace (without freeing) any existing identity
63  * contents.
64  *
65  * @param identity
66  *      The identity to populate
67  * @param kind
68  *      The type of data contained within this identity
69  * @param displayName
70  *      The displayName of this identity
71  * @param enameData
72  *      The opaque data that represents this identity
73  * @param enameLength
74  *      The length of enameData
75  */
76
77 void
78 rx_identity_populate(struct rx_identity *identity, rx_identity_kind kind,
79                      char *displayName, void *enameData, size_t enameLength)
80 {
81     memset(identity, 0, sizeof(struct rx_identity));
82
83     identity->kind = kind;
84     identity->displayName = rxi_Alloc(strlen(displayName)+1);
85     memcpy(identity->displayName, displayName, strlen(displayName)+1);
86
87     rx_opaque_populate(&identity->exportedName, enameData, enameLength);
88 }
89
90 /*!
91  * Copy an identity
92  *
93  * Create a new identity as a copy of an existing one.
94  *
95  * @param from
96  *      The identity to copy from
97  * @return
98  *      The new identity
99  */
100 struct rx_identity *
101 rx_identity_copy(struct rx_identity *from)
102 {
103    return rx_identity_new(from->kind, from->displayName,
104                           from->exportedName.val, from->exportedName.len);
105 }
106
107
108 /*!
109  * Copy an identity's contents
110  *
111  * Copy the contents of one identity into another one. This will replace
112  * (without freeing) any existing identity contents
113  *
114  * @param to
115  *      The identity to copy to
116  * @param from
117  *      The identity to copy from
118  */
119
120 void
121 rx_identity_copyContents(struct rx_identity *to, struct rx_identity *from)
122 {
123     rx_identity_populate(to, from->kind, from->displayName,
124                          from->exportedName.val, from->exportedName.len);
125     return;
126 }
127
128 /*!
129  * Build a new identity
130  *
131  * Create a new identity, with copies of the data passed to this function.
132  *
133  * @param kind
134  *      The type of data contained within this identity
135  * @param displayName
136  *      The displayName of this identity
137  * @param enameData
138  *      The opaque data that represents this identity
139  * @param enameLength
140  *      The length of enameData
141  * @returns
142  *      The new identity
143  */
144
145 struct rx_identity *
146 rx_identity_new(rx_identity_kind kind, char *displayName, void *enameData,
147                 size_t enameLength)
148 {
149     struct rx_identity *identity;
150
151     identity = rxi_Alloc(sizeof(struct rx_identity));
152     rx_identity_populate(identity, kind, displayName, enameData, enameLength);
153
154     return identity;
155 }
156
157 /*!
158  * Free the contents of an identity
159  *
160  * @param identity
161  *      The identity to free the contents of
162  */
163
164 void
165 rx_identity_freeContents(struct rx_identity *identity)
166 {
167     if (identity->displayName) {
168         rxi_Free(identity->displayName, strlen(identity->displayName));
169         identity->displayName = NULL;
170     }
171
172     rx_opaque_freeContents(&identity->exportedName);
173 }
174
175 /*!
176  * Free an identity
177  *
178  * @param identity
179  *      The identity to free (passed by reference)
180  */
181
182 void
183 rx_identity_free(struct rx_identity **identity)
184 {
185     rx_identity_freeContents(*identity);
186     rxi_Free(*identity, sizeof(struct rx_identity));
187     *identity = NULL;
188 }