1/* 2 Copyright (c) 2010 Frank Lahm <franklahm@gmail.com> 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13*/ 14 15#ifdef HAVE_CONFIG_H 16#include "config.h" 17#endif /* HAVE_CONFIG_H */ 18 19#include <string.h> 20#include <stdio.h> 21#include <stdlib.h> 22#include <errno.h> 23 24#include <atalk/util.h> 25#include <atalk/cnid.h> 26#include <atalk/logger.h> 27#include <atalk/volume.h> 28#include <atalk/directory.h> 29#include <atalk/queue.h> 30#include <atalk/bstrlib.h> 31#include <atalk/globals.h> 32 33#include "file.h" 34#include "filedir.h" 35#include "directory.h" 36#include "dircache.h" 37#include "hash.h" 38#include "afp_config.h" 39#include "volume.h" 40 41#include "test.h" 42#include "subtests.h" 43 44 45#define rbufsize 128000 46static char rbuf[rbufsize]; 47static size_t rbuflen; 48 49#define ADD(a, b, c) (a) += (c); \ 50 (b) += (c) 51 52#define PUSHBUF(p, val, size, len) \ 53 memcpy((p), (val), (size)); \ 54 (p) += (size); \ 55 (len) += (size) 56 57#define PUSHVAL(p, type, val, len) \ 58 { \ 59 type type = val; \ 60 memcpy(p, &type, sizeof(type)); \ 61 (p) += sizeof(type); \ 62 (len) += sizeof(type); \ 63 } 64 65static int push_path(char **bufp, const char *name) 66{ 67 int len = 0; 68 int slen = strlen(name); 69 char *p = *bufp; 70 71 PUSHVAL(p, uint8_t, 3, len); /* path type */ 72 PUSHVAL(p, uint32_t, kTextEncodingUTF8, len); /* text encoding hint */ 73 PUSHVAL(p, uint16_t, htons(slen), len); 74 if (slen) { 75 for (int i = 0; i < slen; i++) { 76 if (name[i] == '/') 77 p[i] = 0; 78 else 79 p[i] = name[i]; 80 } 81 len += slen; 82 } 83 84 *bufp += len; 85 return len; 86} 87 88/*********************************************************************************** 89 * Interface 90 ***********************************************************************************/ 91 92char **cnamewrap(const char *name) 93{ 94 static char buf[256]; 95 static char *p = buf; 96 int len = 0; 97 98 PUSHVAL(p, uint8_t, 3, len); /* path type */ 99 PUSHVAL(p, uint32_t, kTextEncodingUTF8, len); /* text encoding hint */ 100 PUSHVAL(p, uint16_t, ntohs(strlen(name)), len); 101 strcpy(p, name); 102 103 p = buf; 104 return &p; 105} 106 107int getfiledirparms(AFPObj *obj, uint16_t vid, cnid_t did, const char *name) 108{ 109 const int bufsize = 256; 110 char buf[bufsize]; 111 char *p = buf; 112 int len = 0; 113 114 ADD(p, len , 2); 115 116 PUSHVAL(p, uint16_t, vid, len); 117 PUSHVAL(p, cnid_t, did, len); 118 PUSHVAL(p, uint16_t, htons(FILPBIT_FNUM | FILPBIT_PDINFO), len); 119 PUSHVAL(p, uint16_t, htons(DIRPBIT_DID | DIRPBIT_PDINFO), len); 120 121 len += push_path(&p, name); 122 123 return afp_getfildirparams(obj, buf, len, rbuf, &rbuflen); 124} 125 126int createdir(AFPObj *obj, uint16_t vid, cnid_t did, const char *name) 127{ 128 const int bufsize = 256; 129 char buf[bufsize]; 130 char *p = buf; 131 int len = 0; 132 133 ADD(p, len , 2); 134 135 PUSHVAL(p, uint16_t, vid, len); 136 PUSHVAL(p, cnid_t, did, len); 137 len += push_path(&p, name); 138 139 return afp_createdir(obj, buf, len, rbuf, &rbuflen); 140} 141 142int createfile(AFPObj *obj, uint16_t vid, cnid_t did, const char *name) 143{ 144 const int bufsize = 256; 145 char buf[bufsize]; 146 char *p = buf; 147 int len = 0; 148 149 PUSHVAL(p, uint16_t, htons(128), len); /* hard create */ 150 PUSHVAL(p, uint16_t, vid, len); 151 PUSHVAL(p, cnid_t, did, len); 152 len += push_path(&p, name); 153 154 return afp_createfile(obj, buf, len, rbuf, &rbuflen); 155} 156 157int delete(AFPObj *obj, uint16_t vid, cnid_t did, const char *name) 158{ 159 const int bufsize = 256; 160 char buf[bufsize]; 161 char *p = buf; 162 int len = 0; 163 164 PUSHVAL(p, uint16_t, htons(128), len); /* hard create */ 165 PUSHVAL(p, uint16_t, vid, len); 166 PUSHVAL(p, cnid_t, did, len); 167 len += push_path(&p, name); 168 169 return afp_delete(obj, buf, len, rbuf, &rbuflen); 170} 171 172int enumerate(AFPObj *obj, uint16_t vid, cnid_t did) 173{ 174 const int bufsize = 256; 175 char buf[bufsize]; 176 char *p = buf; 177 int len = 0; 178 int ret; 179 180 ADD(p, len , 2); 181 182 PUSHVAL(p, uint16_t, vid, len); 183 PUSHVAL(p, cnid_t, did, len); 184 PUSHVAL(p, uint16_t, htons(FILPBIT_PDID | FILPBIT_FNUM | FILPBIT_PDINFO), len); 185 PUSHVAL(p, uint16_t, htons(DIRPBIT_PDID | DIRPBIT_DID | DIRPBIT_PDINFO), len); 186 PUSHVAL(p, uint16_t, htons(20), len); /* reqcount */ 187 PUSHVAL(p, uint32_t, htonl(1), len); /* startindex */ 188 PUSHVAL(p, uint32_t, htonl(rbufsize), len); /* max replysize */ 189 190 len += push_path(&p, ""); 191 192 ret = afp_enumerate_ext2(obj, buf, len, rbuf, &rbuflen); 193 194 if (ret != AFPERR_NOOBJ && ret != AFP_OK) 195 return -1; 196 return 0; 197} 198 199uint16_t openvol(AFPObj *obj, const char *name) 200{ 201 int ret; 202 uint16_t bitmap; 203 uint16_t vid; 204 const int bufsize = 32; 205 char buf[bufsize]; 206 char *p = buf; 207 char len = strlen(name); 208 209 memset(p, 0, bufsize); 210 p += 2; 211 212 /* bitmap */ 213 bitmap = htons(1<<VOLPBIT_VID); 214 memcpy(p, &bitmap, 2); 215 p += 2; 216 217 /* name */ 218 *p = len; 219 p++; 220 memcpy(p, name, len); 221 p += len; 222 223 len += 2 + 2 + 1; /* (command+pad) + bitmap + len */ 224 if (len & 1) 225 len++; 226 227 rbuflen = 0; 228 if ((ret = afp_openvol(obj, buf, len, rbuf, &rbuflen)) != AFP_OK) 229 return 0; 230 231 p = rbuf; 232 memcpy(&bitmap, p, 2); 233 p += 2; 234 bitmap = ntohs(bitmap); 235 if ( ! (bitmap & 1<<VOLPBIT_VID)) 236 return 0; 237 238 memcpy(&vid, p, 2); 239 return vid; 240} 241 242