source: subversion/applications/utils/mod_tile/dir_utils.c @ 29196

Last change on this file since 29196 was 28629, checked in by Dirk Stoecker, 7 years ago

typo

File size: 4.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <limits.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <errno.h>
9
10#include "protocol.h"
11#include "render_config.h"
12#include "dir_utils.h"
13
14// Build parent directories for the specified file name
15// Note: the part following the trailing / is ignored
16// e.g. mkdirp("/a/b/foo.png") == shell mkdir -p /a/b
17int mkdirp(const char *path) {
18    struct stat s;
19    char tmp[PATH_MAX];
20    char *p;
21
22    strncpy(tmp, path, sizeof(tmp));
23
24    // Look for parent directory
25    p = strrchr(tmp, '/');
26    if (!p)
27        return 0;
28
29    *p = '\0';
30
31    if (!stat(tmp, &s))
32        return !S_ISDIR(s.st_mode);
33    *p = '/';
34    // Walk up the path making sure each element is a directory
35    p = tmp;
36    if (!*p)
37        return 0;
38    p++; // Ignore leading /
39    while (*p) {
40        if (*p == '/') {
41            *p = '\0';
42            if (!stat(tmp, &s)) {
43                if (!S_ISDIR(s.st_mode)) {
44                    fprintf(stderr, "Error, is not a directory: %s\n", tmp);
45                    return 1;
46                }
47            } else if (mkdir(tmp, 0777)) {
48                    // Ignore multiple threads attempting to create the same directory
49                    if (errno != EEXIST) { 
50                       perror(tmp);
51                       return 1;
52                    }
53                }
54            *p = '/';
55        }
56        p++;
57    }
58    return 0;
59}
60
61
62
63/* File path hashing. Used by both mod_tile and render daemon
64 * The two must both agree on the file layout for meta-tiling
65 * to work
66 */
67
68void xyz_to_path(char *path, size_t len, const char *tile_dir, const char *xmlconfig, int x, int y, int z)
69{
70#ifdef DIRECTORY_HASH
71    // We attempt to cluster the tiles so that a 16x16 square of tiles will be in a single directory
72    // Hash stores our 40 bit result of mixing the 20 bits of the x & y co-ordinates
73    // 4 bits of x & y are used per byte of output
74    unsigned char i, hash[5];
75
76    for (i=0; i<5; i++) {
77        hash[i] = ((x & 0x0f) << 4) | (y & 0x0f);
78        x >>= 4;
79        y >>= 4;
80    }
81    snprintf(path, len, "%s/%s/%d/%u/%u/%u/%u/%u.png", tile_dir, xmlconfig, z, hash[4], hash[3], hash[2], hash[1], hash[0]);
82#else
83    snprintf(path, len, TILE_PATH "/%s/%d/%d/%d.png", xmlconfig, z, x, y);
84#endif
85    return;
86}
87
88int check_xyz(int x, int y, int z)
89{
90    int oob, limit;
91
92    // Validate tile co-ordinates
93    oob = (z < 0 || z > MAX_ZOOM);
94    if (!oob) {
95         // valid x/y for tiles are 0 ... 2^zoom-1
96        limit = (1 << z) - 1;
97        oob =  (x < 0 || x > limit || y < 0 || y > limit);
98    }
99
100    if (oob)
101        fprintf(stderr, "got bad co-ords: x(%d) y(%d) z(%d)\n", x, y, z);
102
103    return oob;
104}
105
106
107int path_to_xyz(const char *tilepath, const char *path, char *xmlconfig, int *px, int *py, int *pz)
108{
109#ifdef DIRECTORY_HASH
110    int i, n, hash[5], x, y, z;
111    for(i = 0; tilepath[i] && tilepath[i] == path[i]; ++i)
112        ;
113    if(tilepath[i]) {
114        fprintf(stderr, "Tile path does not match settings (%s): %s\n", tilepath, path);
115        return 1;
116    }
117
118    n = sscanf(path+i, "/%40[^/]/%d/%d/%d/%d/%d/%d", xmlconfig, pz, &hash[0], &hash[1], &hash[2], &hash[3], &hash[4]);
119    if (n != 7) {
120        fprintf(stderr, "Failed to parse tile path: %s\n", path);
121        return 1;
122    } else {
123        x = y = 0;
124        for (i=0; i<5; i++) {
125            if (hash[i] < 0 || hash[i] > 255) {
126                fprintf(stderr, "Failed to parse tile path (invalid %d): %s\n", hash[i], path);
127                return 2;
128            }
129            x <<= 4;
130            y <<= 4;
131            x |= (hash[i] & 0xf0) >> 4;
132            y |= (hash[i] & 0x0f);
133        }
134        z = *pz;
135        *px = x;
136        *py = y;
137        return check_xyz(x, y, z);
138    }
139#else
140    int n;
141    n = sscanf(path, TILE_PATH "/%40[^/]/%d/%d/%d", xmlconfig, pz, px, py);
142    if (n != 4) {
143        fprintf(stderr, "Failed to parse tile path: %s\n", path);
144        return 1;
145    } else {
146        return check_xyz(*px, *py, *pz);
147    }
148#endif
149}
150
151#ifdef METATILE
152// Returns the path to the meta-tile and the offset within the meta-tile
153int xyz_to_meta(char *path, size_t len, const char *tile_dir, const char *xmlconfig, int x, int y, int z)
154{
155    unsigned char i, hash[5], offset, mask;
156
157    // Each meta tile winds up in its own file, with several in each leaf directory
158    // the .meta tile name is beasd on the sub-tile at (0,0)
159    mask = METATILE - 1;
160    offset = (x & mask) * METATILE + (y & mask);
161    x &= ~mask;
162    y &= ~mask;
163
164    for (i=0; i<5; i++) {
165        hash[i] = ((x & 0x0f) << 4) | (y & 0x0f);
166        x >>= 4;
167        y >>= 4;
168    }
169#ifdef DIRECTORY_HASH
170    snprintf(path, len, "%s/%s/%d/%u/%u/%u/%u/%u.meta", tile_dir, xmlconfig, z, hash[4], hash[3], hash[2], hash[1], hash[0]);
171#else
172    snprintf(path, len, "%s/%s/%d/%u/%u.meta", tile_dir, xmlconfig, z, x, y);
173#endif
174    return offset;
175}
176#endif
Note: See TracBrowser for help on using the repository browser.