hammer2 - update documentation, cleanup
[dragonfly.git] / bin / cpdup / fsmid.c
blob405d34c603f6202e1f10bd368fffd42f5ac9418d
1 /*-
2 * FSMID.C
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 $
8 */
10 #include "cpdup.h"
12 typedef struct FSMIDNode {
13 struct FSMIDNode *fid_Next;
14 char *fid_Name;
15 int64_t fid_Code;
16 int fid_Accessed;
17 } FSMIDNode;
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;
27 void
28 fsmid_flush(void)
30 if (FSMIDDCacheDirty && FSMIDDCache && NotForRealOpt == 0) {
31 FILE *fo;
33 if ((fo = fopen(FSMIDDCache, "w")) != NULL) {
34 FSMIDNode *node;
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),
41 node->fid_Name
45 fclose(fo);
49 FSMIDDCacheDirty = 0;
51 if (FSMIDDCache) {
52 FSMIDNode *node;
54 while ((node = FSMIDBase) != NULL) {
55 FSMIDBase = node->fid_Next;
57 if (node->fid_Name)
58 free(node->fid_Name);
59 free(node);
61 free(FSMIDDCache);
62 FSMIDDCache = NULL;
66 static void
67 fsmid_cache(const char *dpath, int ddirlen)
69 FILE *fi;
72 * Already cached
75 if (
76 FSMIDDCache &&
77 ddirlen == FSMIDDCacheDirLen &&
78 strncmp(dpath, FSMIDDCache, ddirlen) == 0
79 ) {
80 return;
84 * Different cache, flush old cache
87 if (FSMIDDCache != NULL)
88 fsmid_flush();
91 * Create new cache
94 FSMIDDCacheDirLen = ddirlen;
95 FSMIDDCache = mprintf("%*.*s%s", ddirlen, ddirlen, dpath, FSMIDCacheFile);
97 if ((fi = fopen(FSMIDDCache, "r")) != NULL) {
98 FSMIDNode **pnode = &FSMIDBase;
99 int c;
101 c = fgetc(fi);
102 while (c != EOF) {
103 FSMIDNode *node = *pnode = malloc(sizeof(FSMIDNode));
104 char *s;
105 int nlen;
107 nlen = 0;
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);
117 free(s);
120 * extracting fid_Name - name may contain embedded control
121 * characters.
123 CountSourceReadBytes += nlen+1;
124 node->fid_Name = fextract(fi, nlen, &c, EOF);
125 if (c != '\n') {
126 fprintf(stderr, "Error parsing FSMID Cache: %s (%c)\n", FSMIDDCache, c);
127 while (c != EOF && c != '\n')
128 c = fgetc(fi);
130 if (c != EOF)
131 c = fgetc(fi);
132 pnode = &node->fid_Next;
134 fclose(fi);
139 * fsmid_lookup: lookup/create fsmid entry
142 static FSMIDNode *
143 fsmid_lookup(const char *sfile)
145 FSMIDNode **pnode;
146 FSMIDNode *node;
148 for (pnode = &FSMIDBase; (node = *pnode) != NULL; pnode = &node->fid_Next) {
149 if (strcmp(sfile, node->fid_Name) == 0) {
150 break;
153 if (node == NULL) {
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;
161 return(node);
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
171 * the source FSMID.
174 fsmid_check(int64_t fsmid, const char *dpath)
176 const char *dfile;
177 int ddirlen;
178 FSMIDNode *node;
180 if ((dfile = strrchr(dpath, '/')) != NULL)
181 ++dfile;
182 else
183 dfile = dpath;
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;
193 return(1);
195 return(0);