diff --git a/Makefile.am b/Makefile.am index f9ad239..d235089 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,7 +37,9 @@ src_libisofs_la_SOURCES = \ src/ecma119_tree.h \ src/ecma119_tree.c \ src/writer.h \ - src/buffer.c + src/buffer.c \ + src/rockridge.h \ + src/rockridge.c libinclude_HEADERS = \ src/libisofs.h diff --git a/src/rockridge.c b/src/rockridge.c new file mode 100644 index 0000000..e1b0c06 --- /dev/null +++ b/src/rockridge.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2007 Vreixo Formoso + * Copyright (c) 2007 Mario Danic + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ + +#include "rockridge.h" +#include "node.h" +#include "ecma119_tree.h" +#include "error.h" + +#include + +/** + * Compute the length needed for write all RR and SUSP entries for a given + * node. + * + * @param type + * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." + * for that node (i.e., it will refer to the parent) + * @param space + * Available space in the System Use Area for the directory record. + * @param ce + * Will be filled with the space needed in a CE + * @return + * The size needed for the RR entries in the System Use Area + */ +size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, + size_t space, size_t *ce) +{ + size_t su_size; + + /* space min is 255 - 33 - 37 = 185 */ + + /* PX and TF, we are sure they always fit in SUA */ + su_size = 44 + 26; + + if (n->type == ECMA119_DIR) { + if (n->info.dir.real_parent != NULL) { + /* it is a reallocated entry */ + if (type == 2) { + /* we need to add a PL entry */ + su_size += 12; + } else if (type == 0) { + /* we need to add a RE entry */ + su_size += 4; + } + } + } else if (n->type == ECMA119_SPECIAL) { + if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) { + /* block or char device, we need a PN entry */ + su_size += 20; + } + } else if (n->type == ECMA119_PLACEHOLDER) { + /* we need the CL entry */ + su_size += 12; + } + + if (type == 0) { + size_t namelen = strlen(n->node->name); + + /* NM entry */ + if (su_size + 5 + namelen <= space) { + /* ok, it fits in System Use Area */ + su_size += 5 + namelen; + } else { + /* the NM will be divided in a CE */ + namelen = namelen - (space - su_size - 5 - 28); + *ce = 5 + namelen; + su_size = space; + } + if (n->type == ECMA119_SYMLINK) { + /* + * for symlinks, we also need to write the SL + */ + char *cur, *prev; + size_t sl_len = 5; + int cew = (*ce != 0); /* are we writing to CE? */ + + prev = ((IsoSymlink*)n->node)->dest; + cur = strchr(prev, '/'); + while (1) { + size_t clen; + if (cur) { + clen = cur - prev; + } else { + /* last component */ + clen = strlen(prev); + } + + if (clen == 1 && prev[0] == '.') { + clen = 0; + } else if (clen == 2 && prev[0] == '.' && prev[1] == '.') { + clen = 0; + } + + /* flags and len for each component record (RRIP, 4.1.3.1) */ + clen += 2; + + if (!cew) { + /* we are still writing to the SUA */ + if (su_size + sl_len + clen > space) { + /* + * ok, we need a Continuation Area anyway + * TODO this can be handled better, but for now SL + * will be completelly moved into the CA + */ + if (su_size + 28 <= space) { + /* the CE entry fills without reducing NM */ + su_size += 28; + cew = 1; + } else { + /* we need to reduce NM */ + *ce = (28 - (space - su_size)) + 5; + su_size = space; + cew = 1; + } + } + } else { + if (sl_len + clen > 255) { + /* we need an addition SL entry */ + if (clen > 250) { + /* + * case 1, component too large to fit in a + * single SL entry. Thus, the component need + * to be divided anyway. + * Note than clen can be up to 255 + 2 = 257. + * + * First, we check how many bytes fit in current + * SL field + */ + int fit = 255 - sl_len - 2; + if (clen - 250 <= fit) { + /* + * the component can be divided between this + * and another SL entry + */ + *ce += 255; /* this SL, full */ + sl_len = 5 + (clen - fit); + } else { + /* + * the component will need a 2rd SL entry in + * any case, so we prefer to don't write + * anything in this SL + */ + *ce += sl_len + 255; + sl_len = 5 + (clen - 250); + } + } else { + /* case 2, create a new SL entry */ + *ce += sl_len; + sl_len = 5 + clen; + } + } else { + sl_len += clen; + } + } + + if (!cur || cur[1] == '\0') { + /* cur[1] can be \0 if dest ends with '/' */ + break; + } + prev = cur + 1; + cur = strchr(prev, '/'); + } + + /* and finally write the pending SL field */ + if (!cew) { + /* the whole SL fits into the SUA */ + su_size += sl_len; + } else { + *ce += sl_len; + } + + } + } else { + + /* "." or ".." entry */ + su_size += 5; /* NM field */ + if (type == 1 && n->parent == NULL) { + /* + * "." for root directory + * we need to write SP and ER entries. The first fits in SUA, + * ER needs a Continuation Area, thus we also need a CE entry + */ + su_size += 7 + 28; /* SP + CE */ + *ce = 182; /* ER */ + } + } + + return su_size; +} + + + + diff --git a/src/rockridge.h b/src/rockridge.h new file mode 100644 index 0000000..ca00d6e --- /dev/null +++ b/src/rockridge.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007 Vreixo Formoso + * Copyright (c) 2007 Mario Danic + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ + +/** + * Functions and structures used for Rock Ridge support. + * + * See IEEE P1282, Rock Ridge Interchange Protocol, Draft Standard version + * 1.12 for further details. + */ + +#ifndef LIBISO_ROCKRIDGE_H +#define LIBISO_ROCKRIDGE_H + +#include "ecma119.h" + +/** + * Compute the length needed for write all RR and SUSP entries for a given + * node. + * + * @param type + * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." + * for that node (i.e., it will refer to the parent) + * @param space + * Available space in the System Use Area for the directory record. + * @param ce + * Will be filled with the space needed in a CE + * @return + * The size needed for the RR entries in the System Use Area + */ +size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, + size_t space, size_t *ce); + +#endif /* LIBISO_ROCKRIDGE_H */