4 * (c) Copyright 1997-1999,2006 by Matthew Dillon. Permission to
5 * use and distribute based on the FreeBSD copyright.
7 * $DragonFly: src/bin/cpdup/fsmid.c,v 1.3 2008/11/10 14:30:02 swildner Exp $
12 typedef struct FSMIDNode
{
13 struct FSMIDNode
*fid_Next
;
19 static FSMIDNode
*fsmid_lookup(const char *sfile
);
20 static void fsmid_cache(const char *dpath
, int ddirlen
);
22 static char *FSMIDDCache
; /* cache source directory name */
23 static FSMIDNode
*FSMIDBase
;
24 static int FSMIDDCacheDirLen
;
25 static int FSMIDDCacheDirty
;
30 if (FSMIDDCacheDirty
&& FSMIDDCache
&& NotForRealOpt
== 0) {
33 if ((fo
= fopen(FSMIDDCache
, "w")) != NULL
) {
36 for (node
= FSMIDBase
; node
; node
= node
->fid_Next
) {
37 if (node
->fid_Accessed
&& node
->fid_Code
) {
38 fprintf(fo
, "%016jx %zu %s\n",
39 (intmax_t)node
->fid_Code
,
40 strlen(node
->fid_Name
),
54 while ((node
= FSMIDBase
) != NULL
) {
55 FSMIDBase
= node
->fid_Next
;
67 fsmid_cache(const char *dpath
, int ddirlen
)
77 ddirlen
== FSMIDDCacheDirLen
&&
78 strncmp(dpath
, FSMIDDCache
, ddirlen
) == 0
84 * Different cache, flush old cache
87 if (FSMIDDCache
!= NULL
)
94 FSMIDDCacheDirLen
= ddirlen
;
95 FSMIDDCache
= mprintf("%*.*s%s", ddirlen
, ddirlen
, dpath
, FSMIDCacheFile
);
97 if ((fi
= fopen(FSMIDDCache
, "r")) != NULL
) {
98 FSMIDNode
**pnode
= &FSMIDBase
;
103 FSMIDNode
*node
= *pnode
= malloc(sizeof(FSMIDNode
));
109 if (pnode
== NULL
|| node
== NULL
)
110 fatal("out of memory");
112 bzero(node
, sizeof(FSMIDNode
));
113 node
->fid_Code
= strtoull(fextract(fi
, -1, &c
, ' '), NULL
, 16);
114 node
->fid_Accessed
= 1;
115 if ((s
= fextract(fi
, -1, &c
, ' ')) != NULL
) {
116 nlen
= strtol(s
, NULL
, 0);
120 * extracting fid_Name - name may contain embedded control
123 CountSourceReadBytes
+= nlen
+1;
124 node
->fid_Name
= fextract(fi
, nlen
, &c
, EOF
);
126 fprintf(stderr
, "Error parsing FSMID Cache: %s (%c)\n", FSMIDDCache
, c
);
127 while (c
!= EOF
&& c
!= '\n')
132 pnode
= &node
->fid_Next
;
139 * fsmid_lookup: lookup/create fsmid entry
143 fsmid_lookup(const char *sfile
)
148 for (pnode
= &FSMIDBase
; (node
= *pnode
) != NULL
; pnode
= &node
->fid_Next
) {
149 if (strcmp(sfile
, node
->fid_Name
) == 0) {
154 if ((node
= *pnode
= malloc(sizeof(FSMIDNode
))) == NULL
)
155 fatal("out of memory");
156 bzero(node
, sizeof(FSMIDNode
));
157 node
->fid_Name
= strdup(sfile
);
158 FSMIDDCacheDirty
= 1;
160 node
->fid_Accessed
= 1;
165 * fsmid_check: check FSMID against file
167 * Return -1 if check failed
168 * Return 0 if check succeeded
170 * dpath can be NULL, in which case we are force-updating
174 fsmid_check(int64_t fsmid
, const char *dpath
)
180 if ((dfile
= strrchr(dpath
, '/')) != NULL
)
184 ddirlen
= dfile
- dpath
;
186 fsmid_cache(dpath
, ddirlen
);
188 node
= fsmid_lookup(dfile
);
190 if (node
->fid_Code
!= fsmid
) {
191 node
->fid_Code
= fsmid
;
192 FSMIDDCacheDirty
= 1;