1 /*-
2 ***********************************************************************
3 *
4 * $Id: mask.c,v 1.22 2014/07/18 06:40:44 mavrik Exp $
5 *
6 ***********************************************************************
7 *
8 * Copyright 2005-2014 The FTimes Project, All Rights Reserved.
9 *
10 ***********************************************************************
11 */
12 #include "all-includes.h"
13
14 /*-
15 ***********************************************************************
16 *
17 * Global variables
18 *
19 ***********************************************************************
20 */
21 /*-
22 ***********************************************************************
23 *
24 * NOTE: The field order in this table must exactly match the order in
25 * gasDecodeTable (decode.c). Mask calculations rely on this.
26 *
27 ***********************************************************************
28 */
29 static MASK_B2S_TABLE gasCmpMaskTable[] =
30 {
31 { "name", 0 },
32 { "dev", 1 },
33 { "inode", 1 },
34 { "volume", 1 },
35 { "findex", 1 },
36 { "mode", 1 },
37 { "attributes", 1 },
38 { "nlink", 1 },
39 { "uid", 1 },
40 { "gid", 1 },
41 { "rdev", 1 },
42 { "atime", 2 },
43 { "ams", 0 },
44 { "mtime", 2 },
45 { "mms", 0 },
46 { "ctime", 2 },
47 { "cms", 0 },
48 { "chtime", 2 },
49 { "chms", 0 },
50 { "size", 1 },
51 { "altstreams", 1 },
52 { "md5", 1 },
53 { "sha1", 1 },
54 { "sha256", 1 },
55 { "magic", 1 },
56 { "osid", 1 },
57 { "gsid", 1 },
58 { "dacl", 1 },
59 };
60
61 #ifdef WIN32
62 static MASK_B2S_TABLE gasMapMaskTable[] =
63 {
64 { "volume", 1 },
65 { "findex", 1 },
66 { "attributes", 1 },
67 { "atime", 1 },
68 { "mtime", 1 },
69 { "ctime", 1 },
70 { "chtime", 1 },
71 { "size", 1 },
72 { "altstreams", 1 },
73 { "md5", 1 },
74 { "sha1", 1 },
75 { "sha256", 1 },
76 { "magic", 1 },
77 { "osid", 1 },
78 { "gsid", 1 },
79 { "dacl", 1 },
80 };
81 #else
82 static MASK_B2S_TABLE gasMapMaskTable[] =
83 {
84 { "dev", 1 },
85 { "inode", 1 },
86 { "mode", 1 },
87 { "nlink", 1 },
88 { "uid", 1 },
89 { "gid", 1 },
90 { "rdev", 1 },
91 { "atime", 1 },
92 { "mtime", 1 },
93 { "ctime", 1 },
94 { "size", 1 },
95 { "md5", 1 },
96 { "sha1", 1 },
97 { "sha256", 1 },
98 { "magic", 1 },
99 };
100 #endif
101
102 /*-
103 ***********************************************************************
104 *
105 * MaskBuildMask
106 *
107 ***********************************************************************
108 */
109 char *
MaskBuildMask(unsigned long ulMask,int iType,char * pcError)110 MaskBuildMask(unsigned long ulMask, int iType, char *pcError)
111 {
112 const char acRoutine[] = "MaskBuildMask()";
113 char *pcMask = NULL;
114 int i = 0;
115 int iCount = 0;
116 int iIndex = 0;
117 int iMaskSize = 0;
118 int iMaskTableLength = MaskGetTableLength(iType);
119 int iNLeft = 0;
120 MASK_B2S_TABLE *pasMaskTable = MaskGetTableReference(iType);
121 unsigned long ulTestBit = 0;
122
123 /*-
124 *********************************************************************
125 *
126 * Determine what type of mask we're dealing with.
127 *
128 *********************************************************************
129 */
130 switch (iType)
131 {
132 case MASK_RUNMODE_TYPE_CMP:
133 case MASK_RUNMODE_TYPE_DIG:
134 case MASK_RUNMODE_TYPE_MAP:
135 break;
136 default:
137 snprintf(pcError, MESSAGE_SIZE, "%s: Invalid type [%d]. That shouldn't happen.", acRoutine, iType);
138 return NULL;
139 break;
140 }
141
142 /*-
143 *********************************************************************
144 *
145 * Allocate enough memory to hold the mask converted into a string.
146 * The caller is expected to free this memory.
147 *
148 *********************************************************************
149 */
150 iMaskSize = iNLeft = strlen("none") + ((strlen("+") + MASK_NAME_SIZE) * iMaskTableLength) + 1;
151 pcMask = calloc(iMaskSize, 1);
152 if (pcMask == NULL)
153 {
154 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
155 return NULL;
156 }
157
158 /*-
159 *********************************************************************
160 *
161 * Start with the mask's anchor.
162 *
163 *********************************************************************
164 */
165 iCount = snprintf(&pcMask[iIndex], iNLeft, "none");
166 iIndex += iCount;
167 iNLeft -= iCount;
168
169 /*-
170 *********************************************************************
171 *
172 * Loop through the mask table adding a name only when the number of
173 * bits to set is greater than zero. If the number is zero, it means
174 * the field is (effectively) private.
175 *
176 *********************************************************************
177 */
178 for (i = 0; i < iMaskTableLength; i++)
179 {
180 ulTestBit = 1 << i;
181 if (MASK_BIT_IS_SET(ulMask, ulTestBit) && pasMaskTable[i].iBits2Set > 0)
182 {
183 iCount = snprintf(&pcMask[iIndex], iNLeft, "+%s", pasMaskTable[i].acName);
184 iIndex += iCount;
185 iNLeft -= iCount;
186 }
187 }
188
189 return pcMask;
190 }
191
192 /*-
193 ***********************************************************************
194 *
195 * MaskFreeMask
196 *
197 ***********************************************************************
198 */
199 void
MaskFreeMask(MASK_USS_MASK * psMask)200 MaskFreeMask(MASK_USS_MASK *psMask)
201 {
202 if (psMask != NULL)
203 {
204 if (psMask->pcMask != NULL)
205 {
206 free(psMask->pcMask);
207 }
208 free(psMask);
209 }
210 }
211
212
213 /*-
214 ***********************************************************************
215 *
216 * MaskGetTableLength
217 *
218 ***********************************************************************
219 */
220 int
MaskGetTableLength(int iType)221 MaskGetTableLength(int iType)
222 {
223 switch (iType)
224 {
225 case MASK_RUNMODE_TYPE_CMP:
226 return (sizeof(gasCmpMaskTable) / sizeof(gasCmpMaskTable[0]));
227 break;
228 case MASK_RUNMODE_TYPE_DIG:
229 return 0;
230 break;
231 case MASK_RUNMODE_TYPE_MAP:
232 return (sizeof(gasMapMaskTable) / sizeof(gasMapMaskTable[0]));
233 break;
234 default:
235 return 0;
236 break;
237 }
238 }
239
240
241 /*-
242 ***********************************************************************
243 *
244 * MaskGetTableReference
245 *
246 ***********************************************************************
247 */
248 MASK_B2S_TABLE *
MaskGetTableReference(int iType)249 MaskGetTableReference(int iType)
250 {
251 switch (iType)
252 {
253 case MASK_RUNMODE_TYPE_CMP:
254 return gasCmpMaskTable;
255 break;
256 case MASK_RUNMODE_TYPE_DIG:
257 return NULL;
258 break;
259 case MASK_RUNMODE_TYPE_MAP:
260 return gasMapMaskTable;
261 break;
262 default:
263 return NULL;
264 break;
265 }
266 }
267
268
269 /*-
270 ***********************************************************************
271 *
272 * MaskNewMask
273 *
274 ***********************************************************************
275 */
276 MASK_USS_MASK *
MaskNewMask(char * pcError)277 MaskNewMask(char *pcError)
278 {
279 const char acRoutine[] = "MaskNewMask()";
280 MASK_USS_MASK *psMask = NULL;
281
282 /*-
283 *********************************************************************
284 *
285 * The caller is expected to free this memory.
286 *
287 *********************************************************************
288 */
289 psMask = (MASK_USS_MASK *) calloc(sizeof(MASK_USS_MASK), 1);
290 if (psMask == NULL)
291 {
292 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
293 return NULL;
294 }
295
296 return psMask;
297 }
298
299
300 /*-
301 ***********************************************************************
302 *
303 * MaskParseMask
304 *
305 ***********************************************************************
306 */
307 MASK_USS_MASK *
MaskParseMask(char * pcMask,int iType,char * pcError)308 MaskParseMask(char *pcMask, int iType, char *pcError)
309 {
310 const char acRoutine[] = "MaskParseMask()";
311 char acLocalError[MESSAGE_SIZE] = "";
312 char cLastAction = 0;
313 char cNextAction = 0;
314 char *pcTemp = NULL;
315 char *pcTempLine = NULL;
316 char *pcToken = NULL;
317 int i = 0;
318 int j = 0;
319 int iDone = 0;
320 int iError = 0;
321 int iLength = strlen(pcMask);
322 int iMaskTableLength = MaskGetTableLength(iType);
323 int iOffset = 0;
324 MASK_B2S_TABLE *pasMaskTable = MaskGetTableReference(iType);
325 MASK_USS_MASK *psMask = NULL;
326 unsigned long ulAllMask = 0;
327
328 /*-
329 *********************************************************************
330 *
331 * Sanity check the type and intialize variables.
332 *
333 *********************************************************************
334 */
335 switch (iType)
336 {
337 case MASK_RUNMODE_TYPE_CMP:
338 ulAllMask = CMP_ALL_MASK;
339 break;
340 case MASK_RUNMODE_TYPE_DIG:
341 ulAllMask = DIG_ALL_MASK;
342 break;
343 case MASK_RUNMODE_TYPE_MAP:
344 ulAllMask = MAP_ALL_MASK;
345 break;
346 default:
347 snprintf(pcError, MESSAGE_SIZE, "%s: Invalid type [%d]. That shouldn't happen.", acRoutine, iType);
348 return NULL;
349 break;
350 }
351
352 /*-
353 *********************************************************************
354 *
355 * Allocate and initialize memory for the mask.
356 *
357 *********************************************************************
358 */
359 psMask = MaskNewMask(acLocalError);
360 if (psMask == NULL)
361 {
362 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
363 return NULL;
364 }
365
366 /*-
367 *********************************************************************
368 *
369 * Set the user-supplied string mask.
370 *
371 *********************************************************************
372 */
373 iError = MaskSetMask(psMask, pcMask, acLocalError);
374 if (iError != ER_OK)
375 {
376 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
377 MaskFreeMask(psMask);
378 return NULL;
379 }
380
381 /*-
382 *********************************************************************
383 *
384 * Check that the mask begins with a valid anchor.
385 *
386 *********************************************************************
387 */
388 if (strncasecmp(pcMask, "all", 3) == 0)
389 {
390 psMask->ulMask = ~0;
391 iLength = 3;
392 }
393 else if (strncasecmp(pcMask, "none", 4) == 0)
394 {
395 psMask->ulMask = 0;
396 iLength = 4;
397 }
398 else
399 {
400 snprintf(pcError, MESSAGE_SIZE, "%s: Prefix = [%s] != [all|none]: Invalid prefix.", acRoutine, pcMask);
401 MaskFreeMask(psMask);
402 return NULL;
403 }
404
405 /*-
406 *********************************************************************
407 *
408 * Continue parsing the mask. If there are no more fields, we're done.
409 *
410 *********************************************************************
411 */
412 switch (pcMask[iLength])
413 {
414 case '+':
415 case '-':
416 cLastAction = '?';
417 cNextAction = pcMask[iLength++];
418 break;
419 case 0:
420 psMask->ulMask &= ulAllMask;
421 return psMask;
422 break;
423 default:
424 snprintf(pcError, MESSAGE_SIZE, "%s: Operator = [%c] != [+|-]: Invalid operator.", acRoutine, pcMask[iLength]);
425 MaskFreeMask(psMask);
426 return NULL;
427 break;
428 }
429
430 /*-
431 *********************************************************************
432 *
433 * Copy the remainder of the input to a scratch pad.
434 *
435 *********************************************************************
436 */
437 pcTemp = &pcMask[iLength];
438 iLength = strlen(pcTemp); /* Calculate new length. */
439 pcTempLine = calloc(iLength + 1, 1);
440 if (pcTempLine == NULL)
441 {
442 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
443 MaskFreeMask(psMask);
444 return NULL;
445 }
446 strncpy(pcTempLine, pcTemp, iLength + 1);
447
448 /*-
449 *********************************************************************
450 *
451 * Remove EOL characters.
452 *
453 *********************************************************************
454 */
455 SupportChopEOLs(pcTempLine, 0, NULL);
456
457 /*-
458 *********************************************************************
459 *
460 * Scan through the string looking for tokens delimited by '+', '-',
461 * or 0.
462 *
463 *********************************************************************
464 */
465 for (pcToken = pcTempLine, iOffset = 0, iDone = 0; !iDone;)
466 {
467 if (pcTempLine[iOffset] == '+' || pcTempLine[iOffset] == '-' || pcTempLine[iOffset] == 0)
468 {
469 if (pcTempLine[iOffset] == 0)
470 {
471 iDone = 1;
472 }
473
474 /*-
475 *****************************************************************
476 *
477 * Update the action values.
478 *
479 *****************************************************************
480 */
481 cLastAction = cNextAction;
482 cNextAction = pcTempLine[iOffset];
483
484 /*-
485 *****************************************************************
486 *
487 * Terminate the token.
488 *
489 *****************************************************************
490 */
491 pcTempLine[iOffset] = 0;
492
493 /*-
494 *****************************************************************
495 *
496 * Scan the table looking for this token. Add or subtract the
497 * expanded token value (i.e., the time tokens count for more
498 * than one mask bit each) from the mask depending on whether
499 * '+' or '-' was given.
500 *
501 *****************************************************************
502 */
503 for (i = 0; i < iMaskTableLength; i++)
504 {
505 if (strcasecmp(pcToken, pasMaskTable[i].acName) == 0 && pasMaskTable[i].iBits2Set > 0)
506 {
507 for (j = 0; j < pasMaskTable[i].iBits2Set; j++)
508 {
509 PUTBIT(psMask->ulMask, ((cLastAction == '+') ? 1 : 0), (i + j));
510 }
511 break;
512 }
513 }
514 if (i == iMaskTableLength)
515 {
516 /*-
517 ***************************************************************
518 *
519 * Check to see if this is a group field before aborting.
520 *
521 ***************************************************************
522 */
523 if (strcasecmp(pcToken, "hashes") == 0 && (iType == MASK_RUNMODE_TYPE_CMP || iType == MASK_RUNMODE_TYPE_MAP))
524 {
525 if (cLastAction == '+')
526 {
527 psMask->ulMask |= (iType == MASK_RUNMODE_TYPE_CMP) ? CMP_HASHES_MASK : MAP_HASHES_MASK;
528 }
529 else
530 {
531 psMask->ulMask &= (iType == MASK_RUNMODE_TYPE_CMP) ? ~CMP_HASHES_MASK : ~MAP_HASHES_MASK;
532 }
533 }
534 else if (strcasecmp(pcToken, "times") == 0 && (iType == MASK_RUNMODE_TYPE_CMP || iType == MASK_RUNMODE_TYPE_MAP))
535 {
536 if (cLastAction == '+')
537 {
538 psMask->ulMask |= (iType == MASK_RUNMODE_TYPE_CMP) ? CMP_TIMES_MASK : MAP_TIMES_MASK;
539 }
540 else
541 {
542 psMask->ulMask &= (iType == MASK_RUNMODE_TYPE_CMP) ? ~CMP_TIMES_MASK : ~MAP_TIMES_MASK;
543 }
544 }
545 else
546 {
547 snprintf(pcError, MESSAGE_SIZE, "%s: Token = [%c%s]: Invalid value.", acRoutine, cLastAction, pcToken);
548 MaskFreeMask(psMask);
549 return NULL;
550 }
551 }
552 if (!iDone)
553 {
554 iOffset++;
555 pcToken = &pcTempLine[iOffset];
556 }
557 }
558 else
559 {
560 iOffset++;
561 }
562 }
563
564 /*-
565 *********************************************************************
566 *
567 * Remove any extra bits, and send it back to the caller.
568 *
569 *********************************************************************
570 */
571 psMask->ulMask &= ulAllMask;
572
573 return psMask;
574 }
575
576
577 /*-
578 ***********************************************************************
579 *
580 * MaskSetDynamicString
581 *
582 ***********************************************************************
583 */
584 int
MaskSetDynamicString(char ** ppcValue,char * pcNewValue,char * pcError)585 MaskSetDynamicString(char **ppcValue, char *pcNewValue, char *pcError)
586 {
587 const char acRoutine[] = "MaskSetDynamicString()";
588 char *pcTempValue = NULL;
589 int iLength = 0;
590
591 /*-
592 *********************************************************************
593 *
594 * Allocate additional memory as required. Preserve the user-supplied
595 * pointer in case the operation fails. Then, copy the new value into
596 * place. The caller is expected to free this memory.
597 *
598 *********************************************************************
599 */
600 iLength = strlen(pcNewValue);
601 pcTempValue = realloc(*ppcValue, iLength + 1);
602 if (pcTempValue == NULL)
603 {
604 snprintf(pcError, MESSAGE_SIZE, "%s: realloc(): %s", acRoutine, strerror(errno));
605 return ER;
606 }
607 strncpy(pcTempValue, pcNewValue, iLength + 1);
608 *ppcValue = pcTempValue;
609
610 return ER_OK;
611 }
612
613
614 /*-
615 ***********************************************************************
616 *
617 * MaskSetMask
618 *
619 ***********************************************************************
620 */
621 int
MaskSetMask(MASK_USS_MASK * psMask,char * pcMask,char * pcError)622 MaskSetMask(MASK_USS_MASK *psMask, char *pcMask, char *pcError)
623 {
624 const char acRoutine[] = "MaskSetMask()";
625 char acLocalError[MESSAGE_SIZE] = "";
626 int iError = 0;
627
628 if (psMask == NULL)
629 {
630 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined mask.", acRoutine);
631 return ER;
632 }
633
634 iError = MaskSetDynamicString(&psMask->pcMask, pcMask, acLocalError);
635 if (iError == ER)
636 {
637 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
638 return ER;
639 }
640
641 return ER_OK;
642 }
643