MHEG5  18.9.0
MHEG5 Documentation
mh5hfs.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2009 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 
31 #include "mh5profile.h"
32 #include "mh5hfs.h"
33 #include "mh5gate.h"
34 #include "mh5memory.h"
35 #include "techtype.h"
36 #include "glue_debug.h"
37 
38 /*---constant definitions for this file--------------------------------------*/
39 /*#define HFS_DEBUG_TABLE*/
40 /*#define HFS_DEBUG_PRINT*/
41 
42 #ifdef HFS_DEBUG_PRINT
43 #define PRINT(x) TRACE(TFILE,x)
44 #else
45 #define PRINT(x)
46 #endif
47 
48 /* TODO: This needs to be tied in with maximum number of applications */
49 #define MAX_HFS_TABLES 6
50 
51 
52 /*---local typedef structs for this file-------------------------------------*/
53 typedef struct HfsMapping
54 {
55  struct HfsMapping *next;
59 } HfsMapping;
60 
61 typedef struct HfsTable
62 {
64 } HfsTable;
65 
66 /*---local (static) variable declarations for this file----------------------*/
67 
68 static HfsTable hfsTables[MAX_HFS_TABLES];
69 static HfsTable *hfsTable = &hfsTables[0];
70 static HfsMapping defaultMapping = {
71  NULL,
72  { 2, (MHEG5Byte *)"//" },
73  { 6, (MHEG5Byte *)"DSM://" },
74  0
75 };
76 
77 /*---local function prototypes for this file---------------------------------*/
78 static void ClearMappingTable(void);
79 static void PushMappingTable(void);
80 static void PopMappingTable(void);
81 static void ReleaseMapping(HfsMapping *mapping);
82 static HfsMapping** FindMapping(MHEG5String *pathName);
83 static void RemoveMapping(HfsMapping **pMapping);
84 static void ReplaceMapping(HfsMapping **pMapping, HfsMapping *mapping);
85 static HfsMapping* CreateMapping(MHEG5String *pathName,
87 static void InsertMapping(HfsMapping *newMapping);
88 static MHEG5Bool IsStringEqual(MHEG5String *string, MHEG5String *otherString);
89 static MHEG5Bool IsStringAfter(MHEG5String *string, MHEG5String *otherString);
90 static MHEG5Bool IsDefaultMapping(HfsMapping *mapping);
91 static MHEG5Bool IsValidReference(MHEG5String *reference);
92 static MHEG5Bool IsValidInput(MHEG5String *pathName, MHEG5String *mappingList);
93 
94 #ifdef HFS_DEBUG_TABLE
95 static void PrintMappingTable(void);
96 #endif /* HFS_DEBUG_TABLE */
97 
98 /*---global function definitions---------------------------------------------*/
99 
108 {
109  ClearMappingTable();
110 }
111 
118 {
119  ClearMappingTable();
120  while (hfsTable != hfsTables)
121  {
122  PopMappingTable();
123  ClearMappingTable();
124  }
125 }
126 
132 {
133  PushMappingTable();
134 }
135 
142 {
143  PopMappingTable();
144 }
145 
152 void MHEG5SetHybridFileSystem(MHEG5String *pathName, MHEG5String *mappingList)
153 {
154  HfsMapping *newMapping;
155  HfsMapping **pMapping;
156 
157  TRACE(TFILE,("(\"%.*s\",\"%.*s\")",
158  (int)pathName->len, (char *)pathName->data,
159  (int)mappingList->len, (char *)mappingList->data));
160 
161  if (pathName->len > 0)
162  {
163  pMapping = FindMapping(pathName);
164  if (pMapping != NULL)
165  {
166  if (mappingList->len == 0)
167  {
168  RemoveMapping(pMapping);
169  }
170  else
171  {
172  newMapping = CreateMapping(pathName, mappingList);
173  if (newMapping != NULL)
174  {
175  ReplaceMapping(pMapping, newMapping);
176  }
177  }
178  }
179  else
180  {
181  if (mappingList->len != 0)
182  {
183  newMapping = CreateMapping(pathName, mappingList);
184  if (newMapping != NULL)
185  {
186  InsertMapping(newMapping);
187  }
188  }
189  }
190  }
191  else
192  {
193  /* When pathName is empty, all mappings are removed and the
194  * default mapping is restored
195  */
197  }
198 
199 #ifdef HFS_DEBUG_TABLE
200  DBGTRACE(TFILE,"");
201  PrintMappingTable();
202 #endif
203 }
204 
212 {
213  HfsMapping *mapping;
214  HfsMapping *currentMapping;
216  MHEG5Int longest;
217 
218  longest = 0;
219  mapping = NULL;
220  if (IsValidReference(reference))
221  {
222  currentMapping = hfsTable->anchor;
223  while (currentMapping != NULL)
224  {
225  pathName = currentMapping->pathName;
226  if (longest < pathName.len)
227  {
228  if (pathName.data[pathName.len - 1] == '/')
229  {
230  /* Directory, must be a proper prefix */
231  if (pathName.len < reference->len &&
232  memcmp(pathName.data, reference->data, pathName.len) == 0)
233  {
234  longest = pathName.len;
235  mapping = currentMapping;
236  }
237  }
238  else
239  {
240  /* File, must be a complete match */
241  if (pathName.len == reference->len &&
242  memcmp(pathName.data, reference->data, pathName.len) == 0)
243  {
244  longest = pathName.len;
245  mapping = currentMapping;
246  }
247  }
248  }
249  currentMapping = currentMapping->next;
250  }
251  if (mapping != NULL)
252  {
253  TRACE(TFILE,("path=%.*s mapping=%.*s",
254  (int)mapping->pathName.len, mapping->pathName.data,
255  (int)mapping->mappingList.len, mapping->mappingList.data));
256  mapping->refCount++;
257  }
258  }
259 
260  return mapping;
261 }
262 
271 {
272  assert(handle != NULL);
273 
274  ReleaseMapping(handle);
275 }
276 
283 void MHEG5InitMappingIter(MHEG5MappingIter_t *iter, void *mapping)
284 {
285  assert(iter != NULL);
286  assert(mapping != NULL);
287 
288  iter->mapping = mapping;
289  iter->currentPos = 0;
290  TRACE(TFILE,(""));
291 }
292 
302  MHEG5MappingIter_t *iter)
303 {
304  MHEG5String reference;
305  HfsMapping *mapping;
306  MHEG5Byte *data;
307  MHEG5Int len, limit;
308 
309  assert(iter != NULL);
310 
311  mapping = iter->mapping;
312  if (iter->currentPos == mapping->mappingList.len)
313  {
314  /* End of iteration */
315  reference.len = 0;
316  reference.data = NULL;
317  TRACE(TFILE,("END"));
318  }
319  else
320  {
321  /* Find next space or end-of-list */
322  data = mapping->mappingList.data + iter->currentPos;
323  limit = mapping->mappingList.len - iter->currentPos;
324  len = 0;
325  while (len < limit && data[len] != ' ')
326  {
327  len++;
328  }
329 
330  if (data[len - 1] == '/')
331  {
332  reference.len = 0;
333  reference.data = STR_DataAlloc(len + ref->len -
334  mapping->pathName.len);
335  if (reference.data != NULL)
336  {
337  memcpy(reference.data, data, len);
338  reference.len += len;
339  memcpy(reference.data + reference.len,
340  ref->data + mapping->pathName.len,
341  ref->len - mapping->pathName.len);
342  reference.len += ref->len - mapping->pathName.len;
343  reference.data[reference.len] = '\0';
344  }
345  }
346  else
347  {
348  reference.len = 0;
349  reference.data = STR_DataAlloc(len);
350  if (reference.data != NULL)
351  {
352  memcpy(reference.data, data, len);
353  reference.data[len] = '\0';
354  reference.len = len;
355  }
356  }
357 
358  iter->currentPos += len;
359  if (iter->currentPos < mapping->mappingList.len)
360  {
361  /* Skip space */
362  iter->currentPos++;
363  }
364  TRACE(TFILE,("reference=%.*s",(int)reference.len, reference.data));
365  }
366  return reference;
367 }
368 
382 {
383  MHEG5String path;
384  MHEG5String output, input;
385  void *mapping;
386  E_FS_ORIGIN origin;
387  MHEG5MappingIter_t iter;
388 
389  output.len = 0;
390  output.data = NULL;
391 
392  /* Convenience function - uses other API functions */
393  path = MHEG5convertGIDGetOrigin(reference,&origin);
394  if (origin == ORIGIN_HYBRID)
395  {
396  input.data = (U8BIT *)path.data + 7; /* skip "hybrid:" */
397  input.len = path.len - 7;
398  mapping = MHEG5GetHybridFileSystemMapping(&input);
399  MHEG5InitMappingIter(&iter, mapping);
400  output = MHEG5GetNextReference(&input, &iter);
401  while (output.len != 0)
402  {
403  if (output.len >= 6 && memcmp(output.data, "DSM://", 6) == 0)
404  {
405  break;
406  }
407  MHEG5stringDestruct(&output);
408  output = MHEG5GetNextReference(&input, &iter);
409  }
411  }
412  else if (origin == ORIGIN_DSM)
413  {
414  /* starts with "DSM://" */
415  output = MHEG5stringCopy(*reference);
416  }
417  MHEG5stringDestruct(&path);
418 
419  return output;
420 }
421 
422 /*---local function definitions----------------------------------------------*/
423 
424 
429 static void ClearMappingTable(void)
430 {
431  HfsMapping *mapping;
432 
433  /* Release all mappings */
434  mapping = hfsTable->anchor;
435  while (mapping != NULL)
436  {
437  hfsTable->anchor = mapping->next;
438  ReleaseMapping(mapping);
439  mapping = hfsTable->anchor;
440  }
441 
442  /* Create default mapping */
443  hfsTable->anchor = &defaultMapping;
444 
445 #ifdef HFS_DEBUG_TABLE
446  DBGTRACE(TFILE,"");
447  PrintMappingTable();
448 #endif
449 }
450 
455 static void PushMappingTable(void)
456 {
457  HfsTable *newTable = hfsTable + 1;
458  HfsMapping *curr, **new;
459 
460  assert(newTable - hfsTables < MAX_HFS_TABLES);
461  assert(newTable->anchor == NULL ||
462  newTable->anchor == &defaultMapping);
463 
464  /* Copy mapping, resetting reference counts */
465  curr = hfsTable->anchor;
466  new = &newTable->anchor;
467  while (curr != NULL)
468  {
469  (*new) = MHEG5getMem(sizeof **new);
470  if (*new != NULL)
471  {
472  (*new)->pathName = MHEG5stringCopy(curr->pathName);
473  (*new)->mappingList = MHEG5stringCopy(curr->mappingList);
474  (*new)->refCount = 1;
475 
476  new = &(*new)->next;
477  }
478  curr = curr->next;
479  }
480  *new = NULL;
481 
482  ++hfsTable;
483 
484 #ifdef HFS_DEBUG_TABLE
485  DBGTRACE(TFILE,"");
486  PrintMappingTable();
487 #endif
488 }
489 
494 static void PopMappingTable(void)
495 {
496  assert(hfsTable - hfsTables > 0);
497 
498  ClearMappingTable();
499  --hfsTable;
500 
501 #ifdef HFS_DEBUG_TABLE
502  DBGTRACE(TFILE,"");
503  PrintMappingTable();
504 #endif
505 }
506 
514 static void ReleaseMapping(HfsMapping *mapping)
515 {
516  if (mapping != &defaultMapping)
517  {
518  mapping->refCount--;
519  assert(mapping->refCount >= 0);
520 
521  if (mapping->refCount == 0)
522  {
523  MHEG5stringDestruct(&mapping->pathName);
524  MHEG5stringDestruct(&mapping->mappingList);
525  MHEG5freeMem(mapping);
526  }
527  }
528 }
529 
535 static HfsMapping** FindMapping(MHEG5String *pathName)
536 {
537  HfsMapping *mapping;
538  HfsMapping **pMapping;
539  MHEG5Bool match;
540 
541  pMapping = &hfsTable->anchor;
542  mapping = *pMapping;
543  match = MHEG5FALSE;
544  while (mapping != NULL && !match)
545  {
546  match = IsStringEqual(pathName, &mapping->pathName);
547  if (!match)
548  {
549  pMapping = &mapping->next;
550  mapping = *pMapping;
551  }
552  }
553 
554  if (!match)
555  {
556  pMapping = NULL;
557  }
558 
559  return pMapping;
560 }
561 
568 static void RemoveMapping(HfsMapping **pMapping)
569 {
570  HfsMapping *oldMapping;
571  HfsMapping *nextMapping;
572 
573  oldMapping = *pMapping;
574  if (!IsDefaultMapping(oldMapping))
575  {
576  nextMapping = oldMapping->next;
577 
578  /* Detach old mapping */
579  *pMapping = nextMapping;
580 
581  /* Release old mapping */
582  ReleaseMapping(oldMapping);
583  }
584 }
585 
594 static void ReplaceMapping(HfsMapping **pMapping, HfsMapping *mapping)
595 {
596  HfsMapping *oldMapping;
597  HfsMapping *nextMapping;
598 
599  oldMapping = (*pMapping);
600  nextMapping = oldMapping->next;
601 
602  /* Detach old mapping */
603  oldMapping->next = NULL;
604 
605  /* Replace mapping */
606  mapping->next = nextMapping;
607  *pMapping = mapping;
608 
609  /* Release old mapping */
610  ReleaseMapping(oldMapping);
611 }
612 
620 static HfsMapping* CreateMapping(MHEG5String *pathName,
621  MHEG5String *mappingList)
622 {
623  HfsMapping *mapping;
624 
625  mapping = NULL;
626  if (IsValidInput(pathName, mappingList))
627  {
628  mapping = MHEG5getMem(sizeof *mapping);
629  if (mapping != NULL)
630  {
631  mapping->pathName = MHEG5stringCopy(*pathName);
632  mapping->mappingList = MHEG5stringCopy(*mappingList);
633  if ((mapping->pathName.len == pathName->len) &&
634  (mapping->mappingList.len == mappingList->len))
635  {
636  mapping->next = NULL;
637  mapping->refCount = 1;
638  }
639  else
640  {
641  MHEG5stringDestruct(&mapping->pathName);
642  MHEG5stringDestruct(&mapping->mappingList);
643  MHEG5freeMem(mapping);
644  mapping = NULL;
645  }
646  }
647  }
648 
649  return mapping;
650 }
651 
660 static void InsertMapping(HfsMapping *newMapping)
661 {
662  HfsMapping *mapping;
663  HfsMapping **pMapping;
664 
665  newMapping->next = NULL;
666 
667  pMapping = &hfsTable->anchor;
668  while (*pMapping != NULL)
669  {
670  mapping = *pMapping;
671  if (IsStringAfter(&newMapping->pathName, &mapping->pathName))
672  {
673  newMapping->next = mapping;
674  break;
675  }
676  else
677  {
678  pMapping = &(*pMapping)->next;
679  }
680  }
681  *pMapping = newMapping;
682 }
683 
690 static MHEG5Bool IsStringEqual(MHEG5String *string, MHEG5String *otherString)
691 {
692  MHEG5Bool equal;
693 
694  equal = MHEG5FALSE;
695  if (string->len == otherString->len)
696  {
697  if (string->len == 0 ||
698  (string->len > 0 &&
699  memcmp(string->data, otherString->data, string->len) == 0))
700  {
701  equal = MHEG5TRUE;
702  }
703  }
704 
705  return equal;
706 }
707 
716 static MHEG5Bool IsStringAfter(MHEG5String *string, MHEG5String *otherString)
717 {
718  MHEG5Bool after;
719  MHEG5Int toCompare;
720  int comp;
721 
722  after = MHEG5FALSE;
723  toCompare = string->len;
724  if (toCompare > otherString->len)
725  {
726  toCompare = otherString->len;
727  }
728 
729  comp = memcmp(string->data, otherString->data, toCompare);
730  if (comp > 0 || (comp == 0 && string->len > otherString->len))
731  {
732  after = MHEG5TRUE;
733  }
734 
735  return after;
736 }
737 
745 static MHEG5Bool IsDefaultMapping(HfsMapping *mapping)
746 {
747  MHEG5Bool result;
748 
749  result = MHEG5FALSE;
750  if (mapping->pathName.len == 2 &&
751  mapping->pathName.data[0] == '/' &&
752  mapping->pathName.data[1] == '/')
753  {
754  result = MHEG5TRUE;
755  }
756 
757  return result;
758 }
759 
767 static MHEG5Bool IsValidReference(MHEG5String *reference)
768 {
769  MHEG5Bool valid;
770 
771  valid = MHEG5FALSE;
772  if ((reference->len > 2) &&
773  (reference->data[0] == '/') && (reference->data[1] == '/'))
774  {
775  valid = MHEG5TRUE;
776  }
777 
778  return valid;
779 }
780 
794 static MHEG5Bool IsValidInput(MHEG5String *pathName, MHEG5String *mappingList)
795 {
796  MHEG5Int start;
797  MHEG5Int offset;
798  MHEG5Int length;
799  MHEG5String check;
800  MHEG5Bool valid;
801  MHEG5Bool isFile;
802  MHEG5String path;
803  E_FS_ORIGIN origin;
804 
805  valid = MHEG5TRUE;
806 
807  /* Check path name */
808  path = MHEG5convertGIDGetOrigin(pathName,&origin);
809  if (path.len > 0)
810  {
811  if (path.data[path.len - 1] != '/')
812  {
813  isFile = MHEG5TRUE;
814  }
815  else
816  {
817  isFile = MHEG5FALSE;
818  }
819  }
820  else
821  {
822  valid = MHEG5FALSE;
823  }
824 
825  /* Check mapping list */
826  start = 0;
827  offset = 0;
828  while (valid && offset < mappingList->len)
829  {
830  while (offset < mappingList->len && mappingList->data[offset] != ' ')
831  {
832  ++offset;
833  }
834 
835  length = offset - start;
836  PRINT(("Checking \"%.*s\"\n", (int)length, mappingList->data + start));
837 
838  check.data = mappingList->data + start;
839  check.len = length;
840  MHEG5stringDestruct(&path);
841  path = MHEG5convertGIDGetOrigin(&check,&origin);
842  if (path.len == 0 || origin == ORIGIN_HYBRID)
843  {
844  valid = MHEG5FALSE;
845  }
846  else if (path.data[path.len - 1] == '/' && isFile)
847  {
848  valid = MHEG5FALSE;
849  }
850  else if (path.data[path.len - 1] != '/' && !isFile)
851  {
852  valid = MHEG5FALSE;
853  }
854 
855  ++offset;
856  start = offset;
857  }
858  MHEG5stringDestruct(&path);
859 
860  return valid;
861 }
862 
863 #ifdef HFS_DEBUG_TABLE
864 
868 static void PrintMappingTable(void)
869 {
870  HfsMapping *mapping;
871 
872  mapping = hfsTable->anchor;
873  while (mapping != NULL)
874  {
875  TPRINT(TFILE,("pathName = \"%.*s\"\n", (int)mapping->pathName.len,
876  (char *)mapping->pathName.data));
877  TPRINT(TFILE,("mappingList = \"%.*s\"\n", (int)mapping->mappingList.len,
878  (char *)mapping->mappingList.data));
879  mapping = mapping->next;
880  }
881 }
882 
883 #endif /* HFS_DEBUG_TABLE */
884 
885 
#define TPRINT(t, x)
Definition: glue_debug.h:119
struct HfsMapping HfsMapping
void MHEG5ReleaseHybridFileSystemMapping(void *handle)
Release mapping returned from the hybrid file system. The mapping must be have been returned by a cal...
Definition: mh5hfs.c:270
struct HfsTable HfsTable
#define DBGTRACE(...)
Definition: glue_debug.h:126
void MHEG5ClearHybridFileSystem(void)
Clear the hybrid file system and restore the default mapping // -> DSM://.
Definition: mh5hfs.c:117
const char * data
Definition: mh5gate.c:56
void MHEG5PopHybridFileSystem(void)
Clear the current hybrid file system and pop a stored hybrid file system from the stack...
Definition: mh5hfs.c:141
HfsMapping * anchor
Definition: mh5hfs.c:63
Debug tracing.
unsigned char * STR_DataAlloc(unsigned int size)
Definition: glue_memory.c:596
MHEG5String MHEG5GetFirstDsmReference(MHEG5String *reference)
Return first reference with DSM:// source. This is a convenience function that converts a hybrid:// r...
Definition: mh5hfs.c:381
#define MHEG5getMem
Definition: glue_memory.h:93
void * MHEG5GetHybridFileSystemMapping(MHEG5String *reference)
Return mapping from the hybrid file system given path name. The mapping must be released using MHEG5R...
Definition: mh5hfs.c:211
#define MAX_HFS_TABLES
Definition: mh5hfs.c:49
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
Definition: mh5base.c:574
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
uint8_t U8BIT
Definition: techtype.h:82
long MHEG5Int
Definition: mh5base.h:73
struct HfsMapping * next
Definition: mh5hfs.c:55
#define MHEG5freeMem
Definition: glue_memory.h:94
This file defines the profile for the MHEG engine.
Implement Functions to support Service Gateways. Functions for standarizing several GroupIDs like +DS...
short MHEG5Bool
Definition: mh5base.h:71
void MHEG5PushHybridFileSystem(void)
Push a copy of the current hybrid file system into the stack.
Definition: mh5hfs.c:131
MHEG5String MHEG5convertGIDGetOrigin(MHEG5String *inRef, E_FS_ORIGIN *pOrigin)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:282
unsigned char MHEG5Byte
Definition: mh5base.h:74
MHEG5Byte * data
Definition: mh5base.h:85
void MHEG5InitialiseHybridFileSystem(void)
Initialise the hybrid file system. The hybrid file system is a set of mappings from a "path" string (...
Definition: mh5hfs.c:107
int len
Definition: mh5gate.c:57
#define MHEG5TRUE
Definition: mh5base.h:49
MHEG5Int currentPos
Definition: mh5hfs.h:40
void MHEG5InitMappingIter(MHEG5MappingIter_t *iter, void *mapping)
Initialise hybrid filesystem mapping iterator.
Definition: mh5hfs.c:283
System Wide Global Technical Data Type Definitions.
MHEG5String mappingList
Definition: mh5hfs.c:57
redirection include
MHEG5String MHEG5GetNextReference(MHEG5String *ref, MHEG5MappingIter_t *iter)
Return next reference from mapping iterator.
Definition: mh5hfs.c:301
void * mapping
Definition: mh5hfs.h:39
MHEG5Int refCount
Definition: mh5hfs.c:58
MHEG5Int len
Definition: mh5base.h:84
#define PRINT(x)
Definition: mh5hfs.c:45
void MHEG5SetHybridFileSystem(MHEG5String *pathName, MHEG5String *mappingList)
Set mapping list in the hybrid file system. This function sets, clears or modifies the list of mappin...
Definition: mh5hfs.c:152
MHEG5String pathName
Definition: mh5hfs.c:56
E_FS_ORIGIN
Definition: mh5gate.h:48
#define MHEG5FALSE
Definition: mh5base.h:48
Functions relating to Hybrid file system.
#define TRACE(t, x)
Definition: glue_debug.h:118