| Index: embios/trunk/global.h |
| — | — | @@ -28,7 +28,9 @@ |
| 29 | 29 | #include <stdint.h>
|
| 30 | 30 | #include <stddef.h>
|
| 31 | 31 | #include <stdbool.h>
|
| 32 | | -#include <stdio.h>
|
| | 32 | +typedef int32_t ssize_t;
|
| | 33 | +typedef int32_t mode_t;
|
| | 34 | +typedef int32_t off_t;
|
| 33 | 35 | #endif
|
| 34 | 36 |
|
| 35 | 37 | #include "build/version.h"
|
| Index: embios/trunk/fat.c |
| — | — | @@ -20,13 +20,12 @@ |
| 21 | 21 | ****************************************************************************/ |
| 22 | 22 | #include "global.h" |
| 23 | 23 | #include "thread.h" |
| 24 | | -#include <stdio.h> |
| 25 | 24 | #include <string.h> |
| 26 | | -#include <ctype.h> |
| 27 | 25 | #include "fat.h" |
| 28 | 26 | #include "storage.h" |
| 29 | 27 | #include "debug.h" |
| 30 | 28 | #include "panic.h" |
| | 29 | +#include "snprintf.h" |
| 31 | 30 | |
| 32 | 31 | #define BYTES2INT16(array,pos) \ |
| 33 | 32 | (array[pos] | (array[pos+1] << 8 )) |
| Index: embios/trunk/dir.c |
| — | — | @@ -1,337 +1,336 @@ |
| 2 | | -/*************************************************************************** |
| 3 | | - * __________ __ ___. |
| 4 | | - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 5 | | - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 6 | | - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 7 | | - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 8 | | - * \/ \/ \/ \/ \/ |
| 9 | | - * $Id: dir.c 13741 2007-06-30 02:08:27Z jethead71 $ |
| 10 | | - * |
| 11 | | - * Copyright (C) 2002 by Björn Stenberg |
| 12 | | - * |
| 13 | | - * This program is free software; you can redistribute it and/or |
| 14 | | - * modify it under the terms of the GNU General Public License |
| 15 | | - * as published by the Free Software Foundation; either version 2 |
| 16 | | - * of the License, or (at your option) any later version. |
| 17 | | - * |
| 18 | | - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 19 | | - * KIND, either express or implied. |
| 20 | | - * |
| 21 | | - ****************************************************************************/ |
| 22 | | -#include "global.h" |
| 23 | | -#include <stdio.h> |
| 24 | | -#include <errno.h> |
| 25 | | -#include <string.h> |
| 26 | | -#include "fat.h" |
| 27 | | -#include "dir.h" |
| 28 | | -#include "debug.h" |
| 29 | | - |
| 30 | | -#ifndef MAX_OPEN_DIRS |
| 31 | | -#define MAX_OPEN_DIRS 16 |
| 32 | | -#endif |
| 33 | | - |
| | 2 | +/***************************************************************************
|
| | 3 | + * __________ __ ___.
|
| | 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| | 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| | 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| | 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| | 8 | + * \/ \/ \/ \/ \/
|
| | 9 | + * $Id: dir.c 13741 2007-06-30 02:08:27Z jethead71 $
|
| | 10 | + *
|
| | 11 | + * Copyright (C) 2002 by Björn Stenberg
|
| | 12 | + *
|
| | 13 | + * This program is free software; you can redistribute it and/or
|
| | 14 | + * modify it under the terms of the GNU General Public License
|
| | 15 | + * as published by the Free Software Foundation; either version 2
|
| | 16 | + * of the License, or (at your option) any later version.
|
| | 17 | + *
|
| | 18 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| | 19 | + * KIND, either express or implied.
|
| | 20 | + *
|
| | 21 | + ****************************************************************************/
|
| | 22 | +#include "global.h"
|
| | 23 | +#include <errno.h>
|
| | 24 | +#include <string.h>
|
| | 25 | +#include "fat.h"
|
| | 26 | +#include "dir.h"
|
| | 27 | +#include "debug.h"
|
| | 28 | +
|
| | 29 | +#ifndef MAX_OPEN_DIRS
|
| | 30 | +#define MAX_OPEN_DIRS 16
|
| | 31 | +#endif
|
| | 32 | +
|
| 34 | 33 | extern struct scheduler_thread* current_thread;
|
| 35 | | -static DIR opendirs[MAX_OPEN_DIRS]; |
| 36 | | - |
| 37 | | -#ifdef HAVE_HOTSWAP |
| 38 | | -// release all dir handles on a given volume "by force", to avoid leaks |
| 39 | | -int release_dirs(int volume) |
| 40 | | -{ |
| 41 | | - DIR* pdir = opendirs; |
| 42 | | - int dd; |
| 43 | | - int closed = 0; |
| 44 | | - for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++) |
| 45 | | - { |
| 46 | | -#ifdef HAVE_MULTIVOLUME |
| 47 | | - if (pdir->fatdir.file.volume == volume) |
| 48 | | -#else |
| 49 | | - (void)volume; |
| 50 | | -#endif |
| 51 | | - { |
| 52 | | - pdir->busy = false; /* mark as available, no further action */ |
| 53 | | - closed++; |
| 54 | | - } |
| 55 | | - } |
| 56 | | - return closed; /* return how many we did */ |
| 57 | | -} |
| 58 | | -#endif /* #ifdef HAVE_HOTSWAP */ |
| 59 | | - |
| 60 | | -DIR* opendir(const char* name) |
| 61 | | -{ |
| 62 | | - char namecopy[MAX_PATH]; |
| 63 | | - char* part; |
| 64 | | - char* end; |
| 65 | | - struct fat_direntry entry; |
| 66 | | - int dd; |
| 67 | | - DIR* pdir = opendirs; |
| 68 | | -#ifdef HAVE_MULTIVOLUME |
| 69 | | - int volume; |
| 70 | | -#endif |
| 71 | | - |
| 72 | | - if ( name[0] != '/' ) { |
| 73 | | - DEBUGF("Only absolute paths supported right now"); |
| 74 | | - return NULL; |
| 75 | | - } |
| 76 | | - |
| 77 | | - /* find a free dir descriptor */ |
| 78 | | - for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++) |
| 79 | | - if ( !pdir->busy ) |
| 80 | | - break; |
| 81 | | - |
| 82 | | - if ( dd == MAX_OPEN_DIRS ) { |
| 83 | | - DEBUGF("Too many dirs open"); |
| 84 | | - errno = EMFILE; |
| 85 | | - return NULL; |
| 86 | | - } |
| 87 | | - |
| 88 | | - pdir->busy = true; |
| 89 | | - pdir->process = current_thread; |
| 90 | | - |
| 91 | | -#ifdef HAVE_MULTIVOLUME |
| 92 | | - /* try to extract a heading volume name, if present */ |
| 93 | | - volume = strip_volume(name, namecopy); |
| 94 | | - pdir->volumecounter = 0; |
| 95 | | -#else |
| 96 | | - strlcpy(namecopy, name, sizeof(namecopy)); /* just copy */ |
| 97 | | -#endif |
| 98 | | - |
| 99 | | - if ( fat_opendir(IF_MV2(volume,) &pdir->fatdir, 0, NULL) < 0 ) { |
| 100 | | - DEBUGF("Failed opening root dir"); |
| 101 | | - pdir->busy = false; |
| 102 | | - return NULL; |
| 103 | | - } |
| 104 | | - |
| 105 | | - for ( part = strtok_r(namecopy, "/", &end); part; |
| 106 | | - part = strtok_r(NULL, "/", &end)) { |
| 107 | | - /* scan dir for name */ |
| 108 | | - while (1) { |
| 109 | | - if ((fat_getnext(&pdir->fatdir,&entry) < 0) || |
| 110 | | - (!entry.name[0])) { |
| 111 | | - pdir->busy = false; |
| 112 | | - return NULL; |
| 113 | | - } |
| 114 | | - if ( (entry.attr & FAT_ATTR_DIRECTORY) && |
| 115 | | - (!strcasecmp(part, entry.name)) ) { |
| 116 | | - /* In reality, the parent_dir parameter of fat_opendir seems |
| 117 | | - * useless because it's sole purpose it to have a way to |
| 118 | | - * update the file metadata, but here we are only reading |
| 119 | | - * a directory so there's no need for that kind of stuff. |
| 120 | | - * However, the rmdir function uses a ugly hack to |
| 121 | | - * avoid opening a directory twice when deleting it and thus |
| 122 | | - * needs those information. That's why we pass pdir->fatdir both |
| 123 | | - * as the parent directory and the resulting one (this is safe, |
| 124 | | - * in doubt, check fat_open(dir) code) which will allow this kind of |
| 125 | | - * (ugly) things */ |
| 126 | | - if ( fat_opendir(IF_MV2(volume,) |
| 127 | | - &pdir->fatdir, |
| 128 | | - entry.firstcluster, |
| 129 | | - &pdir->fatdir) < 0 ) { |
| 130 | | - DEBUGF("Failed opening dir '%s' (%ld)", |
| 131 | | - part, entry.firstcluster); |
| 132 | | - pdir->busy = false; |
| 133 | | - return NULL; |
| 134 | | - } |
| 135 | | -#ifdef HAVE_MULTIVOLUME |
| 136 | | - pdir->volumecounter = -1; /* n.a. to subdirs */ |
| 137 | | -#endif |
| 138 | | - break; |
| 139 | | - } |
| 140 | | - } |
| 141 | | - } |
| 142 | | - |
| 143 | | - return pdir; |
| 144 | | -} |
| 145 | | - |
| 146 | | -int closedir(DIR* dir) |
| 147 | | -{ |
| 148 | | - dir->busy=false; |
| 149 | | - return 0; |
| 150 | | -} |
| 151 | | - |
| 152 | | -int closedir_all_of_process(struct scheduler_thread* process) |
| 153 | | -{ |
| 154 | | - DIR* pdir = opendirs; |
| 155 | | - int dd; |
| 156 | | - int closed = 0; |
| 157 | | - for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++) |
| 158 | | - { |
| 159 | | - if (pdir->process == process) |
| 160 | | - { |
| 161 | | - pdir->busy = false; /* mark as available, no further action */ |
| 162 | | - closed++; |
| 163 | | - } |
| 164 | | - } |
| 165 | | - return closed; /* return how many we did */ |
| 166 | | -} |
| 167 | | - |
| 168 | | -struct dirent* readdir(DIR* dir) |
| 169 | | -{ |
| 170 | | - struct fat_direntry entry; |
| 171 | | - struct dirent* theent = &(dir->theent); |
| 172 | | - |
| 173 | | - if (!dir->busy) |
| 174 | | - return NULL; |
| 175 | | - |
| 176 | | -#ifdef HAVE_MULTIVOLUME |
| 177 | | - /* Volumes (secondary file systems) get inserted into the root directory |
| 178 | | - of the first volume, since we have no separate top level. */ |
| 179 | | - if (dir->volumecounter >= 0 /* on a root dir */ |
| 180 | | - && dir->volumecounter < NUM_VOLUMES /* in range */ |
| 181 | | - && dir->fatdir.file.volume == 0) /* at volume 0 */ |
| 182 | | - { /* fake special directories, which don't really exist, but |
| 183 | | - will get redirected upon opendir() */ |
| 184 | | - while (++dir->volumecounter < NUM_VOLUMES) |
| 185 | | - { |
| 186 | | - if (fat_ismounted(dir->volumecounter)) |
| 187 | | - { |
| 188 | | - memset(theent, 0, sizeof(*theent)); |
| 189 | | - theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; |
| 190 | | - snprintf(theent->d_name, sizeof(theent->d_name), |
| 191 | | - VOL_NAMES, dir->volumecounter); |
| 192 | | - return theent; |
| 193 | | - } |
| 194 | | - } |
| 195 | | - } |
| 196 | | -#endif |
| 197 | | - /* normal directory entry fetching follows here */ |
| 198 | | - if (fat_getnext(&(dir->fatdir),&entry) < 0) |
| 199 | | - return NULL; |
| 200 | | - |
| 201 | | - if ( !entry.name[0] ) |
| 202 | | - return NULL; |
| 203 | | - |
| 204 | | - strlcpy(theent->d_name, entry.name, sizeof(theent->d_name)); |
| 205 | | - theent->attribute = entry.attr; |
| 206 | | - theent->size = entry.filesize; |
| 207 | | - theent->startcluster = entry.firstcluster; |
| 208 | | - theent->wrtdate = entry.wrtdate; |
| 209 | | - theent->wrttime = entry.wrttime; |
| 210 | | - |
| 211 | | - return theent; |
| 212 | | -} |
| 213 | | - |
| 214 | | -int mkdir(const char *name) |
| 215 | | -{ |
| 216 | | - DIR *dir; |
| 217 | | - char namecopy[MAX_PATH]; |
| 218 | | - char* end; |
| 219 | | - char *basename; |
| 220 | | - char *parent; |
| 221 | | - struct dirent *entry; |
| 222 | | - struct fat_dir newdir; |
| 223 | | - int rc; |
| 224 | | - |
| 225 | | - if ( name[0] != '/' ) { |
| 226 | | - DEBUGF("mkdir: Only absolute paths supported right now"); |
| 227 | | - return -1; |
| 228 | | - } |
| 229 | | - |
| 230 | | - strlcpy(namecopy, name, sizeof(namecopy)); |
| 231 | | - |
| 232 | | - /* Split the base name and the path */ |
| 233 | | - end = strrchr(namecopy, '/'); |
| 234 | | - *end = 0; |
| 235 | | - basename = end+1; |
| 236 | | - |
| 237 | | - if(namecopy == end) /* Root dir? */ |
| 238 | | - parent = "/"; |
| 239 | | - else |
| 240 | | - parent = namecopy; |
| 241 | | - |
| 242 | | - DEBUGF("mkdir: parent: %s, name: %s", parent, basename); |
| 243 | | - |
| 244 | | - dir = opendir(parent); |
| 245 | | - |
| 246 | | - if(!dir) { |
| 247 | | - DEBUGF("mkdir: can't open parent dir"); |
| 248 | | - return -2; |
| 249 | | - } |
| 250 | | - |
| 251 | | - if(basename[0] == 0) { |
| 252 | | - DEBUGF("mkdir: Empty dir name"); |
| 253 | | - errno = EINVAL; |
| 254 | | - return -3; |
| 255 | | - } |
| 256 | | - |
| 257 | | - /* Now check if the name already exists */ |
| 258 | | - while ((entry = readdir(dir))) { |
| 259 | | - if ( !strcasecmp(basename, entry->d_name) ) { |
| 260 | | - DEBUGF("mkdir error: file exists"); |
| 261 | | - errno = EEXIST; |
| 262 | | - closedir(dir); |
| 263 | | - return - 4; |
| 264 | | - } |
| 265 | | - } |
| 266 | | - |
| 267 | | - memset(&newdir, 0, sizeof(struct fat_dir)); |
| 268 | | - |
| 269 | | - rc = fat_create_dir(basename, &newdir, &(dir->fatdir)); |
| 270 | | - closedir(dir); |
| 271 | | - |
| 272 | | - return rc; |
| 273 | | -} |
| 274 | | - |
| 275 | | -int rmdir(const char* name) |
| 276 | | -{ |
| 277 | | - int rc; |
| 278 | | - DIR* dir; |
| 279 | | - struct dirent* entry; |
| 280 | | - |
| 281 | | - dir = opendir(name); |
| 282 | | - if (!dir) |
| 283 | | - { |
| 284 | | - errno = ENOENT; /* open error */ |
| 285 | | - return -1; |
| 286 | | - } |
| 287 | | - |
| 288 | | - /* check if the directory is empty */ |
| 289 | | - while ((entry = readdir(dir))) |
| 290 | | - { |
| 291 | | - if (strcmp(entry->d_name, ".") && |
| 292 | | - strcmp(entry->d_name, "..")) |
| 293 | | - { |
| 294 | | - DEBUGF("rmdir error: not empty"); |
| 295 | | - errno = ENOTEMPTY; |
| 296 | | - closedir(dir); |
| 297 | | - return -2; |
| 298 | | - } |
| 299 | | - } |
| 300 | | - |
| 301 | | - rc = fat_remove(&(dir->fatdir.file)); |
| 302 | | - if ( rc < 0 ) { |
| 303 | | - DEBUGF("Failed removing dir: %d", rc); |
| 304 | | - errno = EIO; |
| 305 | | - rc = rc * 10 - 3; |
| 306 | | - } |
| 307 | | - |
| 308 | | - closedir(dir); |
| 309 | | - return rc; |
| 310 | | -} |
| 311 | | - |
| 312 | | -#ifdef HAVE_MULTIVOLUME |
| 313 | | -/* returns on which volume this is, and copies the reduced name |
| 314 | | - (sortof a preprocessor for volume-decorated pathnames) */ |
| 315 | | -int strip_volume(const char* name, char* namecopy) |
| 316 | | -{ |
| 317 | | - int volume = 0; |
| 318 | | - const char *temp = name; |
| 319 | | - |
| 320 | | - while (*temp == '/') /* skip all leading slashes */ |
| 321 | | - ++temp; |
| 322 | | - |
| 323 | | - if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS)) |
| 324 | | - { |
| 325 | | - temp += VOL_ENUM_POS; /* behind special name */ |
| 326 | | - volume = atoi(temp); /* number is following */ |
| 327 | | - temp = strchr(temp, '/'); /* search for slash behind */ |
| 328 | | - if (temp != NULL) |
| 329 | | - name = temp; /* use the part behind the volume */ |
| 330 | | - else |
| 331 | | - name = "/"; /* else this must be the root dir */ |
| 332 | | - } |
| 333 | | - |
| 334 | | - strlcpy(namecopy, name, MAX_PATH); |
| 335 | | - |
| 336 | | - return volume; |
| 337 | | -} |
| 338 | | -#endif /* #ifdef HAVE_MULTIVOLUME */ |
| | 34 | +static DIR opendirs[MAX_OPEN_DIRS];
|
| | 35 | +
|
| | 36 | +#ifdef HAVE_HOTSWAP
|
| | 37 | +// release all dir handles on a given volume "by force", to avoid leaks
|
| | 38 | +int release_dirs(int volume)
|
| | 39 | +{
|
| | 40 | + DIR* pdir = opendirs;
|
| | 41 | + int dd;
|
| | 42 | + int closed = 0;
|
| | 43 | + for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
|
| | 44 | + {
|
| | 45 | +#ifdef HAVE_MULTIVOLUME
|
| | 46 | + if (pdir->fatdir.file.volume == volume)
|
| | 47 | +#else
|
| | 48 | + (void)volume;
|
| | 49 | +#endif
|
| | 50 | + {
|
| | 51 | + pdir->busy = false; /* mark as available, no further action */
|
| | 52 | + closed++;
|
| | 53 | + }
|
| | 54 | + }
|
| | 55 | + return closed; /* return how many we did */
|
| | 56 | +}
|
| | 57 | +#endif /* #ifdef HAVE_HOTSWAP */
|
| | 58 | +
|
| | 59 | +DIR* opendir(const char* name)
|
| | 60 | +{
|
| | 61 | + char namecopy[MAX_PATH];
|
| | 62 | + char* part;
|
| | 63 | + char* end;
|
| | 64 | + struct fat_direntry entry;
|
| | 65 | + int dd;
|
| | 66 | + DIR* pdir = opendirs;
|
| | 67 | +#ifdef HAVE_MULTIVOLUME
|
| | 68 | + int volume;
|
| | 69 | +#endif
|
| | 70 | +
|
| | 71 | + if ( name[0] != '/' ) {
|
| | 72 | + DEBUGF("Only absolute paths supported right now");
|
| | 73 | + return NULL;
|
| | 74 | + }
|
| | 75 | +
|
| | 76 | + /* find a free dir descriptor */
|
| | 77 | + for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
|
| | 78 | + if ( !pdir->busy )
|
| | 79 | + break;
|
| | 80 | +
|
| | 81 | + if ( dd == MAX_OPEN_DIRS ) {
|
| | 82 | + DEBUGF("Too many dirs open");
|
| | 83 | + errno = EMFILE;
|
| | 84 | + return NULL;
|
| | 85 | + }
|
| | 86 | +
|
| | 87 | + pdir->busy = true;
|
| | 88 | + pdir->process = current_thread;
|
| | 89 | +
|
| | 90 | +#ifdef HAVE_MULTIVOLUME
|
| | 91 | + /* try to extract a heading volume name, if present */
|
| | 92 | + volume = strip_volume(name, namecopy);
|
| | 93 | + pdir->volumecounter = 0;
|
| | 94 | +#else
|
| | 95 | + strlcpy(namecopy, name, sizeof(namecopy)); /* just copy */
|
| | 96 | +#endif
|
| | 97 | +
|
| | 98 | + if ( fat_opendir(IF_MV2(volume,) &pdir->fatdir, 0, NULL) < 0 ) {
|
| | 99 | + DEBUGF("Failed opening root dir");
|
| | 100 | + pdir->busy = false;
|
| | 101 | + return NULL;
|
| | 102 | + }
|
| | 103 | +
|
| | 104 | + for ( part = strtok_r(namecopy, "/", &end); part;
|
| | 105 | + part = strtok_r(NULL, "/", &end)) {
|
| | 106 | + /* scan dir for name */
|
| | 107 | + while (1) {
|
| | 108 | + if ((fat_getnext(&pdir->fatdir,&entry) < 0) ||
|
| | 109 | + (!entry.name[0])) {
|
| | 110 | + pdir->busy = false;
|
| | 111 | + return NULL;
|
| | 112 | + }
|
| | 113 | + if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
|
| | 114 | + (!strcasecmp(part, entry.name)) ) {
|
| | 115 | + /* In reality, the parent_dir parameter of fat_opendir seems
|
| | 116 | + * useless because it's sole purpose it to have a way to
|
| | 117 | + * update the file metadata, but here we are only reading
|
| | 118 | + * a directory so there's no need for that kind of stuff.
|
| | 119 | + * However, the rmdir function uses a ugly hack to
|
| | 120 | + * avoid opening a directory twice when deleting it and thus
|
| | 121 | + * needs those information. That's why we pass pdir->fatdir both
|
| | 122 | + * as the parent directory and the resulting one (this is safe,
|
| | 123 | + * in doubt, check fat_open(dir) code) which will allow this kind of
|
| | 124 | + * (ugly) things */
|
| | 125 | + if ( fat_opendir(IF_MV2(volume,)
|
| | 126 | + &pdir->fatdir,
|
| | 127 | + entry.firstcluster,
|
| | 128 | + &pdir->fatdir) < 0 ) {
|
| | 129 | + DEBUGF("Failed opening dir '%s' (%ld)",
|
| | 130 | + part, entry.firstcluster);
|
| | 131 | + pdir->busy = false;
|
| | 132 | + return NULL;
|
| | 133 | + }
|
| | 134 | +#ifdef HAVE_MULTIVOLUME
|
| | 135 | + pdir->volumecounter = -1; /* n.a. to subdirs */
|
| | 136 | +#endif
|
| | 137 | + break;
|
| | 138 | + }
|
| | 139 | + }
|
| | 140 | + }
|
| | 141 | +
|
| | 142 | + return pdir;
|
| | 143 | +}
|
| | 144 | +
|
| | 145 | +int closedir(DIR* dir)
|
| | 146 | +{
|
| | 147 | + dir->busy=false;
|
| | 148 | + return 0;
|
| | 149 | +}
|
| | 150 | +
|
| | 151 | +int closedir_all_of_process(struct scheduler_thread* process)
|
| | 152 | +{
|
| | 153 | + DIR* pdir = opendirs;
|
| | 154 | + int dd;
|
| | 155 | + int closed = 0;
|
| | 156 | + for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
|
| | 157 | + {
|
| | 158 | + if (pdir->process == process)
|
| | 159 | + {
|
| | 160 | + pdir->busy = false; /* mark as available, no further action */
|
| | 161 | + closed++;
|
| | 162 | + }
|
| | 163 | + }
|
| | 164 | + return closed; /* return how many we did */
|
| | 165 | +}
|
| | 166 | +
|
| | 167 | +struct dirent* readdir(DIR* dir)
|
| | 168 | +{
|
| | 169 | + struct fat_direntry entry;
|
| | 170 | + struct dirent* theent = &(dir->theent);
|
| | 171 | +
|
| | 172 | + if (!dir->busy)
|
| | 173 | + return NULL;
|
| | 174 | +
|
| | 175 | +#ifdef HAVE_MULTIVOLUME
|
| | 176 | + /* Volumes (secondary file systems) get inserted into the root directory
|
| | 177 | + of the first volume, since we have no separate top level. */
|
| | 178 | + if (dir->volumecounter >= 0 /* on a root dir */
|
| | 179 | + && dir->volumecounter < NUM_VOLUMES /* in range */
|
| | 180 | + && dir->fatdir.file.volume == 0) /* at volume 0 */
|
| | 181 | + { /* fake special directories, which don't really exist, but
|
| | 182 | + will get redirected upon opendir() */
|
| | 183 | + while (++dir->volumecounter < NUM_VOLUMES)
|
| | 184 | + {
|
| | 185 | + if (fat_ismounted(dir->volumecounter))
|
| | 186 | + {
|
| | 187 | + memset(theent, 0, sizeof(*theent));
|
| | 188 | + theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
| | 189 | + snprintf(theent->d_name, sizeof(theent->d_name),
|
| | 190 | + VOL_NAMES, dir->volumecounter);
|
| | 191 | + return theent;
|
| | 192 | + }
|
| | 193 | + }
|
| | 194 | + }
|
| | 195 | +#endif
|
| | 196 | + /* normal directory entry fetching follows here */
|
| | 197 | + if (fat_getnext(&(dir->fatdir),&entry) < 0)
|
| | 198 | + return NULL;
|
| | 199 | +
|
| | 200 | + if ( !entry.name[0] )
|
| | 201 | + return NULL;
|
| | 202 | +
|
| | 203 | + strlcpy(theent->d_name, entry.name, sizeof(theent->d_name));
|
| | 204 | + theent->attribute = entry.attr;
|
| | 205 | + theent->size = entry.filesize;
|
| | 206 | + theent->startcluster = entry.firstcluster;
|
| | 207 | + theent->wrtdate = entry.wrtdate;
|
| | 208 | + theent->wrttime = entry.wrttime;
|
| | 209 | +
|
| | 210 | + return theent;
|
| | 211 | +}
|
| | 212 | +
|
| | 213 | +int mkdir(const char *name)
|
| | 214 | +{
|
| | 215 | + DIR *dir;
|
| | 216 | + char namecopy[MAX_PATH];
|
| | 217 | + char* end;
|
| | 218 | + char *basename;
|
| | 219 | + char *parent;
|
| | 220 | + struct dirent *entry;
|
| | 221 | + struct fat_dir newdir;
|
| | 222 | + int rc;
|
| | 223 | +
|
| | 224 | + if ( name[0] != '/' ) {
|
| | 225 | + DEBUGF("mkdir: Only absolute paths supported right now");
|
| | 226 | + return -1;
|
| | 227 | + }
|
| | 228 | +
|
| | 229 | + strlcpy(namecopy, name, sizeof(namecopy));
|
| | 230 | +
|
| | 231 | + /* Split the base name and the path */
|
| | 232 | + end = strrchr(namecopy, '/');
|
| | 233 | + *end = 0;
|
| | 234 | + basename = end+1;
|
| | 235 | +
|
| | 236 | + if(namecopy == end) /* Root dir? */
|
| | 237 | + parent = "/";
|
| | 238 | + else
|
| | 239 | + parent = namecopy;
|
| | 240 | +
|
| | 241 | + DEBUGF("mkdir: parent: %s, name: %s", parent, basename);
|
| | 242 | +
|
| | 243 | + dir = opendir(parent);
|
| | 244 | +
|
| | 245 | + if(!dir) {
|
| | 246 | + DEBUGF("mkdir: can't open parent dir");
|
| | 247 | + return -2;
|
| | 248 | + }
|
| | 249 | +
|
| | 250 | + if(basename[0] == 0) {
|
| | 251 | + DEBUGF("mkdir: Empty dir name");
|
| | 252 | + errno = EINVAL;
|
| | 253 | + return -3;
|
| | 254 | + }
|
| | 255 | +
|
| | 256 | + /* Now check if the name already exists */
|
| | 257 | + while ((entry = readdir(dir))) {
|
| | 258 | + if ( !strcasecmp(basename, entry->d_name) ) {
|
| | 259 | + DEBUGF("mkdir error: file exists");
|
| | 260 | + errno = EEXIST;
|
| | 261 | + closedir(dir);
|
| | 262 | + return - 4;
|
| | 263 | + }
|
| | 264 | + }
|
| | 265 | +
|
| | 266 | + memset(&newdir, 0, sizeof(struct fat_dir));
|
| | 267 | +
|
| | 268 | + rc = fat_create_dir(basename, &newdir, &(dir->fatdir));
|
| | 269 | + closedir(dir);
|
| | 270 | +
|
| | 271 | + return rc;
|
| | 272 | +}
|
| | 273 | +
|
| | 274 | +int rmdir(const char* name)
|
| | 275 | +{
|
| | 276 | + int rc;
|
| | 277 | + DIR* dir;
|
| | 278 | + struct dirent* entry;
|
| | 279 | +
|
| | 280 | + dir = opendir(name);
|
| | 281 | + if (!dir)
|
| | 282 | + {
|
| | 283 | + errno = ENOENT; /* open error */
|
| | 284 | + return -1;
|
| | 285 | + }
|
| | 286 | +
|
| | 287 | + /* check if the directory is empty */
|
| | 288 | + while ((entry = readdir(dir)))
|
| | 289 | + {
|
| | 290 | + if (strcmp(entry->d_name, ".") &&
|
| | 291 | + strcmp(entry->d_name, ".."))
|
| | 292 | + {
|
| | 293 | + DEBUGF("rmdir error: not empty");
|
| | 294 | + errno = ENOTEMPTY;
|
| | 295 | + closedir(dir);
|
| | 296 | + return -2;
|
| | 297 | + }
|
| | 298 | + }
|
| | 299 | +
|
| | 300 | + rc = fat_remove(&(dir->fatdir.file));
|
| | 301 | + if ( rc < 0 ) {
|
| | 302 | + DEBUGF("Failed removing dir: %d", rc);
|
| | 303 | + errno = EIO;
|
| | 304 | + rc = rc * 10 - 3;
|
| | 305 | + }
|
| | 306 | +
|
| | 307 | + closedir(dir);
|
| | 308 | + return rc;
|
| | 309 | +}
|
| | 310 | +
|
| | 311 | +#ifdef HAVE_MULTIVOLUME
|
| | 312 | +/* returns on which volume this is, and copies the reduced name
|
| | 313 | + (sortof a preprocessor for volume-decorated pathnames) */
|
| | 314 | +int strip_volume(const char* name, char* namecopy)
|
| | 315 | +{
|
| | 316 | + int volume = 0;
|
| | 317 | + const char *temp = name;
|
| | 318 | +
|
| | 319 | + while (*temp == '/') /* skip all leading slashes */
|
| | 320 | + ++temp;
|
| | 321 | +
|
| | 322 | + if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS))
|
| | 323 | + {
|
| | 324 | + temp += VOL_ENUM_POS; /* behind special name */
|
| | 325 | + volume = atoi(temp); /* number is following */
|
| | 326 | + temp = strchr(temp, '/'); /* search for slash behind */
|
| | 327 | + if (temp != NULL)
|
| | 328 | + name = temp; /* use the part behind the volume */
|
| | 329 | + else
|
| | 330 | + name = "/"; /* else this must be the root dir */
|
| | 331 | + }
|
| | 332 | +
|
| | 333 | + strlcpy(namecopy, name, MAX_PATH);
|
| | 334 | +
|
| | 335 | + return volume;
|
| | 336 | +}
|
| | 337 | +#endif /* #ifdef HAVE_MULTIVOLUME */
|