[1679] | 1 | /* |
---|
[1706] | 2 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/directories.c,v $ |
---|
[12144] | 3 | * $Author: ghudson $ |
---|
[1706] | 4 | * |
---|
| 5 | * This program is part of a package including delete, undelete, |
---|
| 6 | * lsdel, expunge and purge. The software suite is meant as a |
---|
| 7 | * replacement for rm which allows for file recovery. |
---|
| 8 | * |
---|
| 9 | * Copyright (c) 1989 by the Massachusetts Institute of Technology. |
---|
[4505] | 10 | * For copying and distribution information, see the file "mit-copying.h." |
---|
[1706] | 11 | */ |
---|
| 12 | |
---|
| 13 | #if !defined(lint) && !defined(SABER) |
---|
[12144] | 14 | static char rcsid_directories_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/directories.c,v 1.27 1998-11-16 16:42:12 ghudson Exp $"; |
---|
[1706] | 15 | #endif |
---|
| 16 | |
---|
[2181] | 17 | #include <stdio.h> |
---|
[1679] | 18 | #include <sys/types.h> |
---|
| 19 | #include <sys/param.h> |
---|
[5049] | 20 | #include <dirent.h> |
---|
[3049] | 21 | #include <string.h> |
---|
[10977] | 22 | #include <time.h> |
---|
[2181] | 23 | #include <errno.h> |
---|
| 24 | #include <com_err.h> |
---|
| 25 | #include "delete_errs.h" |
---|
[1688] | 26 | #include "util.h" |
---|
[4415] | 27 | #include "directories.h" |
---|
[4505] | 28 | #include "mit-copying.h" |
---|
[2181] | 29 | #include "errors.h" |
---|
[1679] | 30 | |
---|
| 31 | static filerec root_tree; |
---|
| 32 | static filerec cwd_tree; |
---|
| 33 | |
---|
[2221] | 34 | void free_leaf(); |
---|
[1679] | 35 | |
---|
[2221] | 36 | /* These are not static because external routines need to be able to */ |
---|
| 37 | /* access them. */ |
---|
| 38 | time_t current_time; |
---|
[1679] | 39 | |
---|
[2221] | 40 | |
---|
[1688] | 41 | static filerec default_cwd = { |
---|
[1713] | 42 | "", |
---|
[1688] | 43 | (filerec *) NULL, |
---|
| 44 | (filerec *) NULL, |
---|
| 45 | (filerec *) NULL, |
---|
| 46 | (filerec *) NULL, |
---|
| 47 | (filerec *) NULL, |
---|
| 48 | False, |
---|
[1732] | 49 | False, |
---|
| 50 | {0} |
---|
[1688] | 51 | }; |
---|
[1679] | 52 | |
---|
[1688] | 53 | static filerec default_root = { |
---|
[1713] | 54 | "/", |
---|
[1688] | 55 | (filerec *) NULL, |
---|
| 56 | (filerec *) NULL, |
---|
| 57 | (filerec *) NULL, |
---|
| 58 | (filerec *) NULL, |
---|
| 59 | (filerec *) NULL, |
---|
| 60 | False, |
---|
[1732] | 61 | False, |
---|
| 62 | {0} |
---|
[1688] | 63 | }; |
---|
| 64 | |
---|
| 65 | static filerec default_directory = { |
---|
| 66 | "", |
---|
| 67 | (filerec *) NULL, |
---|
| 68 | (filerec *) NULL, |
---|
| 69 | (filerec *) NULL, |
---|
| 70 | (filerec *) NULL, |
---|
| 71 | (filerec *) NULL, |
---|
| 72 | False, |
---|
[1732] | 73 | False, |
---|
| 74 | {0} |
---|
[1688] | 75 | }; |
---|
| 76 | |
---|
| 77 | static filerec default_file = { |
---|
| 78 | "", |
---|
| 79 | (filerec *) NULL, |
---|
| 80 | (filerec *) NULL, |
---|
| 81 | (filerec *) NULL, |
---|
| 82 | (filerec *) NULL, |
---|
| 83 | (filerec *) NULL, |
---|
| 84 | False, |
---|
[1732] | 85 | False, |
---|
| 86 | {0} |
---|
[1688] | 87 | }; |
---|
| 88 | |
---|
| 89 | |
---|
[1679] | 90 | filerec *get_root_tree() |
---|
| 91 | { |
---|
| 92 | return(&root_tree); |
---|
| 93 | } |
---|
| 94 | |
---|
| 95 | |
---|
| 96 | |
---|
| 97 | filerec *get_cwd_tree() |
---|
| 98 | { |
---|
| 99 | return(&cwd_tree); |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | |
---|
[2181] | 103 | int initialize_tree() |
---|
[1679] | 104 | { |
---|
[2181] | 105 | int retval; |
---|
[1732] | 106 | |
---|
[1679] | 107 | root_tree = default_root; |
---|
| 108 | cwd_tree = default_cwd; |
---|
[1732] | 109 | |
---|
[2181] | 110 | current_time = time((time_t *)0); |
---|
| 111 | if (retval = get_specs(".", &cwd_tree.specs, FOLLOW_LINKS)) { |
---|
| 112 | error("get_specs on ."); |
---|
| 113 | return retval; |
---|
[1679] | 114 | } |
---|
[2181] | 115 | if (retval = get_specs("/", &root_tree.specs, FOLLOW_LINKS)) { |
---|
| 116 | error("get_specs on /"); |
---|
| 117 | return retval; |
---|
| 118 | } |
---|
| 119 | return 0; |
---|
[1679] | 120 | } |
---|
| 121 | |
---|
| 122 | |
---|
[2181] | 123 | int add_path_to_tree(path, leaf) |
---|
[1679] | 124 | char *path; |
---|
[2181] | 125 | filerec **leaf; |
---|
[1679] | 126 | { |
---|
[2181] | 127 | filerec *parent; |
---|
[1679] | 128 | char next_name[MAXNAMLEN]; |
---|
[1732] | 129 | char lpath[MAXPATHLEN], built_path[MAXPATHLEN], *ptr; |
---|
[4422] | 130 | struct mystat specs; |
---|
[2181] | 131 | int retval; |
---|
| 132 | |
---|
| 133 | if (retval = get_specs(path, &specs, DONT_FOLLOW_LINKS)) { |
---|
| 134 | char error_buf[MAXPATHLEN+14]; |
---|
[1679] | 135 | |
---|
[2181] | 136 | (void) sprintf(error_buf, "get_specs on %s", path); |
---|
| 137 | error(error_buf); |
---|
| 138 | return retval; |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | (void) strcpy(lpath, path); /* we don't want to damage the user's */ |
---|
| 142 | /* string */ |
---|
| 143 | ptr = lpath; |
---|
[1679] | 144 | if (*ptr == '/') { |
---|
| 145 | parent = &root_tree; |
---|
| 146 | ptr++; |
---|
[2181] | 147 | (void) strcpy(built_path, "/"); |
---|
[1679] | 148 | } |
---|
| 149 | else if (! strncmp(ptr, "./", 2)) { |
---|
| 150 | parent = &cwd_tree; |
---|
| 151 | ptr += 2; |
---|
[1732] | 152 | *built_path = '\0'; |
---|
[1679] | 153 | } |
---|
[1732] | 154 | else { |
---|
[1679] | 155 | parent = &cwd_tree; |
---|
[1732] | 156 | *built_path = '\0'; |
---|
| 157 | } |
---|
| 158 | |
---|
[2181] | 159 | (void) strcpy(next_name, firstpart(ptr, ptr)); |
---|
[1679] | 160 | while (*ptr) { |
---|
[2181] | 161 | (void) strcat(built_path, next_name); |
---|
| 162 | if (retval = add_directory_to_parent(parent, next_name, False, |
---|
| 163 | &parent)) { |
---|
| 164 | error("add_directory_to_parent"); |
---|
| 165 | return retval; |
---|
| 166 | } |
---|
| 167 | (void) strcpy(next_name, firstpart(ptr, ptr)); |
---|
| 168 | if (retval = get_specs(built_path, &parent->specs, FOLLOW_LINKS)) { |
---|
| 169 | char error_buf[MAXPATHLEN+14]; |
---|
| 170 | |
---|
| 171 | (void) sprintf(error_buf, "get_specs on %s", built_path); |
---|
| 172 | error(error_buf); |
---|
| 173 | return retval; |
---|
| 174 | } |
---|
| 175 | (void) strcat(built_path, "/"); |
---|
[1679] | 176 | } |
---|
[2181] | 177 | if ((specs.st_mode & S_IFMT) == S_IFDIR) { |
---|
| 178 | retval = add_directory_to_parent(parent, next_name, True, leaf); |
---|
| 179 | if (retval) { |
---|
| 180 | error("add_directory_to_parent"); |
---|
| 181 | return retval; |
---|
| 182 | } |
---|
| 183 | } |
---|
| 184 | else { |
---|
| 185 | retval = add_file_to_parent(parent, next_name, True, leaf); |
---|
| 186 | if (retval) { |
---|
| 187 | error("add_file_to_parent"); |
---|
| 188 | return retval; |
---|
| 189 | } |
---|
| 190 | } |
---|
[1679] | 191 | |
---|
[2181] | 192 | (*leaf)->specs = specs; |
---|
| 193 | |
---|
| 194 | return 0; |
---|
[1679] | 195 | } |
---|
| 196 | |
---|
| 197 | |
---|
| 198 | |
---|
[2181] | 199 | int get_specs(path, specs, follow) |
---|
[1679] | 200 | char *path; |
---|
[4422] | 201 | struct mystat *specs; |
---|
[2181] | 202 | int follow; /* follow symlinks or not? */ |
---|
[1679] | 203 | { |
---|
[1732] | 204 | int status; |
---|
[4422] | 205 | struct stat realspecs; |
---|
[1679] | 206 | |
---|
[1732] | 207 | if (strlen(path)) if ((path[strlen(path) - 1] == '/') && |
---|
| 208 | (strlen(path) != 1)) |
---|
[1679] | 209 | path[strlen(path) - 1] = '\0'; |
---|
[1732] | 210 | if (follow == FOLLOW_LINKS) |
---|
[4422] | 211 | status = stat(path, &realspecs); |
---|
[1732] | 212 | else |
---|
[4422] | 213 | status = lstat(path, &realspecs); |
---|
[1732] | 214 | |
---|
[2181] | 215 | if (status) { |
---|
| 216 | set_error(errno); |
---|
| 217 | error(path); |
---|
| 218 | return error_code; |
---|
| 219 | } |
---|
| 220 | |
---|
[4422] | 221 | specs->st_dev = realspecs.st_dev; |
---|
| 222 | specs->st_ino = realspecs.st_ino; |
---|
| 223 | specs->st_mode = realspecs.st_mode; |
---|
| 224 | specs->st_size = realspecs.st_size; |
---|
[7980] | 225 | specs->st_chtime = realspecs.st_ctime; |
---|
[4422] | 226 | specs->st_blocks = realspecs.st_blocks; |
---|
| 227 | |
---|
[2181] | 228 | return 0; |
---|
[1679] | 229 | } |
---|
| 230 | |
---|
| 231 | |
---|
| 232 | |
---|
| 233 | filerec *next_leaf(leaf) |
---|
| 234 | filerec *leaf; |
---|
| 235 | { |
---|
[1684] | 236 | filerec *new; |
---|
[1732] | 237 | |
---|
| 238 | if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) { |
---|
[1684] | 239 | new = first_in_directory(leaf); |
---|
| 240 | if (new) |
---|
| 241 | return(new); |
---|
| 242 | new = next_directory(leaf); |
---|
| 243 | return(new); |
---|
| 244 | } |
---|
| 245 | else { |
---|
| 246 | new = next_in_directory(leaf); |
---|
| 247 | return(new); |
---|
| 248 | } |
---|
[1679] | 249 | } |
---|
| 250 | |
---|
| 251 | |
---|
| 252 | filerec *next_specified_leaf(leaf) |
---|
| 253 | filerec *leaf; |
---|
| 254 | { |
---|
[1684] | 255 | while (leaf = next_leaf(leaf)) |
---|
| 256 | if (leaf->specified) |
---|
| 257 | return(leaf); |
---|
[1679] | 258 | return((filerec *) NULL); |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | |
---|
| 262 | filerec *next_directory(leaf) |
---|
| 263 | filerec *leaf; |
---|
| 264 | { |
---|
[1684] | 265 | filerec *ret; |
---|
[1732] | 266 | if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR) |
---|
[1679] | 267 | leaf = leaf->parent; |
---|
| 268 | if (leaf) |
---|
[1684] | 269 | ret = leaf->next; |
---|
[1679] | 270 | else |
---|
[1684] | 271 | ret = (filerec *) NULL; |
---|
| 272 | if (ret) if (ret->freed) |
---|
| 273 | ret = next_directory(ret); |
---|
| 274 | return(ret); |
---|
[1679] | 275 | } |
---|
| 276 | |
---|
| 277 | |
---|
| 278 | filerec *next_specified_directory(leaf) |
---|
| 279 | filerec *leaf; |
---|
| 280 | { |
---|
[1684] | 281 | while (leaf = next_directory(leaf)) |
---|
| 282 | if (leaf->specified) |
---|
| 283 | return(leaf); |
---|
| 284 | return ((filerec *) NULL); |
---|
[1679] | 285 | } |
---|
| 286 | |
---|
| 287 | |
---|
| 288 | |
---|
| 289 | filerec *next_in_directory(leaf) |
---|
| 290 | filerec *leaf; |
---|
| 291 | { |
---|
[1684] | 292 | filerec *ret; |
---|
[1732] | 293 | |
---|
[1679] | 294 | if (leaf->next) |
---|
[1684] | 295 | ret = leaf->next; |
---|
[1732] | 296 | else if (((leaf->specs.st_mode & S_IFMT) != S_IFDIR) && leaf->parent) |
---|
[1684] | 297 | ret = leaf->parent->dirs; |
---|
[1679] | 298 | else |
---|
[1684] | 299 | ret = (filerec *) NULL; |
---|
| 300 | if (ret) if (ret->freed) |
---|
| 301 | ret = next_in_directory(ret); |
---|
| 302 | return (ret); |
---|
[1679] | 303 | } |
---|
| 304 | |
---|
| 305 | |
---|
| 306 | |
---|
| 307 | |
---|
| 308 | filerec *next_specified_in_directory(leaf) |
---|
| 309 | filerec *leaf; |
---|
| 310 | { |
---|
| 311 | while (leaf = next_in_directory(leaf)) |
---|
| 312 | if (leaf->specified) |
---|
| 313 | return(leaf); |
---|
| 314 | return ((filerec *) NULL); |
---|
| 315 | } |
---|
| 316 | |
---|
| 317 | |
---|
| 318 | |
---|
| 319 | filerec *first_in_directory(leaf) |
---|
| 320 | filerec *leaf; |
---|
| 321 | { |
---|
[1684] | 322 | filerec *ret; |
---|
[1732] | 323 | |
---|
| 324 | if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR) |
---|
[1684] | 325 | ret = (filerec *) NULL; |
---|
| 326 | else if (leaf->files) |
---|
| 327 | ret = leaf->files; |
---|
[1679] | 328 | else if (leaf->dirs) |
---|
[1684] | 329 | ret = leaf->dirs; |
---|
[1679] | 330 | else |
---|
[1684] | 331 | ret = (filerec *) NULL; |
---|
| 332 | if (ret) if (ret->freed) |
---|
| 333 | ret = next_in_directory(ret); |
---|
| 334 | return(ret); |
---|
[1679] | 335 | } |
---|
| 336 | |
---|
| 337 | |
---|
[1684] | 338 | filerec *first_specified_in_directory(leaf) |
---|
[1679] | 339 | filerec *leaf; |
---|
| 340 | { |
---|
| 341 | leaf = first_in_directory(leaf); |
---|
[1700] | 342 | if (! leaf) |
---|
| 343 | return((filerec *) NULL); |
---|
[1679] | 344 | |
---|
[1684] | 345 | if (leaf->specified) |
---|
[1679] | 346 | return(leaf); |
---|
| 347 | else |
---|
[1684] | 348 | leaf = next_specified_in_directory(leaf); |
---|
[1732] | 349 | return (leaf); |
---|
[1679] | 350 | } |
---|
| 351 | |
---|
| 352 | |
---|
[2221] | 353 | void print_paths_from(leaf) |
---|
[1679] | 354 | filerec *leaf; |
---|
| 355 | { |
---|
[6420] | 356 | /* |
---|
| 357 | * This is static to prevent multiple copies of it when calling |
---|
| 358 | * recursively. |
---|
| 359 | */ |
---|
| 360 | static char buf[MAXPATHLEN]; |
---|
[1732] | 361 | |
---|
[1679] | 362 | printf("%s\n", get_leaf_path(leaf, buf)); |
---|
| 363 | if (leaf->dirs) |
---|
[1684] | 364 | print_paths_from(leaf->dirs); |
---|
[1679] | 365 | if (leaf->files) |
---|
[1684] | 366 | print_paths_from(leaf->files); |
---|
[1679] | 367 | if (leaf->next) |
---|
[1684] | 368 | print_paths_from(leaf->next); |
---|
[1679] | 369 | } |
---|
| 370 | |
---|
| 371 | |
---|
[2221] | 372 | void print_specified_paths_from(leaf) |
---|
[1679] | 373 | filerec *leaf; |
---|
| 374 | { |
---|
[6420] | 375 | /* |
---|
| 376 | * This is static to prevent multiple copies of it when calling |
---|
| 377 | * recursively. |
---|
| 378 | */ |
---|
| 379 | static char buf[MAXPATHLEN]; |
---|
[1732] | 380 | |
---|
[1679] | 381 | if (leaf->specified) |
---|
| 382 | printf("%s\n", get_leaf_path(leaf, buf)); |
---|
| 383 | if (leaf->dirs) |
---|
[1684] | 384 | print_specified_paths_from(leaf->dirs); |
---|
[1679] | 385 | if (leaf->files) |
---|
[1684] | 386 | print_specified_paths_from(leaf->files); |
---|
[1679] | 387 | if (leaf->next) |
---|
[1684] | 388 | print_specified_paths_from(leaf->next); |
---|
[1679] | 389 | } |
---|
| 390 | |
---|
| 391 | |
---|
[2181] | 392 | int add_file_to_parent(parent, name, specified, last) |
---|
| 393 | filerec *parent, **last; |
---|
[1679] | 394 | char *name; |
---|
[1684] | 395 | Boolean specified; |
---|
[1679] | 396 | { |
---|
[2181] | 397 | filerec *files; |
---|
[1732] | 398 | |
---|
[2181] | 399 | *last = files = (filerec *) NULL; |
---|
[1679] | 400 | files = parent->files; |
---|
| 401 | while (files) { |
---|
| 402 | if (! strcmp(files->name, name)) |
---|
| 403 | break; |
---|
[2181] | 404 | *last = files; |
---|
[1679] | 405 | files = files->next; |
---|
| 406 | } |
---|
| 407 | if (files) { |
---|
| 408 | files->specified = (files->specified || specified); |
---|
[2181] | 409 | *last = files; |
---|
| 410 | return 0; |
---|
[1679] | 411 | } |
---|
[2181] | 412 | if (*last) { |
---|
[2367] | 413 | (*last)->next = (filerec *) Malloc((unsigned) sizeof(filerec)); |
---|
[2181] | 414 | if (! (*last)->next) { |
---|
| 415 | set_error(errno); |
---|
[2367] | 416 | error("Malloc"); |
---|
[2181] | 417 | return error_code; |
---|
| 418 | } |
---|
| 419 | *(*last)->next = default_file; |
---|
| 420 | (*last)->next->previous = *last; |
---|
| 421 | (*last)->next->parent = parent; |
---|
| 422 | (*last) = (*last)->next; |
---|
[1679] | 423 | } |
---|
| 424 | else { |
---|
[2367] | 425 | parent->files = (filerec *) Malloc(sizeof(filerec)); |
---|
[2181] | 426 | if (! parent->files) { |
---|
| 427 | set_error(errno); |
---|
[2367] | 428 | error("Malloc"); |
---|
[2181] | 429 | return error_code; |
---|
| 430 | } |
---|
[1679] | 431 | *parent->files = default_file; |
---|
| 432 | parent->files->parent = parent; |
---|
| 433 | parent->files->previous = (filerec *) NULL; |
---|
[2181] | 434 | *last = parent->files; |
---|
[1679] | 435 | } |
---|
[2181] | 436 | (void) strcpy((*last)->name, name); |
---|
| 437 | (*last)->specified = specified; |
---|
| 438 | return 0; |
---|
[1679] | 439 | } |
---|
| 440 | |
---|
| 441 | |
---|
| 442 | |
---|
| 443 | |
---|
| 444 | |
---|
[2181] | 445 | int add_directory_to_parent(parent, name, specified, last) |
---|
| 446 | filerec *parent, **last; |
---|
[1679] | 447 | char *name; |
---|
[1684] | 448 | Boolean specified; |
---|
[1679] | 449 | { |
---|
[2181] | 450 | filerec *directories; |
---|
[1732] | 451 | |
---|
[2181] | 452 | *last = (filerec *) NULL; |
---|
[1679] | 453 | directories = parent->dirs; |
---|
| 454 | while (directories) { |
---|
| 455 | if (! strcmp(directories->name, name)) |
---|
| 456 | break; |
---|
[2181] | 457 | (*last) = directories; |
---|
[1679] | 458 | directories = directories->next; |
---|
| 459 | } |
---|
| 460 | if (directories) { |
---|
| 461 | directories->specified = (directories->specified || specified); |
---|
[2181] | 462 | *last = directories; |
---|
| 463 | return 0; |
---|
[1679] | 464 | } |
---|
[2181] | 465 | if (*last) { |
---|
[2367] | 466 | (*last)->next = (filerec *) Malloc(sizeof(filerec)); |
---|
[2181] | 467 | if (! (*last)->next) { |
---|
| 468 | set_error(errno); |
---|
[2367] | 469 | error("Malloc"); |
---|
[2181] | 470 | return error_code; |
---|
| 471 | } |
---|
| 472 | *(*last)->next = default_directory; |
---|
| 473 | (*last)->next->previous = *last; |
---|
| 474 | (*last)->next->parent = parent; |
---|
| 475 | (*last) = (*last)->next; |
---|
[1679] | 476 | } |
---|
| 477 | else { |
---|
[2367] | 478 | parent->dirs = (filerec *) Malloc(sizeof(filerec)); |
---|
[2181] | 479 | if (! parent->dirs) { |
---|
| 480 | set_error(errno); |
---|
[2367] | 481 | error("Malloc"); |
---|
[2181] | 482 | return error_code; |
---|
| 483 | } |
---|
[1679] | 484 | *parent->dirs = default_directory; |
---|
| 485 | parent->dirs->parent = parent; |
---|
| 486 | parent->dirs->previous = (filerec *) NULL; |
---|
[2181] | 487 | (*last) = parent->dirs; |
---|
[1679] | 488 | } |
---|
[2181] | 489 | (void) strcpy((*last)->name, name); |
---|
| 490 | (*last)->specified = specified; |
---|
| 491 | return 0; |
---|
[1679] | 492 | } |
---|
| 493 | |
---|
| 494 | |
---|
| 495 | |
---|
| 496 | |
---|
| 497 | |
---|
[2221] | 498 | void free_leaf(leaf) |
---|
[1679] | 499 | filerec *leaf; |
---|
| 500 | { |
---|
| 501 | leaf->freed = True; |
---|
[1684] | 502 | if (! (leaf->dirs || leaf->files)) { |
---|
| 503 | if (leaf->previous) |
---|
| 504 | leaf->previous->next = leaf->next; |
---|
| 505 | if (leaf->next) |
---|
| 506 | leaf->next->previous = leaf->previous; |
---|
[1752] | 507 | if (leaf->parent) { |
---|
| 508 | if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) { |
---|
| 509 | if (leaf->parent->dirs == leaf) { |
---|
| 510 | leaf->parent->dirs = leaf->next; |
---|
| 511 | if (leaf->parent->freed) |
---|
[2221] | 512 | free_leaf(leaf->parent); |
---|
[1752] | 513 | } |
---|
[1684] | 514 | } |
---|
[1752] | 515 | else { |
---|
| 516 | if (leaf->parent->files == leaf) { |
---|
| 517 | leaf->parent->files = leaf->next; |
---|
| 518 | if (leaf->parent->freed) |
---|
[2221] | 519 | free_leaf(leaf->parent); |
---|
[1752] | 520 | } |
---|
[1684] | 521 | } |
---|
[2181] | 522 | free((char *) leaf); |
---|
[1684] | 523 | } |
---|
| 524 | } |
---|
[1679] | 525 | } |
---|
| 526 | |
---|
| 527 | |
---|
| 528 | |
---|
[2181] | 529 | int find_child(directory, name, child) |
---|
| 530 | filerec *directory, **child; |
---|
[1679] | 531 | char *name; |
---|
| 532 | { |
---|
| 533 | filerec *ptr; |
---|
[2181] | 534 | |
---|
| 535 | *child = (filerec *) NULL; |
---|
[1732] | 536 | if ((directory->specs.st_mode & S_IFMT) != S_IFDIR) |
---|
[2181] | 537 | return DIR_NOT_DIRECTORY; |
---|
[1679] | 538 | ptr = directory->dirs; |
---|
| 539 | while (ptr) |
---|
| 540 | if (strcmp(ptr->name, name)) |
---|
| 541 | ptr = ptr->next; |
---|
| 542 | else |
---|
| 543 | break; |
---|
[2181] | 544 | if (ptr) { |
---|
| 545 | *child = ptr; |
---|
| 546 | return DIR_MATCH; |
---|
| 547 | } |
---|
[1679] | 548 | ptr = directory->files; |
---|
| 549 | while (ptr) |
---|
| 550 | if (strcmp(ptr->name, name)) |
---|
| 551 | ptr = ptr->next; |
---|
| 552 | else |
---|
| 553 | break; |
---|
[2181] | 554 | if (ptr) { |
---|
| 555 | *child = ptr; |
---|
| 556 | return DIR_MATCH; |
---|
| 557 | } |
---|
| 558 | set_status(DIR_NO_MATCH); |
---|
| 559 | return DIR_NO_MATCH; |
---|
[1679] | 560 | } |
---|
| 561 | |
---|
[1732] | 562 | |
---|
| 563 | |
---|
| 564 | |
---|
| 565 | |
---|
[2181] | 566 | int change_path(old_path, new_path) |
---|
[1679] | 567 | char *old_path, *new_path; |
---|
| 568 | { |
---|
| 569 | char next_old[MAXNAMLEN], next_new[MAXNAMLEN]; |
---|
| 570 | char rest_old[MAXPATHLEN], rest_new[MAXPATHLEN]; |
---|
[2181] | 571 | int retval; |
---|
[1679] | 572 | filerec *current; |
---|
[2181] | 573 | |
---|
[1679] | 574 | if (*old_path == '/') { |
---|
| 575 | current = &root_tree; |
---|
| 576 | old_path++; |
---|
| 577 | new_path++; |
---|
| 578 | } |
---|
| 579 | else if (! strncmp(old_path, "./", 2)) { |
---|
| 580 | current = &cwd_tree; |
---|
| 581 | old_path += 2; |
---|
| 582 | new_path += 2; |
---|
| 583 | } |
---|
| 584 | else |
---|
| 585 | current = &cwd_tree; |
---|
[2181] | 586 | |
---|
| 587 | (void) strcpy(next_old, firstpart(old_path, rest_old)); |
---|
| 588 | (void) strcpy(next_new, firstpart(new_path, rest_new)); |
---|
[1679] | 589 | while (*next_old && *next_new) { |
---|
[2181] | 590 | retval = find_child(current, next_old, ¤t); |
---|
| 591 | if (retval == DIR_MATCH) { |
---|
| 592 | if (current) { |
---|
| 593 | (void) strcpy(current->name, next_new); |
---|
| 594 | current->specified = False; |
---|
| 595 | } |
---|
| 596 | else { |
---|
| 597 | set_error(INTERNAL_ERROR); |
---|
| 598 | error("change_path"); |
---|
| 599 | return error_code; |
---|
| 600 | } |
---|
| 601 | } |
---|
| 602 | else { |
---|
| 603 | error("change_path"); |
---|
| 604 | return retval; |
---|
| 605 | } |
---|
| 606 | |
---|
| 607 | (void) strcpy(next_old, firstpart(rest_old, rest_old)); |
---|
| 608 | (void) strcpy(next_new, firstpart(rest_new, rest_new)); |
---|
[1679] | 609 | } |
---|
[2181] | 610 | return 0; |
---|
[1679] | 611 | } |
---|
| 612 | |
---|
| 613 | |
---|
[2181] | 614 | int get_leaf_path(leaf, leaf_buf) |
---|
[1679] | 615 | filerec *leaf; |
---|
| 616 | char leaf_buf[]; /* RETURN */ |
---|
| 617 | { |
---|
| 618 | char *name_ptr; |
---|
| 619 | |
---|
[2367] | 620 | name_ptr = Malloc(1); |
---|
[1732] | 621 | if (! name_ptr) { |
---|
[2181] | 622 | set_error(errno); |
---|
[2367] | 623 | error("Malloc"); |
---|
[1732] | 624 | *leaf_buf = '\0'; |
---|
[2181] | 625 | return error_code; |
---|
[1732] | 626 | } |
---|
[1679] | 627 | *name_ptr = '\0'; |
---|
| 628 | do { |
---|
[2181] | 629 | name_ptr = realloc((char *) name_ptr, (unsigned) |
---|
| 630 | (strlen(leaf->name) + strlen(name_ptr) + 2)); |
---|
[1732] | 631 | if (! name_ptr) { |
---|
[2181] | 632 | set_error(errno); |
---|
[1732] | 633 | *leaf_buf = '\0'; |
---|
[2181] | 634 | error("realloc"); |
---|
| 635 | return error_code; |
---|
[1732] | 636 | } |
---|
[2181] | 637 | (void) strcpy(leaf_buf, name_ptr); |
---|
[1679] | 638 | *name_ptr = '\0'; |
---|
[1713] | 639 | if (leaf->parent) if (leaf->parent->parent) |
---|
[2181] | 640 | (void) strcat(name_ptr, "/"); |
---|
| 641 | (void) strcat(name_ptr, leaf->name); |
---|
| 642 | (void) strcat(name_ptr, leaf_buf); |
---|
[1679] | 643 | leaf = leaf->parent; |
---|
| 644 | } while (leaf); |
---|
[2181] | 645 | (void) strcpy(leaf_buf, name_ptr); |
---|
| 646 | return 0; |
---|
[1679] | 647 | } |
---|
[1732] | 648 | |
---|
| 649 | |
---|
| 650 | |
---|
| 651 | |
---|
| 652 | |
---|
[2181] | 653 | int accumulate_names(leaf, in_strings, num) |
---|
[1732] | 654 | filerec *leaf; |
---|
[2181] | 655 | char ***in_strings; |
---|
[1732] | 656 | int *num; |
---|
| 657 | { |
---|
[2181] | 658 | char **strings; |
---|
| 659 | int retval; |
---|
[1732] | 660 | |
---|
[2181] | 661 | strings = *in_strings; |
---|
[1732] | 662 | if (leaf->specified) { |
---|
[6420] | 663 | /* |
---|
| 664 | * This array is static so that only one copy of it is allocated, |
---|
| 665 | * rather than one copy on the stack for each recursive |
---|
| 666 | * invocation of accumulate_names. |
---|
| 667 | */ |
---|
| 668 | static char newname[MAXPATHLEN]; |
---|
| 669 | |
---|
[1732] | 670 | *num += 1; |
---|
[2181] | 671 | strings = (char **) realloc((char *) strings, (unsigned) |
---|
| 672 | (sizeof(char *) * (*num))); |
---|
[1732] | 673 | if (! strings) { |
---|
[2181] | 674 | set_error(errno); |
---|
| 675 | error("realloc"); |
---|
| 676 | return error_code; |
---|
[1732] | 677 | } |
---|
[2181] | 678 | if (retval = get_leaf_path(leaf, newname)) { |
---|
| 679 | error("get_leaf_path"); |
---|
| 680 | return retval; |
---|
| 681 | } |
---|
[2221] | 682 | (void) convert_to_user_name(newname, newname); |
---|
[2367] | 683 | strings[*num - 1] = Malloc((unsigned) (strlen(newname) + 1)); |
---|
[1732] | 684 | if (! strings[*num - 1]) { |
---|
[2181] | 685 | set_error(errno); |
---|
[2367] | 686 | error("Malloc"); |
---|
[2181] | 687 | return error_code; |
---|
[1732] | 688 | } |
---|
[2181] | 689 | (void) strcpy(strings[*num - 1], newname); |
---|
[1732] | 690 | } |
---|
[2181] | 691 | if (leaf->files) if (retval = accumulate_names(leaf->files, &strings, |
---|
| 692 | num)) { |
---|
| 693 | error("accumulate_names"); |
---|
| 694 | return retval; |
---|
| 695 | } |
---|
| 696 | if (leaf->dirs) if (retval = accumulate_names(leaf->dirs, &strings, |
---|
| 697 | num)) { |
---|
| 698 | error("accumulate_names"); |
---|
| 699 | return retval; |
---|
| 700 | } |
---|
| 701 | if (leaf->next) if (retval = accumulate_names(leaf->next, &strings, |
---|
| 702 | num)) { |
---|
| 703 | error("accumulate_names"); |
---|
| 704 | return retval; |
---|
| 705 | } |
---|
[1732] | 706 | |
---|
[2181] | 707 | *in_strings = strings; |
---|
| 708 | return 0; |
---|
[1732] | 709 | } |
---|