1/* 2 * Copyright (C) Joerg Lenneis 2003 3 * Copyright (C) Frank Lahm 2010 4 * All Rights Reserved. See COPYING. 5 */ 6 7#ifdef HAVE_CONFIG_H 8#include "config.h" 9#endif /* HAVE_CONFIG_H */ 10 11#include <netatalk/endian.h> 12 13#include <string.h> 14#include <inttypes.h> 15#include <sys/param.h> 16#include <sys/cdefs.h> 17#include <db.h> 18 19#include <atalk/unicode.h> 20#include <atalk/volinfo.h> 21#include <atalk/logger.h> 22#include <atalk/cnid_dbd_private.h> 23#include "pack.h" 24 25/* in main.c for `cnid_dbd` or cmd_dbd.c for `dbd` */ 26extern struct volinfo volinfo; 27 28/* --------------- */ 29/* 30 * This implementation is portable, but could probably be faster by using htonl 31 * where appropriate. Also, this again doubles code from the cdb backend. 32 */ 33static void pack_devino(unsigned char *buf, dev_t dev, ino_t ino) 34{ 35 buf[CNID_DEV_LEN - 1] = dev; dev >>= 8; 36 buf[CNID_DEV_LEN - 2] = dev; dev >>= 8; 37 buf[CNID_DEV_LEN - 3] = dev; dev >>= 8; 38 buf[CNID_DEV_LEN - 4] = dev; dev >>= 8; 39 buf[CNID_DEV_LEN - 5] = dev; dev >>= 8; 40 buf[CNID_DEV_LEN - 6] = dev; dev >>= 8; 41 buf[CNID_DEV_LEN - 7] = dev; dev >>= 8; 42 buf[CNID_DEV_LEN - 8] = dev; 43 44 buf[CNID_DEV_LEN + CNID_INO_LEN - 1] = ino; ino >>= 8; 45 buf[CNID_DEV_LEN + CNID_INO_LEN - 2] = ino; ino >>= 8; 46 buf[CNID_DEV_LEN + CNID_INO_LEN - 3] = ino; ino >>= 8; 47 buf[CNID_DEV_LEN + CNID_INO_LEN - 4] = ino; ino >>= 8; 48 buf[CNID_DEV_LEN + CNID_INO_LEN - 5] = ino; ino >>= 8; 49 buf[CNID_DEV_LEN + CNID_INO_LEN - 6] = ino; ino >>= 8; 50 buf[CNID_DEV_LEN + CNID_INO_LEN - 7] = ino; ino >>= 8; 51 buf[CNID_DEV_LEN + CNID_INO_LEN - 8] = ino; 52} 53 54/* --------------- */ 55int didname(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) 56{ 57int len; 58 59 memset(skey, 0, sizeof(DBT)); 60 skey->data = (char *)pdata->data + CNID_DID_OFS; 61 /* FIXME: At least DB 4.0.14 and 4.1.25 pass in the correct length of 62 pdata.size. strlen is therefore not needed. Also, skey should be zeroed 63 out already. */ 64 len = strlen((char *)skey->data + CNID_DID_LEN); 65 skey->size = CNID_DID_LEN + len + 1; 66 return (0); 67} 68 69/* --------------- */ 70int devino(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) 71{ 72 memset(skey, 0, sizeof(DBT)); 73 skey->data = (char *)pdata->data + CNID_DEVINO_OFS; 74 skey->size = CNID_DEVINO_LEN; 75 return (0); 76} 77 78/* --------------- */ 79int idxname(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) 80{ 81 static char buffer[MAXPATHLEN +2]; 82 uint16_t flags = CONV_TOLOWER; 83 memset(skey, 0, sizeof(DBT)); 84 85 if (convert_charset(volinfo.v_volcharset, 86 volinfo.v_volcharset, 87 volinfo.v_maccharset, 88 (char *)pdata->data + CNID_NAME_OFS, 89 strlen((char *)pdata->data + CNID_NAME_OFS), 90 buffer, 91 MAXPATHLEN, 92 &flags) == (size_t)-1) { 93 LOG(log_error, logtype_cnid, "idxname: conversion error"); 94 } 95 96 skey->data = buffer; 97 skey->size = strlen(skey->data); 98 return (0); 99} 100 101/* The equivalent to make_cnid_data in the cnid library. Non re-entrant. We 102 differ from make_cnid_data in that we never return NULL, rqst->name cannot 103 ever cause start[] to overflow because name length is checked in libatalk. */ 104 105unsigned char *pack_cnid_data(struct cnid_dbd_rqst *rqst) 106{ 107 static unsigned char start[CNID_HEADER_LEN + MAXPATHLEN + 1]; 108 unsigned char *buf = start +CNID_LEN; 109 u_int32_t i; 110 111 pack_devino(buf, rqst->dev, rqst->ino); 112 buf += CNID_DEVINO_LEN; 113 114 i = htonl(rqst->type); 115 memcpy(buf, &i, sizeof(i)); 116 buf += sizeof(i); 117 118 /* did is already in network byte order */ 119 buf = memcpy(buf, &rqst->did, sizeof(rqst->did)); 120 buf += sizeof(rqst->did); 121 buf = memcpy(buf, rqst->name, rqst->namelen); 122 *(buf + rqst->namelen) = '\0'; 123 124 return start; 125} 126 127