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.2 2008/03/22 18:09:16 dillon 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
) {
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
, "%016llx %d %s\n",
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 fprintf(stderr
, "out of memory\n");
114 bzero(node
, sizeof(FSMIDNode
));
115 node
->fid_Code
= strtoull(fextract(fi
, -1, &c
, ' '), NULL
, 16);
116 node
->fid_Accessed
= 1;
117 if ((s
= fextract(fi
, -1, &c
, ' ')) != NULL
) {
118 nlen
= strtol(s
, NULL
, 0);
122 * extracting fid_Name - name may contain embedded control
125 CountSourceReadBytes
+= nlen
+1;
126 node
->fid_Name
= fextract(fi
, nlen
, &c
, EOF
);
128 fprintf(stderr
, "Error parsing FSMID Cache: %s (%c)\n", FSMIDDCache
, c
);
129 while (c
!= EOF
&& c
!= '\n')
134 pnode
= &node
->fid_Next
;
141 * fsmid_lookup: lookup/create fsmid entry
145 fsmid_lookup(const char *sfile
)
150 for (pnode
= &FSMIDBase
; (node
= *pnode
) != NULL
; pnode
= &node
->fid_Next
) {
151 if (strcmp(sfile
, node
->fid_Name
) == 0) {
156 if ((node
= *pnode
= malloc(sizeof(FSMIDNode
))) == NULL
) {
157 fprintf(stderr
,"out of memory\n");
160 bzero(node
, sizeof(FSMIDNode
));
161 node
->fid_Name
= strdup(sfile
);
162 FSMIDDCacheDirty
= 1;
164 node
->fid_Accessed
= 1;
169 * fsmid_check: check FSMID against file
171 * Return -1 if check failed
172 * Return 0 if check succeeded
174 * dpath can be NULL, in which case we are force-updating
178 fsmid_check(int64_t fsmid
, const char *dpath
)
187 if ((dfile
= strrchr(dpath
, '/')) != NULL
)
191 ddirlen
= dfile
- dpath
;
193 fsmid_cache(dpath
, ddirlen
);
195 node
= fsmid_lookup(dfile
);
197 if (node
->fid_Code
!= fsmid
) {
198 node
->fid_Code
= fsmid
;
199 FSMIDDCacheDirty
= 1;