HAMMER 60I/Many: Mirroring
[dragonfly.git] / bin / cpdup / fsmid.c
blob40071cc6ec44b626bfb49e090733d004f8a32238
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.2 2008/03/22 18:09:16 dillon 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) {
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, "%016llx %d %s\n",
39 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 fprintf(stderr, "out of memory\n");
111 exit(EXIT_FAILURE);
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);
119 free(s);
122 * extracting fid_Name - name may contain embedded control
123 * characters.
125 CountSourceReadBytes += nlen+1;
126 node->fid_Name = fextract(fi, nlen, &c, EOF);
127 if (c != '\n') {
128 fprintf(stderr, "Error parsing FSMID Cache: %s (%c)\n", FSMIDDCache, c);
129 while (c != EOF && c != '\n')
130 c = fgetc(fi);
132 if (c != EOF)
133 c = fgetc(fi);
134 pnode = &node->fid_Next;
136 fclose(fi);
141 * fsmid_lookup: lookup/create fsmid entry
144 static FSMIDNode *
145 fsmid_lookup(const char *sfile)
147 FSMIDNode **pnode;
148 FSMIDNode *node;
150 for (pnode = &FSMIDBase; (node = *pnode) != NULL; pnode = &node->fid_Next) {
151 if (strcmp(sfile, node->fid_Name) == 0) {
152 break;
155 if (node == NULL) {
156 if ((node = *pnode = malloc(sizeof(FSMIDNode))) == NULL) {
157 fprintf(stderr,"out of memory\n");
158 exit(EXIT_FAILURE);
160 bzero(node, sizeof(FSMIDNode));
161 node->fid_Name = strdup(sfile);
162 FSMIDDCacheDirty = 1;
164 node->fid_Accessed = 1;
165 return(node);
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
175 * the source FSMID.
178 fsmid_check(int64_t fsmid, const char *dpath)
180 const char *dfile;
181 int ddirlen;
182 int r;
183 FSMIDNode *node;
185 r = -1;
187 if ((dfile = strrchr(dpath, '/')) != NULL)
188 ++dfile;
189 else
190 dfile = dpath;
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;
200 return(1);
202 return(0);