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) {
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 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;