Changeset 988 for vendor/current/source3/client/clitar.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/client/clitar.c
r746 r988 1 1 /* 2 2 Unix SMB/CIFS implementation. 3 Tar Extensions 4 Copyright (C) Ricky Poulten 1995-1998 5 Copyright (C) Richard Sharpe 1998 3 Tar backup command extension 4 Copyright (C) Aurélien Aptel 2013 6 5 7 6 This program is free software; you can redistribute it and/or modify … … 18 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 18 */ 20 /* The following changes developed by Richard Sharpe for Canon Information 21 Systems Research Australia (CISRA) 22 23 1. Restore can now restore files with long file names 24 2. Save now saves directory information so that we can restore 25 directory creation times 26 3. tar now accepts both UNIX path names and DOS path names. I prefer 27 those lovely /'s to those UGLY \'s :-) 28 4. the files to exclude can be specified as a regular expression by adding 29 an r flag to the other tar flags. Eg: 30 31 -TcrX file.tar "*.(obj|exe)" 32 33 will skip all .obj and .exe files 34 */ 35 19 20 /** 21 * # General overview of the tar extension 22 * 23 * All tar_xxx() functions work on a `struct tar` which store most of 24 * the context of the backup process. 25 * 26 * The current tar context can be accessed via the global variable 27 * `tar_ctx`. It's publicly exported as an opaque handle via 28 * tar_get_ctx(). 29 * 30 * A tar context is first configured through tar_parse_args() which 31 * can be called from either the CLI (in client.c) or the interactive 32 * session (via the cmd_tar() callback). 33 * 34 * Once the configuration is done (successfully), the context is ready 35 * for processing and tar_to_process() returns true. 36 * 37 * The next step is to call tar_process() which dispatch the 38 * processing to either tar_create() or tar_extract(), depending on 39 * the context. 40 * 41 * ## Archive creation 42 * 43 * tar_create() creates an archive using the libarchive API then 44 * 45 * - iterates on the requested paths if the context is in inclusion 46 * mode with tar_create_from_list() 47 * 48 * - or iterates on the whole share (starting from the current dir) if 49 * in exclusion mode or if no specific path were requested 50 * 51 * The do_list() function from client.c is used to list recursively 52 * the share. In particular it takes a DOS path mask (eg. \mydir\*) 53 * and a callback function which will be called with each file name 54 * and attributes. The tar callback function is get_file_callback(). 55 * 56 * The callback function checks whether the file should be skipped 57 * according the the configuration via tar_create_skip_path(). If it's 58 * not skipped it's downloaded and written to the archive in 59 * tar_get_file(). 60 * 61 * ## Archive extraction 62 * 63 * tar_extract() opens the archive and iterates on each file in 64 * it. For each file tar_extract_skip_path() checks whether it should 65 * be skipped according to the config. If it's not skipped it's 66 * uploaded on the server in tar_send_file(). 67 */ 36 68 37 69 #include "includes.h" 38 70 #include "system/filesys.h" 39 #include "clitar.h"40 71 #include "client/client_proto.h" 72 #include "client/clitar_proto.h" 41 73 #include "libsmb/libsmb.h" 42 74 43 static int clipfind(char **aret, int ret, char *tok); 44 45 typedef struct file_info_struct file_info2; 46 47 struct file_info_struct { 48 SMB_OFF_T size; 49 uint16 mode; 50 uid_t uid; 51 gid_t gid; 52 /* These times are normally kept in GMT */ 53 struct timespec mtime_ts; 54 struct timespec atime_ts; 55 struct timespec ctime_ts; 56 char *name; /* This is dynamically allocated */ 57 file_info2 *next, *prev; /* Used in the stack ... */ 75 #ifdef HAVE_LIBARCHIVE 76 77 #include <archive.h> 78 #include <archive_entry.h> 79 80 /* prepend module name and line number to debug messages */ 81 #define DBG(a, b) (DEBUG(a, ("tar:%-4d ", __LINE__)), DEBUG(a, b)) 82 83 /* preprocessor magic to stringify __LINE__ (int) */ 84 #define STR1(x) #x 85 #define STR2(x) STR1(x) 86 87 /** 88 * Number of byte in a block unit. 89 */ 90 #define TAR_BLOCK_UNIT 512 91 92 /** 93 * Default tar block size in TAR_BLOCK_UNIT. 94 */ 95 #define TAR_DEFAULT_BLOCK_SIZE 20 96 97 /** 98 * Maximum value for the blocksize field 99 */ 100 #define TAR_MAX_BLOCK_SIZE 0xffff 101 102 /** 103 * Size of the buffer used when downloading a file 104 */ 105 #define TAR_CLI_READ_SIZE 0xff00 106 107 #define TAR_DO_LIST_ATTR (FILE_ATTRIBUTE_DIRECTORY \ 108 | FILE_ATTRIBUTE_SYSTEM \ 109 | FILE_ATTRIBUTE_HIDDEN) 110 111 112 enum tar_operation { 113 TAR_NO_OPERATION, 114 TAR_CREATE, /* c flag */ 115 TAR_EXTRACT, /* x flag */ 58 116 }; 59 117 60 typedef struct { 61 file_info2 *top; 62 int items; 63 } stack; 64 65 #define SEPARATORS " \t\n\r" 66 extern time_t newer_than; 67 extern struct cli_state *cli; 68 69 /* These defines are for the do_setrattr routine, to indicate 70 * setting and reseting of file attributes in the function call */ 71 #define ATTRSET 1 72 #define ATTRRESET 0 73 74 static uint16 attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; 75 76 #ifndef CLIENT_TIMEOUT 77 #define CLIENT_TIMEOUT (30*1000) 78 #endif 79 80 static char *tarbuf, *buffer_p; 81 static int tp, ntarf, tbufsiz; 82 static double ttarf; 83 /* Incremental mode */ 84 static bool tar_inc=False; 85 /* Reset archive bit */ 86 static bool tar_reset=False; 87 /* Include / exclude mode (true=include, false=exclude) */ 88 static bool tar_excl=True; 89 /* use regular expressions for search on file names */ 90 static bool tar_re_search=False; 91 /* Do not dump anything, just calculate sizes */ 92 static bool dry_run=False; 93 /* Dump files with System attribute */ 94 static bool tar_system=True; 95 /* Dump files with Hidden attribute */ 96 static bool tar_hidden=True; 97 /* Be noisy - make a catalogue */ 98 static bool tar_noisy=True; 99 static bool tar_real_noisy=False; /* Don't want to be really noisy by default */ 100 101 char tar_type='\0'; 102 static char **cliplist=NULL; 103 static int clipn=0; 104 static bool must_free_cliplist = False; 105 extern const char *cmd_ptr; 106 107 extern bool lowercase; 108 extern uint16 cnum; 109 extern bool readbraw_supported; 110 extern int max_xmit; 111 extern int get_total_time_ms; 112 extern int get_total_size; 113 114 static int blocksize=20; 115 static int tarhandle; 116 117 static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime, 118 const char *amode, unsigned char ftype); 119 static NTSTATUS do_atar(const char *rname_in, char *lname, 120 struct file_info *finfo1); 121 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo, 122 const char *dir); 123 static void oct_it(uint64_t value, int ndgs, char *p); 124 static void fixtarname(char *tptr, const char *fp, size_t l); 125 static int dotarbuf(int f, char *b, int n); 126 static void dozerobuf(int f, int n); 127 static void dotareof(int f); 128 static void initarbuf(void); 129 130 /* restore functions */ 131 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix); 132 static long unoct(char *p, int ndgs); 133 static void do_tarput(void); 134 static void unfixtarname(char *tptr, char *fp, int l, bool first); 135 136 /* 137 * tar specific utitlities 138 */ 139 140 /******************************************************************* 141 Create a string of size size+1 (for the null) 142 *******************************************************************/ 143 144 static char *string_create_s(int size) 145 { 146 char *tmp; 147 148 tmp = (char *)SMB_MALLOC(size+1); 149 150 if (tmp == NULL) { 151 DEBUG(0, ("Out of memory in string_create_s\n")); 152 } 153 154 return(tmp); 155 } 156 157 /**************************************************************************** 158 Write a tar header to buffer 159 ****************************************************************************/ 160 161 static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime, 162 const char *amode, unsigned char ftype) 163 { 164 union hblock hb; 165 int i, chk, l; 166 char *jp; 167 168 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname)); 169 170 memset(hb.dummy, 0, sizeof(hb.dummy)); 171 172 l=strlen(aname); 173 /* We will be prepending a '.' in fixtarheader so use +2 to 174 * take care of the . and terminating zero. JRA. 175 */ 176 if (l+2 >= NAMSIZ) { 177 /* write a GNU tar style long header */ 178 char *b; 179 b = (char *)SMB_MALLOC(l+TBLOCK+100); 180 if (!b) { 181 DEBUG(0,("out of memory\n")); 182 exit(1); 183 } 184 writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L'); 185 memset(b, 0, l+TBLOCK+100); 186 fixtarname(b, aname, l+2); 187 i = strlen(b)+1; 188 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); 189 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); 190 SAFE_FREE(b); 191 } 192 193 fixtarname(hb.dbuf.name, aname, (l+2 >= NAMSIZ) ? NAMSIZ : l + 2); 194 195 if (lowercase) 196 strlower_m(hb.dbuf.name); 197 198 /* write out a "standard" tar format header */ 199 200 hb.dbuf.name[NAMSIZ-1]='\0'; 201 safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1); 202 oct_it((uint64_t)0, 8, hb.dbuf.uid); 203 oct_it((uint64_t)0, 8, hb.dbuf.gid); 204 oct_it((uint64_t) size, 13, hb.dbuf.size); 205 if (size > (uint64_t)077777777777LL) { 206 /* This is a non-POSIX compatible extention to store files 207 greater than 8GB. */ 208 209 memset(hb.dbuf.size, 0, 4); 210 hb.dbuf.size[0]=128; 211 for (i = 8; i; i--) { 212 hb.dbuf.size[i+3] = size & 0xff; 213 size >>= 8; 214 } 215 } 216 oct_it((uint64_t) mtime, 13, hb.dbuf.mtime); 217 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); 218 memset(hb.dbuf.linkname, 0, NAMSIZ); 219 hb.dbuf.linkflag=ftype; 220 221 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) 222 chk+=(0xFF & *jp++); 223 224 oct_it((uint64_t) chk, 8, hb.dbuf.chksum); 225 hb.dbuf.chksum[6] = '\0'; 226 227 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); 228 } 229 230 /**************************************************************************** 231 Read a tar header into a hblock structure, and validate 232 ***************************************************************************/ 233 234 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix) 235 { 236 long chk, fchk; 118 enum tar_selection { 119 TAR_NO_SELECTION, 120 TAR_INCLUDE, /* I and F flag, default */ 121 TAR_EXCLUDE, /* X flag */ 122 }; 123 124 struct tar { 125 TALLOC_CTX *talloc_ctx; 126 127 /* in state that needs/can be processed? */ 128 bool to_process; 129 130 /* flags */ 131 struct tar_mode { 132 enum tar_operation operation; /* create, extract */ 133 enum tar_selection selection; /* include, exclude */ 134 int blocksize; /* size in TAR_BLOCK_UNIT of a tar file block */ 135 bool hidden; /* backup hidden file? */ 136 bool system; /* backup system file? */ 137 bool incremental; /* backup _only_ archived file? */ 138 bool reset; /* unset archive bit? */ 139 bool dry; /* don't write tar file? */ 140 bool regex; /* XXX: never actually using regex... */ 141 bool verbose; /* XXX: ignored */ 142 } mode; 143 144 /* nb of bytes received */ 145 uint64_t total_size; 146 147 /* path to tar archive name */ 148 char *tar_path; 149 150 /* list of path to include or exclude */ 151 char **path_list; 152 int path_list_size; 153 154 /* archive handle */ 155 struct archive *archive; 156 }; 157 158 /** 159 * Global context imported in client.c when needed. 160 * 161 * Default options. 162 */ 163 struct tar tar_ctx = { 164 .mode.selection = TAR_INCLUDE, 165 .mode.blocksize = TAR_DEFAULT_BLOCK_SIZE, 166 .mode.hidden = true, 167 .mode.system = true, 168 .mode.incremental = false, 169 .mode.reset = false, 170 .mode.dry = false, 171 .mode.regex = false, 172 .mode.verbose = false, 173 }; 174 175 /* tar, local function */ 176 static int tar_create(struct tar* t); 177 static int tar_create_from_list(struct tar *t); 178 static int tar_extract(struct tar *t); 179 static int tar_read_inclusion_file(struct tar *t, const char* filename); 180 static int tar_send_file(struct tar *t, struct archive_entry *entry); 181 static int tar_set_blocksize(struct tar *t, int size); 182 static int tar_set_newer_than(struct tar *t, const char *filename); 183 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path); 184 static void tar_dump(struct tar *t); 185 static NTSTATUS tar_extract_skip_path(struct tar *t, 186 struct archive_entry *entry, 187 bool *_skip); 188 static TALLOC_CTX *tar_reset_mem_context(struct tar *t); 189 static void tar_free_mem_context(struct tar *t); 190 static NTSTATUS tar_create_skip_path(struct tar *t, 191 const char *fullpath, 192 const struct file_info *finfo, 193 bool *_skip); 194 195 static NTSTATUS tar_path_in_list(struct tar *t, const char *path, 196 bool reverse, bool *_is_in_list); 197 198 static int tar_get_file(struct tar *t, 199 const char *full_dos_path, 200 struct file_info *finfo); 201 202 static NTSTATUS get_file_callback(struct cli_state *cli, 203 struct file_info *finfo, 204 const char *dir); 205 206 /* utilities */ 207 static char *fix_unix_path(char *path, bool removeprefix); 208 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base); 209 static const char* skip_useless_char_in_path(const char *p); 210 static int make_remote_path(const char *full_path); 211 static int max_token (const char *str); 212 static NTSTATUS is_subpath(const char *sub, const char *full, 213 bool *_subpath_match); 214 215 /** 216 * tar_get_ctx - retrieve global tar context handle 217 */ 218 struct tar *tar_get_ctx() 219 { 220 return &tar_ctx; 221 } 222 223 /** 224 * cmd_block - interactive command to change tar blocksize 225 * 226 * Read a size from the client command line and update the current 227 * blocksize. 228 */ 229 int cmd_block(void) 230 { 231 /* XXX: from client.c */ 232 const extern char *cmd_ptr; 233 char *buf; 234 int err = 0; 235 bool ok; 236 TALLOC_CTX *ctx = talloc_new(NULL); 237 if (ctx == NULL) { 238 return 1; 239 } 240 241 ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL); 242 if (!ok) { 243 DBG(0, ("blocksize <n>\n")); 244 err = 1; 245 goto out; 246 } 247 248 ok = tar_set_blocksize(&tar_ctx, atoi(buf)); 249 if (ok) { 250 DBG(0, ("invalid blocksize\n")); 251 err = 1; 252 goto out; 253 } 254 255 DBG(2, ("blocksize is now %d\n", tar_ctx.mode.blocksize)); 256 257 out: 258 talloc_free(ctx); 259 return err; 260 } 261 262 /** 263 * cmd_tarmode - interactive command to change tar behaviour 264 * 265 * Read one or more modes from the client command line and update the 266 * current tar mode. 267 */ 268 int cmd_tarmode(void) 269 { 270 const extern char *cmd_ptr; 271 char *buf; 237 272 int i; 238 char *jp; 239 240 /* 241 * read in a "standard" tar format header - we're not that interested 242 * in that many fields, though 243 */ 244 245 /* check the checksum */ 246 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) 247 chk+=(0xFF & *jp++); 248 249 if (chk == 0) 250 return chk; 251 252 /* compensate for blanks in chksum header */ 253 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;) 254 chk-=(0xFF & *jp++); 255 256 chk += ' ' * sizeof(hb->dbuf.chksum); 257 258 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum)); 259 260 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n", 261 chk, fchk, hb->dbuf.chksum)); 262 263 if (fchk != chk) { 264 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk)); 265 dump_data(5, (uint8 *)hb - TBLOCK, TBLOCK *3); 266 return -1; 267 } 268 269 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) { 270 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name)); 271 return(-1); 272 } 273 274 safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3); 275 276 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ 277 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name, 278 strlen(hb->dbuf.name) + 1, True); 279 280 /* can't handle some links at present */ 281 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) { 282 if (hb->dbuf.linkflag == 0) { 283 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n", 284 finfo->name)); 285 } else { 286 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */ 287 /* Do nothing here at the moment. do_tarput will handle this 288 as long as the longlink gets back to it, as it has to advance 289 the buffer pointer, etc */ 290 } else { 291 DEBUG(0, ("this tar file appears to contain some kind \ 292 of link other than a GNUtar Longlink - ignoring\n")); 293 return -2; 294 } 295 } 296 } 297 298 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) || 299 (*(finfo->name+strlen(finfo->name)-1) == '\\')) { 300 finfo->mode=FILE_ATTRIBUTE_DIRECTORY; 301 } else { 302 finfo->mode=0; /* we don't care about mode at the moment, we'll 303 * just make it a regular file */ 304 } 305 306 /* 307 * Bug fix by richard@sj.co.uk 308 * 309 * REC: restore times correctly (as does tar) 310 * We only get the modification time of the file; set the creation time 311 * from the mod. time, and the access time to current time 312 */ 313 finfo->mtime_ts = finfo->ctime_ts = 314 convert_time_t_to_timespec((time_t)strtol(hb->dbuf.mtime, NULL, 8)); 315 finfo->atime_ts = convert_time_t_to_timespec(time(NULL)); 316 if ((hb->dbuf.size[0] & 0xff) == 0x80) { 317 /* This is a non-POSIX compatible extention to extract files 318 greater than 8GB. */ 319 finfo->size = 0; 320 for (i = 0; i < 8; i++) { 321 finfo->size <<= 8; 322 finfo->size |= hb->dbuf.size[i+4] & 0xff; 323 } 324 } else { 325 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size)); 326 } 327 328 return True; 329 } 330 331 /**************************************************************************** 332 Write out the tar buffer to tape or wherever 333 ****************************************************************************/ 334 335 static int dotarbuf(int f, char *b, int n) 336 { 337 int fail=1, writ=n; 338 339 if (dry_run) { 340 return writ; 341 } 342 /* This routine and the next one should be the only ones that do write()s */ 343 if (tp + n >= tbufsiz) { 344 int diff; 345 346 diff=tbufsiz-tp; 347 memcpy(tarbuf + tp, b, diff); 348 fail=fail && (1+sys_write(f, tarbuf, tbufsiz)); 349 n-=diff; 350 b+=diff; 351 tp=0; 352 353 while (n >= tbufsiz) { 354 fail=fail && (1 + sys_write(f, b, tbufsiz)); 355 n-=tbufsiz; 356 b+=tbufsiz; 357 } 358 } 359 360 if (n>0) { 361 memcpy(tarbuf+tp, b, n); 362 tp+=n; 363 } 364 365 return(fail ? writ : 0); 366 } 367 368 /**************************************************************************** 369 Write zeros to buffer / tape 370 ****************************************************************************/ 371 372 static void dozerobuf(int f, int n) 373 { 374 /* short routine just to write out n zeros to buffer - 375 * used to round files to nearest block 376 * and to do tar EOFs */ 377 378 if (dry_run) 379 return; 380 381 if (n+tp >= tbufsiz) { 382 memset(tarbuf+tp, 0, tbufsiz-tp); 383 if (sys_write(f, tarbuf, tbufsiz) != tbufsiz) { 384 DEBUG(0, ("dozerobuf: sys_write fail\n")); 385 return; 386 } 387 memset(tarbuf, 0, (tp+=n-tbufsiz)); 388 } else { 389 memset(tarbuf+tp, 0, n); 390 tp+=n; 391 } 392 } 393 394 /**************************************************************************** 395 Malloc tape buffer 396 ****************************************************************************/ 397 398 static void initarbuf(void) 399 { 400 /* initialize tar buffer */ 401 tbufsiz=blocksize*TBLOCK; 402 tarbuf=(char *)SMB_MALLOC(tbufsiz); /* FIXME: We might not get the buffer */ 403 404 /* reset tar buffer pointer and tar file counter and total dumped */ 405 tp=0; ntarf=0; ttarf=0; 406 } 407 408 /**************************************************************************** 409 Write two zero blocks at end of file 410 ****************************************************************************/ 411 412 static void dotareof(int f) 413 { 414 SMB_STRUCT_STAT stbuf; 415 /* Two zero blocks at end of file, write out full buffer */ 416 417 if (dry_run) 418 return; 419 420 (void) dozerobuf(f, TBLOCK); 421 (void) dozerobuf(f, TBLOCK); 422 423 if (sys_fstat(f, &stbuf, false) == -1) { 424 DEBUG(0, ("Couldn't stat file handle\n")); 425 return; 426 } 427 428 /* Could be a pipe, in which case S_ISREG should fail, 429 * and we should write out at full size */ 430 if (tp > 0) { 431 size_t towrite = S_ISREG(stbuf.st_ex_mode) ? tp : tbufsiz; 432 if (sys_write(f, tarbuf, towrite) != towrite) { 433 DEBUG(0,("dotareof: sys_write fail\n")); 434 } 435 } 436 } 437 438 /**************************************************************************** 439 (Un)mangle DOS pathname, make nonabsolute 440 ****************************************************************************/ 441 442 static void fixtarname(char *tptr, const char *fp, size_t l) 443 { 444 /* add a '.' to start of file name, convert from ugly dos \'s in path 445 * to lovely unix /'s :-} */ 446 *tptr++='.'; 447 l--; 448 449 StrnCpy(tptr, fp, l-1); 450 string_replace(tptr, '\\', '/'); 451 } 452 453 /**************************************************************************** 454 Convert from decimal to octal string 455 ****************************************************************************/ 456 457 static void oct_it (uint64_t value, int ndgs, char *p) 458 { 459 /* Converts long to octal string, pads with leading zeros */ 460 461 /* skip final null, but do final space */ 462 --ndgs; 463 p[--ndgs] = ' '; 464 465 /* Loop does at least one digit */ 466 do { 467 p[--ndgs] = '0' + (char) (value & 7); 468 value >>= 3; 469 } while (ndgs > 0 && value != 0); 470 471 /* Do leading zeros */ 472 while (ndgs > 0) 473 p[--ndgs] = '0'; 474 } 475 476 /**************************************************************************** 477 Convert from octal string to long 478 ***************************************************************************/ 479 480 static long unoct(char *p, int ndgs) 481 { 482 long value=0; 483 /* Converts octal string to long, ignoring any non-digit */ 484 485 while (--ndgs) { 486 if (isdigit((int)*p)) 487 value = (value << 3) | (long) (*p - '0'); 488 489 p++; 490 } 491 492 return value; 493 } 494 495 /**************************************************************************** 496 Compare two strings in a slash insensitive way, allowing s1 to match s2 497 if s1 is an "initial" string (up to directory marker). Thus, if s2 is 498 a file in any subdirectory of s1, declare a match. 499 ***************************************************************************/ 500 501 static int strslashcmp(char *s1, char *s2) 502 { 503 char *s1_0=s1; 504 505 while(*s1 && *s2 && (*s1 == *s2 || tolower_m(*s1) == tolower_m(*s2) || 506 (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) { 507 s1++; s2++; 508 } 509 510 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial" 511 string of s2. 512 */ 513 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) 514 return 0; 515 516 /* ignore trailing slash on s1 */ 517 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) 518 return 0; 519 520 /* check for s1 is an "initial" string of s2 */ 521 if ((*s2 == '/' || *s2 == '\\') && !*s1) 522 return 0; 523 524 return *s1-*s2; 525 } 526 527 /**************************************************************************** 528 Ensure a remote path exists (make if necessary) 529 ***************************************************************************/ 530 531 static bool ensurepath(const char *fname) 532 { 533 /* *must* be called with buffer ready malloc'ed */ 534 /* ensures path exists */ 535 536 char *partpath, *ffname; 537 const char *p=fname; 538 char *basehack; 539 char *saveptr; 540 541 DEBUG(5, ( "Ensurepath called with: %s\n", fname)); 542 543 partpath = string_create_s(strlen(fname)); 544 ffname = string_create_s(strlen(fname)); 545 546 if ((partpath == NULL) || (ffname == NULL)){ 547 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname)); 548 SAFE_FREE(partpath); 549 SAFE_FREE(ffname); 550 return(False); 551 } 552 553 *partpath = 0; 554 555 /* fname copied to ffname so can strtok_r */ 556 557 safe_strcpy(ffname, fname, strlen(fname)); 558 559 /* do a `basename' on ffname, so don't try and make file name directory */ 560 if ((basehack=strrchr_m(ffname, '\\')) == NULL) { 561 SAFE_FREE(partpath); 562 SAFE_FREE(ffname); 563 return True; 564 } else { 565 *basehack='\0'; 566 } 567 568 p=strtok_r(ffname, "\\", &saveptr); 569 570 while (p) { 571 safe_strcat(partpath, p, strlen(fname) + 1); 572 573 if (!NT_STATUS_IS_OK(cli_chkpath(cli, partpath))) { 574 if (!NT_STATUS_IS_OK(cli_mkdir(cli, partpath))) { 575 SAFE_FREE(partpath); 576 SAFE_FREE(ffname); 577 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli))); 578 return False; 579 } else { 580 DEBUG(3, ("mkdirhiering %s\n", partpath)); 581 } 582 } 583 584 safe_strcat(partpath, "\\", strlen(fname) + 1); 585 p = strtok_r(NULL, "/\\", &saveptr); 586 } 587 588 SAFE_FREE(partpath); 589 SAFE_FREE(ffname); 590 return True; 591 } 592 593 static int padit(char *buf, uint64_t bufsize, uint64_t padsize) 594 { 595 int berr= 0; 596 int bytestowrite; 597 598 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize)); 599 memset(buf, 0, (size_t)bufsize); 600 while( !berr && padsize > 0 ) { 601 bytestowrite= (int)MIN(bufsize, padsize); 602 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite; 603 padsize -= bytestowrite; 604 } 605 606 return berr; 607 } 608 609 static void do_setrattr(char *name, uint16 attr, int set) 610 { 611 uint16 oldattr; 612 613 if (!NT_STATUS_IS_OK(cli_getatr(cli, name, &oldattr, NULL, NULL))) { 614 return; 615 } 616 617 if (set == ATTRSET) { 618 attr |= oldattr; 619 } else { 620 attr = oldattr & ~attr; 621 } 622 623 if (!NT_STATUS_IS_OK(cli_setatr(cli, name, attr, 0))) { 624 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli))); 625 } 626 } 627 628 /**************************************************************************** 629 append one remote file to the tar file 630 ***************************************************************************/ 631 632 static NTSTATUS do_atar(const char *rname_in, char *lname, 633 struct file_info *finfo1) 634 { 635 uint16_t fnum = (uint16_t)-1; 636 uint64_t nread=0; 637 char ftype; 638 file_info2 finfo; 639 bool shallitime=True; 640 char *data = NULL; 641 int read_size = 65520; 642 int datalen=0; 643 char *rname = NULL; 644 TALLOC_CTX *ctx = talloc_stackframe(); 645 NTSTATUS status = NT_STATUS_OK; 646 struct timespec tp_start; 647 648 clock_gettime_mono(&tp_start); 649 650 data = SMB_MALLOC_ARRAY(char, read_size); 651 if (!data) { 652 DEBUG(0,("do_atar: out of memory.\n")); 653 status = NT_STATUS_NO_MEMORY; 654 goto cleanup; 655 } 656 657 ftype = '0'; /* An ordinary file ... */ 658 659 ZERO_STRUCT(finfo); 660 661 finfo.size = finfo1 -> size; 662 finfo.mode = finfo1 -> mode; 663 finfo.uid = finfo1 -> uid; 664 finfo.gid = finfo1 -> gid; 665 finfo.mtime_ts = finfo1 -> mtime_ts; 666 finfo.atime_ts = finfo1 -> atime_ts; 667 finfo.ctime_ts = finfo1 -> ctime_ts; 668 669 if (dry_run) { 670 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1->name, 671 (double)finfo.size)); 672 shallitime=0; 673 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); 674 ntarf++; 675 goto cleanup; 676 } 677 678 rname = clean_name(ctx, rname_in); 679 if (!rname) { 680 status = NT_STATUS_NO_MEMORY; 681 goto cleanup; 682 } 683 684 status = cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum); 685 if (!NT_STATUS_IS_OK(status)) { 686 DEBUG(0,("%s opening remote file %s (%s)\n", 687 cli_errstr(cli),rname, client_get_cur_dir())); 688 goto cleanup; 689 } 690 691 finfo.name = string_create_s(strlen(rname)); 692 if (finfo.name == NULL) { 693 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n")); 694 status = NT_STATUS_NO_MEMORY; 695 goto cleanup; 696 } 697 698 safe_strcpy(finfo.name,rname, strlen(rname)); 699 700 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); 701 702 if (tar_inc && !(finfo.mode & FILE_ATTRIBUTE_ARCHIVE)) { 703 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name)); 704 shallitime=0; 705 } else if (!tar_system && (finfo.mode & FILE_ATTRIBUTE_SYSTEM)) { 706 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name)); 707 shallitime=0; 708 } else if (!tar_hidden && (finfo.mode & FILE_ATTRIBUTE_HIDDEN)) { 709 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name)); 710 shallitime=0; 711 } else { 712 bool wrote_tar_header = False; 713 714 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s", 715 finfo.name, (double)finfo.size, lname)); 716 717 do { 718 719 DEBUG(3,("nread=%.0f\n",(double)nread)); 720 721 datalen = cli_read(cli, fnum, data, nread, read_size); 722 723 if (datalen == -1) { 724 DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli))); 725 status = cli_nt_error(cli); 273 TALLOC_CTX *ctx; 274 275 struct { 276 const char *cmd; 277 bool *p; 278 bool value; 279 } table[] = { 280 {"full", &tar_ctx.mode.incremental, false}, 281 {"inc", &tar_ctx.mode.incremental, true }, 282 {"reset", &tar_ctx.mode.reset, true }, 283 {"noreset", &tar_ctx.mode.reset, false}, 284 {"system", &tar_ctx.mode.system, true }, 285 {"nosystem", &tar_ctx.mode.system, false}, 286 {"hidden", &tar_ctx.mode.hidden, true }, 287 {"nohidden", &tar_ctx.mode.hidden, false}, 288 {"verbose", &tar_ctx.mode.verbose, true }, 289 {"noquiet", &tar_ctx.mode.verbose, true }, 290 {"quiet", &tar_ctx.mode.verbose, false}, 291 {"noverbose", &tar_ctx.mode.verbose, false}, 292 }; 293 294 ctx = talloc_new(NULL); 295 if (ctx == NULL) { 296 return 1; 297 } 298 299 while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) { 300 for (i = 0; i < ARRAY_SIZE(table); i++) { 301 if (strequal(table[i].cmd, buf)) { 302 *table[i].p = table[i].value; 726 303 break; 727 304 } 728 729 nread += datalen; 730 731 /* Only if the first read succeeds, write out the tar header. */ 732 if (!wrote_tar_header) { 733 /* write a tar header, don't bother with mode - just set to 100644 */ 734 writetarheader(tarhandle, rname, finfo.size, 735 finfo.mtime_ts.tv_sec, "100644 \0", ftype); 736 wrote_tar_header = True; 305 } 306 307 if (i == ARRAY_SIZE(table)) 308 DBG(0, ("tarmode: unrecognised option %s\n", buf)); 309 } 310 311 DBG(0, ("tarmode is now %s, %s, %s, %s, %s\n", 312 tar_ctx.mode.incremental ? "incremental" : "full", 313 tar_ctx.mode.system ? "system" : "nosystem", 314 tar_ctx.mode.hidden ? "hidden" : "nohidden", 315 tar_ctx.mode.reset ? "reset" : "noreset", 316 tar_ctx.mode.verbose ? "verbose" : "quiet")); 317 318 talloc_free(ctx); 319 return 0; 320 } 321 322 /** 323 * cmd_tar - interactive command to start a tar backup/restoration 324 * 325 * Check presence of argument, parse them and handle the request. 326 */ 327 int cmd_tar(void) 328 { 329 const extern char *cmd_ptr; 330 const char *flag; 331 const char **val; 332 char *buf; 333 int maxtok = max_token(cmd_ptr); 334 int i = 0; 335 int err = 0; 336 bool ok; 337 int rc; 338 TALLOC_CTX *ctx = talloc_new(NULL); 339 if (ctx == NULL) { 340 return 1; 341 } 342 343 ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL); 344 if (!ok) { 345 DBG(0, ("tar <c|x>[IXFbganN] [options] <tar file> [path list]\n")); 346 err = 1; 347 goto out; 348 } 349 350 flag = buf; 351 val = talloc_array(ctx, const char *, maxtok); 352 if (val == NULL) { 353 err = 1; 354 goto out; 355 } 356 357 while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) { 358 val[i++] = buf; 359 } 360 361 rc = tar_parse_args(&tar_ctx, flag, val, i); 362 if (rc != 0) { 363 DBG(0, ("parse_args failed\n")); 364 err = 1; 365 goto out; 366 } 367 368 rc = tar_process(&tar_ctx); 369 if (rc != 0) { 370 DBG(0, ("tar_process failed\n")); 371 err = 1; 372 goto out; 373 } 374 375 out: 376 talloc_free(ctx); 377 return err; 378 } 379 380 381 /** 382 * tar_parse_args - parse and set tar command line arguments 383 * @flag: string pointing to tar options 384 * @val: number of tar arguments 385 * @valsize: table of arguments after the flags (number of element in val) 386 * 387 * tar arguments work in a weird way. For each flag f that takes a 388 * value v, the user is supposed to type: 389 * 390 * on the CLI: 391 * -Tf1f2f3 v1 v2 v3 TARFILE PATHS... 392 * 393 * in the interactive session: 394 * tar f1f2f3 v1 v2 v3 TARFILE PATHS... 395 * 396 * @flag has only flags (eg. "f1f2f3") and @val has the arguments 397 * (values) following them (eg. ["v1", "v2", "v3", "TARFILE", "PATH1", 398 * "PATH2"]). 399 * 400 * There are only 2 flags that take an arg: b and N. The other flags 401 * just change the semantic of PATH or TARFILE. 402 * 403 * PATH can be a list of included/excluded paths, the path to a file 404 * containing a list of included/excluded paths to use (F flag). If no 405 * PATH is provided, the whole share is used (/). 406 */ 407 int tar_parse_args(struct tar* t, 408 const char *flag, 409 const char **val, 410 int valsize) 411 { 412 TALLOC_CTX *ctx; 413 bool do_read_list = false; 414 /* index of next value to use */ 415 int ival = 0; 416 int rc; 417 418 if (t == NULL) { 419 DBG(0, ("Invalid tar context\n")); 420 return 1; 421 } 422 423 ctx = tar_reset_mem_context(t); 424 if (ctx == NULL) { 425 return 1; 426 } 427 /* 428 * Reset back some options - could be from interactive version 429 * all other modes are left as they are 430 */ 431 t->mode.operation = TAR_NO_OPERATION; 432 t->mode.selection = TAR_NO_SELECTION; 433 t->mode.dry = false; 434 t->to_process = false; 435 t->total_size = 0; 436 437 while (flag[0] != '\0') { 438 switch(flag[0]) { 439 /* operation */ 440 case 'c': 441 if (t->mode.operation != TAR_NO_OPERATION) { 442 printf("Tar must be followed by only one of c or x.\n"); 443 return 1; 737 444 } 738 739 /* if file size has increased since we made file size query, truncate 740 read so tar header for this file will be correct. 741 */ 742 743 if (nread > finfo.size) { 744 datalen -= nread - finfo.size; 745 DEBUG(0,("File size change - truncating %s to %.0f bytes\n", 746 finfo.name, (double)finfo.size)); 445 t->mode.operation = TAR_CREATE; 446 break; 447 case 'x': 448 if (t->mode.operation != TAR_NO_OPERATION) { 449 printf("Tar must be followed by only one of c or x.\n"); 450 return 1; 747 451 } 748 749 /* add received bits of file to buffer - dotarbuf will750 * write out in 512 byte intervals */ 751 752 if (dotarbuf(tarhandle,data,datalen) != datalen) {753 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));754 status = map_nt_error_from_unix(errno);755 break;452 t->mode.operation = TAR_EXTRACT; 453 break; 454 455 /* selection */ 456 case 'I': 457 if (t->mode.selection != TAR_NO_SELECTION) { 458 DBG(0,("Only one of I,X,F must be specified\n")); 459 return 1; 756 460 } 757 758 if ( (datalen == 0) && (finfo.size != 0) ) { 759 status = NT_STATUS_UNSUCCESSFUL; 760 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname)); 761 break; 461 t->mode.selection = TAR_INCLUDE; 462 break; 463 case 'X': 464 if (t->mode.selection != TAR_NO_SELECTION) { 465 DBG(0,("Only one of I,X,F must be specified\n")); 466 return 1; 762 467 } 763 764 datalen=0; 765 } while ( nread < finfo.size ); 766 767 if (wrote_tar_header) { 768 /* pad tar file with zero's if we couldn't get entire file */ 769 if (nread < finfo.size) { 770 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n", 771 (double)finfo.size, (int)nread)); 772 if (padit(data, (uint64_t)sizeof(data), finfo.size - nread)) { 773 status = map_nt_error_from_unix(errno); 774 DEBUG(0,("Error writing tar file - %s\n", strerror(errno))); 775 } 468 t->mode.selection = TAR_EXCLUDE; 469 break; 470 case 'F': 471 if (t->mode.selection != TAR_NO_SELECTION) { 472 DBG(0,("Only one of I,X,F must be specified\n")); 473 return 1; 776 474 } 777 778 /* round tar file to nearest block */ 779 if (finfo.size % TBLOCK) 780 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); 781 782 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); 783 ntarf++; 475 t->mode.selection = TAR_INCLUDE; 476 do_read_list = true; 477 break; 478 479 /* blocksize */ 480 case 'b': 481 if (ival >= valsize) { 482 DBG(0, ("Option b must be followed by a blocksize\n")); 483 return 1; 484 } 485 486 if (tar_set_blocksize(t, atoi(val[ival]))) { 487 DBG(0, ("Option b must be followed by a valid blocksize\n")); 488 return 1; 489 } 490 491 ival++; 492 break; 493 494 /* incremental mode */ 495 case 'g': 496 t->mode.incremental = true; 497 break; 498 499 /* newer than */ 500 case 'N': 501 if (ival >= valsize) { 502 DBG(0, ("Option N must be followed by valid file name\n")); 503 return 1; 504 } 505 506 if (tar_set_newer_than(t, val[ival])) { 507 DBG(0,("Error setting newer-than time\n")); 508 return 1; 509 } 510 511 ival++; 512 break; 513 514 /* reset mode */ 515 case 'a': 516 t->mode.reset = true; 517 break; 518 519 /* verbose */ 520 case 'q': 521 t->mode.verbose = true; 522 break; 523 524 /* regex match */ 525 case 'r': 526 t->mode.regex = true; 527 break; 528 529 /* dry run mode */ 530 case 'n': 531 if (t->mode.operation != TAR_CREATE) { 532 DBG(0, ("n is only meaningful when creating a tar-file\n")); 533 return 1; 534 } 535 536 t->mode.dry = true; 537 DBG(0, ("dry_run set\n")); 538 break; 539 540 default: 541 DBG(0,("Unknown tar option\n")); 542 return 1; 543 } 544 545 flag++; 546 } 547 548 /* no selection given? default selection is include */ 549 if (t->mode.selection == TAR_NO_SELECTION) { 550 t->mode.selection = TAR_INCLUDE; 551 } 552 553 if (valsize - ival < 1) { 554 DBG(0, ("No tar file given.\n")); 555 return 1; 556 } 557 558 /* handle TARFILE */ 559 t->tar_path = talloc_strdup(ctx, val[ival]); 560 if (t->tar_path == NULL) { 561 return 1; 562 } 563 ival++; 564 565 /* 566 * Make sure that dbf points to stderr if we are using stdout for 567 * tar output 568 */ 569 if (t->mode.operation == TAR_CREATE && strequal(t->tar_path, "-")) { 570 setup_logging("smbclient", DEBUG_STDERR); 571 } 572 573 /* handle PATHs... */ 574 575 /* flag F -> read file list */ 576 if (do_read_list) { 577 if (valsize - ival != 1) { 578 DBG(0,("Option F must be followed by exactly one filename.\n")); 579 return 1; 580 } 581 582 rc = tar_read_inclusion_file(t, val[ival]); 583 if (rc != 0) { 584 return 1; 585 } 586 ival++; 587 /* otherwise store all the PATHs on the command line */ 588 } else { 589 int i; 590 for (i = ival; i < valsize; i++) { 591 NTSTATUS status; 592 status = tar_add_selection_path(t, val[i]); 593 if (!NT_STATUS_IS_OK(status)) { 594 return 1; 595 } 596 } 597 } 598 599 t->to_process = true; 600 tar_dump(t); 601 return 0; 602 } 603 604 /** 605 * tar_process - start processing archive 606 * 607 * The talloc context of the fields is freed at the end of the call. 608 */ 609 int tar_process(struct tar *t) 610 { 611 int rc = 0; 612 613 if (t == NULL) { 614 DBG(0, ("Invalid tar context\n")); 615 return 1; 616 } 617 618 switch(t->mode.operation) { 619 case TAR_EXTRACT: 620 rc = tar_extract(t); 621 break; 622 case TAR_CREATE: 623 rc = tar_create(t); 624 break; 625 default: 626 DBG(0, ("Invalid tar state\n")); 627 rc = 1; 628 } 629 630 t->to_process = false; 631 tar_free_mem_context(t); 632 DBG(5, ("tar_process done, err = %d\n", rc)); 633 return rc; 634 } 635 636 /** 637 * tar_create - create archive and fetch files 638 */ 639 static int tar_create(struct tar* t) 640 { 641 int r; 642 int err = 0; 643 NTSTATUS status; 644 const char *mask; 645 TALLOC_CTX *ctx = talloc_new(NULL); 646 if (ctx == NULL) { 647 return 1; 648 } 649 650 t->archive = archive_write_new(); 651 652 if (!t->mode.dry) { 653 const int bsize = t->mode.blocksize * TAR_BLOCK_UNIT; 654 r = archive_write_set_bytes_per_block(t->archive, bsize); 655 if (r != ARCHIVE_OK) { 656 DBG(0, ("Can't use a block size of %d bytes", bsize)); 657 err = 1; 658 goto out; 659 } 660 661 /* 662 * Use PAX restricted format which is not the most 663 * conservative choice but has useful extensions and is widely 664 * supported 665 */ 666 r = archive_write_set_format_pax_restricted(t->archive); 667 if (r != ARCHIVE_OK) { 668 DBG(0, ("Can't use pax restricted format: %s\n", 669 archive_error_string(t->archive))); 670 err = 1; 671 goto out; 672 } 673 674 if (strequal(t->tar_path, "-")) { 675 r = archive_write_open_fd(t->archive, STDOUT_FILENO); 784 676 } else { 785 DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo.name)); 786 shallitime=0; 677 r = archive_write_open_filename(t->archive, t->tar_path); 678 } 679 680 if (r != ARCHIVE_OK) { 681 DBG(0, ("Can't open %s: %s\n", t->tar_path, 682 archive_error_string(t->archive))); 683 err = 1; 684 goto out_close; 685 } 686 } 687 688 /* 689 * In inclusion mode, iterate on the inclusion list 690 */ 691 if (t->mode.selection == TAR_INCLUDE && t->path_list_size > 0) { 692 if (tar_create_from_list(t)) { 693 err = 1; 694 goto out_close; 695 } 696 } else { 697 mask = talloc_asprintf(ctx, "%s\\*", client_get_cur_dir()); 698 if (mask == NULL) { 699 err = 1; 700 goto out_close; 701 } 702 DBG(5, ("tar_process do_list with mask: %s\n", mask)); 703 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); 704 if (!NT_STATUS_IS_OK(status)) { 705 DBG(0, ("do_list fail %s\n", nt_errstr(status))); 706 err = 1; 707 goto out_close; 708 } 709 } 710 711 out_close: 712 DBG(0, ("Total bytes received: %" PRIu64 "\n", t->total_size)); 713 714 if (!t->mode.dry) { 715 r = archive_write_close(t->archive); 716 if (r != ARCHIVE_OK) { 717 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); 718 err = 1; 719 goto out; 720 } 721 } 722 out: 723 #ifdef HAVE_ARCHIVE_READ_FREE 724 archive_write_free(t->archive); 725 #else 726 archive_write_finish(t->archive); 727 #endif 728 talloc_free(ctx); 729 return err; 730 } 731 732 /** 733 * tar_create_from_list - fetch from path list in include mode 734 */ 735 static int tar_create_from_list(struct tar *t) 736 { 737 int err = 0; 738 NTSTATUS status; 739 char *base; 740 const char *path, *mask, *start_dir; 741 int i; 742 TALLOC_CTX *ctx = talloc_new(NULL); 743 if (ctx == NULL) { 744 return 1; 745 } 746 747 start_dir = talloc_strdup(ctx, client_get_cur_dir()); 748 if (start_dir == NULL) { 749 err = 1; 750 goto out; 751 } 752 753 for (i = 0; i < t->path_list_size; i++) { 754 path = t->path_list[i]; 755 base = NULL; 756 status = path_base_name(ctx, path, &base); 757 if (!NT_STATUS_IS_OK(status)) { 758 err = 1; 759 goto out; 760 } 761 mask = talloc_asprintf(ctx, "%s\\%s", 762 client_get_cur_dir(), path); 763 if (mask == NULL) { 764 err = 1; 765 goto out; 766 } 767 768 DBG(5, ("incl. path='%s', base='%s', mask='%s'\n", 769 path, base ? base : "NULL", mask)); 770 771 if (base != NULL) { 772 base = talloc_asprintf(ctx, "%s%s\\", 773 client_get_cur_dir(), base); 774 if (base == NULL) { 775 err = 1; 776 goto out; 777 } 778 DBG(5, ("cd '%s' before do_list\n", base)); 779 client_set_cur_dir(base); 780 } 781 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); 782 if (base != NULL) { 783 client_set_cur_dir(start_dir); 784 } 785 if (!NT_STATUS_IS_OK(status)) { 786 DBG(0, ("do_list failed on %s (%s)\n", path, nt_errstr(status))); 787 err = 1; 788 goto out; 789 } 790 } 791 792 out: 793 talloc_free(ctx); 794 return err; 795 } 796 797 /** 798 * get_file_callback - do_list callback 799 * 800 * Callback for client.c do_list(). Called for each file found on the 801 * share matching do_list mask. Recursively call do_list() with itself 802 * as callback when the current file is a directory. 803 */ 804 static NTSTATUS get_file_callback(struct cli_state *cli, 805 struct file_info *finfo, 806 const char *dir) 807 { 808 NTSTATUS status = NT_STATUS_OK; 809 char *remote_name; 810 const char *initial_dir = client_get_cur_dir(); 811 bool skip = false; 812 int rc; 813 TALLOC_CTX *ctx = talloc_new(NULL); 814 if (ctx == NULL) { 815 return NT_STATUS_NO_MEMORY; 816 } 817 818 remote_name = talloc_asprintf(ctx, "%s%s", initial_dir, finfo->name); 819 if (remote_name == NULL) { 820 status = NT_STATUS_NO_MEMORY; 821 goto out; 822 } 823 824 if (strequal(finfo->name, "..") || strequal(finfo->name, ".")) { 825 goto out; 826 } 827 828 status = tar_create_skip_path(&tar_ctx, remote_name, finfo, &skip); 829 if (!NT_STATUS_IS_OK(status)) { 830 goto out; 831 } 832 833 if (skip) { 834 DBG(5, ("--- %s\n", remote_name)); 835 status = NT_STATUS_OK; 836 goto out; 837 } 838 839 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) { 840 char *old_dir; 841 char *new_dir; 842 char *mask; 843 844 old_dir = talloc_strdup(ctx, initial_dir); 845 new_dir = talloc_asprintf(ctx, "%s%s\\", 846 initial_dir, finfo->name); 847 if ((old_dir == NULL) || (new_dir == NULL)) { 848 status = NT_STATUS_NO_MEMORY; 849 goto out; 850 } 851 mask = talloc_asprintf(ctx, "%s*", new_dir); 852 if (mask == NULL) { 853 status = NT_STATUS_NO_MEMORY; 854 goto out; 855 } 856 857 rc = tar_get_file(&tar_ctx, remote_name, finfo); 858 if (rc != 0) { 787 859 status = NT_STATUS_UNSUCCESSFUL; 788 } 789 } 790 791 cli_close(cli, fnum); 792 fnum = -1; 793 794 if (shallitime) { 795 struct timespec tp_end; 796 int this_time; 797 798 /* if shallitime is true then we didn't skip */ 799 if (tar_reset && !dry_run) 800 (void) do_setrattr(finfo.name, FILE_ATTRIBUTE_ARCHIVE, ATTRRESET); 801 802 clock_gettime_mono(&tp_end); 803 this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000000; 804 get_total_time_ms += this_time; 805 get_total_size += finfo.size; 806 807 if (tar_noisy) { 808 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n", 809 (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)), 810 finfo.name)); 811 } 812 813 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */ 814 DEBUG(3,("(%g kb/s) (average %g kb/s)\n", 815 finfo.size / MAX(0.001, (1.024*this_time)), 816 get_total_size / MAX(0.001, (1.024*get_total_time_ms)))); 817 } 818 819 cleanup: 820 821 if (fnum != (uint16_t)-1) { 822 cli_close(cli, fnum); 823 fnum = -1; 824 } 825 TALLOC_FREE(ctx); 826 SAFE_FREE(data); 860 goto out; 861 } 862 863 client_set_cur_dir(new_dir); 864 do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true); 865 client_set_cur_dir(old_dir); 866 } else { 867 rc = tar_get_file(&tar_ctx, remote_name, finfo); 868 if (rc != 0) { 869 status = NT_STATUS_UNSUCCESSFUL; 870 goto out; 871 } 872 } 873 874 out: 875 talloc_free(ctx); 827 876 return status; 828 877 } 829 878 830 /**************************************************************************** 831 Append single file to tar file (or not) 832 ***************************************************************************/ 833 834 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo, 835 const char *dir) 836 { 837 TALLOC_CTX *ctx = talloc_stackframe(); 879 /** 880 * tar_get_file - fetch a remote file to the local archive 881 * @full_dos_path: path to the file to fetch 882 * @finfo: attributes of the file to fetch 883 */ 884 static int tar_get_file(struct tar *t, 885 const char *full_dos_path, 886 struct file_info *finfo) 887 { 888 extern struct cli_state *cli; 889 NTSTATUS status; 890 struct archive_entry *entry; 891 char *full_unix_path; 892 char buf[TAR_CLI_READ_SIZE]; 893 size_t len; 894 uint64_t off = 0; 895 uint16_t remote_fd = (uint16_t)-1; 896 int err = 0, r; 897 const bool isdir = finfo->mode & FILE_ATTRIBUTE_DIRECTORY; 898 TALLOC_CTX *ctx = talloc_new(NULL); 899 if (ctx == NULL) { 900 return 1; 901 } 902 903 DBG(5, ("+++ %s\n", full_dos_path)); 904 905 t->total_size += finfo->size; 906 907 if (t->mode.dry) { 908 goto out; 909 } 910 911 if (t->mode.reset) { 912 /* ignore return value: server might not store DOS attributes */ 913 set_remote_attr(full_dos_path, FILE_ATTRIBUTE_ARCHIVE, ATTR_UNSET); 914 } 915 916 full_unix_path = talloc_asprintf(ctx, ".%s", full_dos_path); 917 if (full_unix_path == NULL) { 918 err = 1; 919 goto out; 920 } 921 string_replace(full_unix_path, '\\', '/'); 922 entry = archive_entry_new(); 923 archive_entry_copy_pathname(entry, full_unix_path); 924 archive_entry_set_filetype(entry, isdir ? AE_IFDIR : AE_IFREG); 925 archive_entry_set_atime(entry, 926 finfo->atime_ts.tv_sec, 927 finfo->atime_ts.tv_nsec); 928 archive_entry_set_mtime(entry, 929 finfo->mtime_ts.tv_sec, 930 finfo->mtime_ts.tv_nsec); 931 archive_entry_set_ctime(entry, 932 finfo->ctime_ts.tv_sec, 933 finfo->ctime_ts.tv_nsec); 934 archive_entry_set_perm(entry, isdir ? 0755 : 0644); 935 /* 936 * check if we can safely cast unsigned file size to libarchive 937 * signed size. Very unlikely problem (>9 exabyte file) 938 */ 939 if (finfo->size > INT64_MAX) { 940 DBG(0, ("Remote file %s too big\n", full_dos_path)); 941 goto out_entry; 942 } 943 944 archive_entry_set_size(entry, (int64_t)finfo->size); 945 946 r = archive_write_header(t->archive, entry); 947 if (r != ARCHIVE_OK) { 948 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); 949 err = 1; 950 goto out_entry; 951 } 952 953 if (isdir) { 954 DBG(5, ("get_file skip dir %s\n", full_dos_path)); 955 goto out_entry; 956 } 957 958 status = cli_open(cli, full_dos_path, O_RDONLY, DENY_NONE, &remote_fd); 959 if (!NT_STATUS_IS_OK(status)) { 960 DBG(0,("%s opening remote file %s\n", 961 nt_errstr(status), full_dos_path)); 962 goto out_entry; 963 } 964 965 do { 966 status = cli_read(cli, remote_fd, buf, off, sizeof(buf), &len); 967 if (!NT_STATUS_IS_OK(status)) { 968 DBG(0,("Error reading file %s : %s\n", 969 full_dos_path, nt_errstr(status))); 970 err = 1; 971 goto out_close; 972 } 973 974 off += len; 975 976 r = archive_write_data(t->archive, buf, len); 977 if (r < 0) { 978 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); 979 err = 1; 980 goto out_close; 981 } 982 983 } while (off < finfo->size); 984 985 out_close: 986 cli_close(cli, remote_fd); 987 988 out_entry: 989 archive_entry_free(entry); 990 991 out: 992 talloc_free(ctx); 993 return err; 994 } 995 996 /** 997 * tar_extract - open archive and send files. 998 */ 999 static int tar_extract(struct tar *t) 1000 { 1001 int err = 0; 1002 int r; 1003 struct archive_entry *entry; 1004 const size_t bsize = t->mode.blocksize * TAR_BLOCK_UNIT; 1005 int rc; 1006 1007 t->archive = archive_read_new(); 1008 archive_read_support_format_all(t->archive); 1009 #ifdef HAVE_ARCHIVE_READ_SUPPORT_FILTER_ALL 1010 archive_read_support_filter_all(t->archive); 1011 #endif 1012 1013 if (strequal(t->tar_path, "-")) { 1014 r = archive_read_open_fd(t->archive, STDIN_FILENO, bsize); 1015 } else { 1016 r = archive_read_open_filename(t->archive, t->tar_path, bsize); 1017 } 1018 1019 if (r != ARCHIVE_OK) { 1020 DBG(0, ("Can't open %s : %s\n", t->tar_path, 1021 archive_error_string(t->archive))); 1022 err = 1; 1023 goto out; 1024 } 1025 1026 for (;;) { 1027 NTSTATUS status; 1028 bool skip; 1029 r = archive_read_next_header(t->archive, &entry); 1030 if (r == ARCHIVE_EOF) { 1031 break; 1032 } 1033 if (r == ARCHIVE_WARN) { 1034 DBG(0, ("Warning: %s\n", archive_error_string(t->archive))); 1035 } 1036 if (r == ARCHIVE_FATAL) { 1037 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); 1038 err = 1; 1039 goto out; 1040 } 1041 1042 status = tar_extract_skip_path(t, entry, &skip); 1043 if (!NT_STATUS_IS_OK(status)) { 1044 err = 1; 1045 goto out; 1046 } 1047 if (skip) { 1048 DBG(5, ("--- %s\n", archive_entry_pathname(entry))); 1049 continue; 1050 } 1051 1052 DBG(5, ("+++ %s\n", archive_entry_pathname(entry))); 1053 1054 rc = tar_send_file(t, entry); 1055 if (rc != 0) { 1056 err = 1; 1057 goto out; 1058 } 1059 } 1060 1061 out: 1062 #ifdef HAVE_ARCHIVE_READ_FREE 1063 r = archive_read_free(t->archive); 1064 #else 1065 r = archive_read_finish(t->archive); 1066 #endif 1067 if (r != ARCHIVE_OK) { 1068 DBG(0, ("Can't close %s : %s\n", t->tar_path, 1069 archive_error_string(t->archive))); 1070 err = 1; 1071 } 1072 return err; 1073 } 1074 1075 /** 1076 * tar_send_file - send @entry to the remote server 1077 * @entry: current archive entry 1078 * 1079 * Handle the creation of the parent directories and transfer the 1080 * entry to a new remote file. 1081 */ 1082 static int tar_send_file(struct tar *t, struct archive_entry *entry) 1083 { 1084 extern struct cli_state *cli; 1085 char *dos_path; 1086 char *full_path; 1087 NTSTATUS status; 1088 uint16_t remote_fd = (uint16_t) -1; 1089 int err = 0; 1090 int flags = O_RDWR | O_CREAT | O_TRUNC; 1091 mode_t mode = archive_entry_filetype(entry); 1092 int rc; 1093 TALLOC_CTX *ctx = talloc_new(NULL); 1094 if (ctx == NULL) { 1095 return 1; 1096 } 1097 1098 dos_path = talloc_strdup(ctx, archive_entry_pathname(entry)); 1099 if (dos_path == NULL) { 1100 err = 1; 1101 goto out; 1102 } 1103 fix_unix_path(dos_path, true); 1104 1105 full_path = talloc_strdup(ctx, client_get_cur_dir()); 1106 if (full_path == NULL) { 1107 err = 1; 1108 goto out; 1109 } 1110 full_path = talloc_strdup_append(full_path, dos_path); 1111 if (full_path == NULL) { 1112 err = 1; 1113 goto out; 1114 } 1115 1116 if (mode != AE_IFREG && mode != AE_IFDIR) { 1117 DBG(0, ("Skipping non-dir & non-regular file %s\n", full_path)); 1118 goto out; 1119 } 1120 1121 rc = make_remote_path(full_path); 1122 if (rc != 0) { 1123 err = 1; 1124 goto out; 1125 } 1126 1127 if (mode == AE_IFDIR) { 1128 goto out; 1129 } 1130 1131 status = cli_open(cli, full_path, flags, DENY_NONE, &remote_fd); 1132 if (!NT_STATUS_IS_OK(status)) { 1133 DBG(0, ("Error opening remote file %s: %s\n", 1134 full_path, nt_errstr(status))); 1135 err = 1; 1136 goto out; 1137 } 1138 1139 for (;;) { 1140 const void *buf; 1141 size_t len; 1142 off_t off; 1143 int r; 1144 1145 r = archive_read_data_block(t->archive, &buf, &len, &off); 1146 if (r == ARCHIVE_EOF) { 1147 break; 1148 } 1149 if (r == ARCHIVE_WARN) { 1150 DBG(0, ("Warning: %s\n", archive_error_string(t->archive))); 1151 } 1152 if (r == ARCHIVE_FATAL) { 1153 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive))); 1154 err = 1; 1155 goto close_out; 1156 } 1157 1158 status = cli_writeall(cli, remote_fd, 0, buf, off, len, NULL); 1159 if (!NT_STATUS_IS_OK(status)) { 1160 DBG(0, ("Error writing remote file %s: %s\n", 1161 full_path, nt_errstr(status))); 1162 err = 1; 1163 goto close_out; 1164 } 1165 } 1166 1167 close_out: 1168 status = cli_close(cli, remote_fd); 1169 if (!NT_STATUS_IS_OK(status)) { 1170 DBG(0, ("Error losing remote file %s: %s\n", 1171 full_path, nt_errstr(status))); 1172 err = 1; 1173 } 1174 1175 out: 1176 talloc_free(ctx); 1177 return err; 1178 } 1179 1180 /** 1181 * tar_add_selection_path - add a path to the path list 1182 * @path: path to add 1183 */ 1184 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path) 1185 { 1186 const char **list; 1187 TALLOC_CTX *ctx = t->talloc_ctx; 1188 if (!t->path_list) { 1189 t->path_list = str_list_make_empty(ctx); 1190 if (t->path_list == NULL) { 1191 return NT_STATUS_NO_MEMORY; 1192 } 1193 t->path_list_size = 0; 1194 } 1195 1196 /* cast to silence gcc const-qual warning */ 1197 list = str_list_add((void *)t->path_list, path); 1198 if (list == NULL) { 1199 return NT_STATUS_NO_MEMORY; 1200 } 1201 t->path_list = discard_const_p(char *, list); 1202 t->path_list_size++; 1203 fix_unix_path(t->path_list[t->path_list_size - 1], true); 1204 1205 return NT_STATUS_OK; 1206 } 1207 1208 /** 1209 * tar_set_blocksize - set block size in TAR_BLOCK_UNIT 1210 */ 1211 static int tar_set_blocksize(struct tar *t, int size) 1212 { 1213 if (size <= 0 || size > TAR_MAX_BLOCK_SIZE) { 1214 return 1; 1215 } 1216 1217 t->mode.blocksize = size; 1218 1219 return 0; 1220 } 1221 1222 /** 1223 * tar_set_newer_than - set date threshold of saved files 1224 * @filename: local path to a file 1225 * 1226 * Only files newer than the modification time of @filename will be 1227 * saved. 1228 * 1229 * Note: this function set the global variable newer_than from 1230 * client.c. Thus the time is not a field of the tar structure. See 1231 * cmd_newer() to change its value from an interactive session. 1232 */ 1233 static int tar_set_newer_than(struct tar *t, const char *filename) 1234 { 1235 extern time_t newer_than; 1236 SMB_STRUCT_STAT stbuf; 1237 int rc; 1238 1239 rc = sys_stat(filename, &stbuf, false); 1240 if (rc != 0) { 1241 DBG(0, ("Error setting newer-than time\n")); 1242 return 1; 1243 } 1244 1245 newer_than = convert_timespec_to_time_t(stbuf.st_ex_mtime); 1246 DBG(1, ("Getting files newer than %s\n", time_to_asc(newer_than))); 1247 return 0; 1248 } 1249 1250 /** 1251 * tar_read_inclusion_file - set path list from file 1252 * @filename: path to the list file 1253 * 1254 * Read and add each line of @filename to the path list. 1255 */ 1256 static int tar_read_inclusion_file(struct tar *t, const char* filename) 1257 { 1258 char *line; 1259 int err = 0; 1260 int fd; 1261 TALLOC_CTX *ctx = talloc_new(NULL); 1262 if (ctx == NULL) { 1263 return 1; 1264 } 1265 1266 fd = open(filename, O_RDONLY); 1267 if (fd < 0) { 1268 DBG(0, ("Can't open inclusion file '%s': %s\n", filename, strerror(errno))); 1269 err = 1; 1270 goto out; 1271 } 1272 1273 for (line = afdgets(fd, ctx, 0); 1274 line != NULL; 1275 line = afdgets(fd, ctx, 0)) { 1276 NTSTATUS status; 1277 status = tar_add_selection_path(t, line); 1278 if (!NT_STATUS_IS_OK(status)) { 1279 err = 1; 1280 goto out; 1281 } 1282 } 1283 1284 close(fd); 1285 1286 out: 1287 talloc_free(ctx); 1288 return err; 1289 } 1290 1291 /** 1292 * tar_path_in_list - check whether @path is in the path list 1293 * @path: path to find 1294 * @reverse: when true also try to find path list element in @path 1295 * @_is_in_list: set if @path is in the path list 1296 * 1297 * Look at each path of the path list and set @_is_in_list if @path is a 1298 * subpath of one of them. 1299 * 1300 * If you want /path to be in the path list (path/a/, path/b/) set 1301 * @reverse to true to try to match the other way around. 1302 */ 1303 static NTSTATUS tar_path_in_list(struct tar *t, const char *path, 1304 bool reverse, bool *_is_in_list) 1305 { 1306 int i; 1307 const char *p; 1308 const char *pattern; 1309 1310 if (path == NULL || path[0] == '\0') { 1311 *_is_in_list = false; 1312 return NT_STATUS_OK; 1313 } 1314 1315 p = skip_useless_char_in_path(path); 1316 1317 for (i = 0; i < t->path_list_size; i++) { 1318 bool is_in_list; 1319 NTSTATUS status; 1320 1321 pattern = skip_useless_char_in_path(t->path_list[i]); 1322 status = is_subpath(p, pattern, &is_in_list); 1323 if (!NT_STATUS_IS_OK(status)) { 1324 return status; 1325 } 1326 if (reverse && !is_in_list) { 1327 status = is_subpath(pattern, p, &is_in_list); 1328 if (!NT_STATUS_IS_OK(status)) { 1329 return status; 1330 } 1331 } 1332 if (is_in_list) { 1333 *_is_in_list = true; 1334 return NT_STATUS_OK; 1335 } 1336 } 1337 1338 *_is_in_list = false; 1339 return NT_STATUS_OK; 1340 } 1341 1342 /** 1343 * tar_extract_skip_path - check if @entry should be skipped 1344 * @entry: current tar entry 1345 * @_skip: set true if path should be skipped, otherwise false 1346 * 1347 * Skip predicate for tar extraction (archive to server) only. 1348 */ 1349 static NTSTATUS tar_extract_skip_path(struct tar *t, 1350 struct archive_entry *entry, 1351 bool *_skip) 1352 { 1353 const char *fullpath = archive_entry_pathname(entry); 1354 bool in = true; 1355 1356 if (t->path_list_size <= 0) { 1357 *_skip = false; 1358 return NT_STATUS_OK; 1359 } 1360 1361 if (t->mode.regex) { 1362 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true); 1363 } else { 1364 NTSTATUS status = tar_path_in_list(t, fullpath, false, &in); 1365 if (!NT_STATUS_IS_OK(status)) { 1366 return status; 1367 } 1368 } 1369 1370 if (t->mode.selection == TAR_EXCLUDE) { 1371 *_skip = in; 1372 } else { 1373 *_skip = !in; 1374 } 1375 1376 return NT_STATUS_OK; 1377 } 1378 1379 /** 1380 * tar_create_skip_path - check if @fullpath shoud be skipped 1381 * @fullpath: full remote path of the current file 1382 * @finfo: remote file attributes 1383 * @_skip: returned skip not 1384 * 1385 * Skip predicate for tar creation (server to archive) only. 1386 */ 1387 static NTSTATUS tar_create_skip_path(struct tar *t, 1388 const char *fullpath, 1389 const struct file_info *finfo, 1390 bool *_skip) 1391 { 1392 /* syntaxic sugar */ 1393 const mode_t mode = finfo->mode; 1394 const bool isdir = mode & FILE_ATTRIBUTE_DIRECTORY; 1395 const bool exclude = t->mode.selection == TAR_EXCLUDE; 1396 bool in = true; 1397 1398 if (!isdir) { 1399 1400 /* 1. if we don't want X and we have X, skip */ 1401 if (!t->mode.system && (mode & FILE_ATTRIBUTE_SYSTEM)) { 1402 *_skip = true; 1403 return NT_STATUS_OK; 1404 } 1405 1406 if (!t->mode.hidden && (mode & FILE_ATTRIBUTE_HIDDEN)) { 1407 *_skip = true; 1408 return NT_STATUS_OK; 1409 } 1410 1411 /* 2. if we only want archive and it's not, skip */ 1412 1413 if (t->mode.incremental && !(mode & FILE_ATTRIBUTE_ARCHIVE)) { 1414 *_skip = true; 1415 return NT_STATUS_OK; 1416 } 1417 } 1418 1419 /* 3. is it in the selection list? */ 1420 1421 /* 1422 * tar_create_from_list() use the include list as a starting 1423 * point, no need to check 1424 */ 1425 if (!exclude) { 1426 *_skip = false; 1427 return NT_STATUS_OK; 1428 } 1429 1430 /* we are now in exclude mode */ 1431 1432 /* no matter the selection, no list => include everything */ 1433 if (t->path_list_size <= 0) { 1434 *_skip = false; 1435 return NT_STATUS_OK; 1436 } 1437 1438 if (t->mode.regex) { 1439 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true); 1440 } else { 1441 bool reverse = isdir && !exclude; 1442 NTSTATUS status = tar_path_in_list(t, fullpath, reverse, &in); 1443 if (!NT_STATUS_IS_OK(status)) { 1444 return status; 1445 } 1446 } 1447 *_skip = in; 1448 1449 return NT_STATUS_OK; 1450 } 1451 1452 /** 1453 * tar_to_process - return true if @t is ready to be processed 1454 * 1455 * @t is ready if it properly parsed command line arguments. 1456 */ 1457 bool tar_to_process(struct tar *t) 1458 { 1459 if (t == NULL) { 1460 DBG(0, ("Invalid tar context\n")); 1461 return false; 1462 } 1463 return t->to_process; 1464 } 1465 1466 /** 1467 * skip_useless_char_in_path - skip leading slashes/dots 1468 * 1469 * Skip leading slashes, backslashes and dot-slashes. 1470 */ 1471 static const char* skip_useless_char_in_path(const char *p) 1472 { 1473 while (p) { 1474 if (*p == '/' || *p == '\\') { 1475 p++; 1476 } 1477 else if (p[0] == '.' && (p[1] == '/' || p[1] == '\\')) { 1478 p += 2; 1479 } 1480 else 1481 return p; 1482 } 1483 return p; 1484 } 1485 1486 /** 1487 * is_subpath - check if the path @sub is a subpath of @full. 1488 * @sub: path to test 1489 * @full: container path 1490 * @_subpath_match: set true if @sub is a subpath of @full, otherwise false 1491 * 1492 * String comparaison is case-insensitive. 1493 */ 1494 static NTSTATUS is_subpath(const char *sub, const char *full, 1495 bool *_subpath_match) 1496 { 838 1497 NTSTATUS status = NT_STATUS_OK; 839 840 if (strequal(finfo->name,"..") || strequal(finfo->name,".")) { 841 status = NT_STATUS_OK; 842 goto cleanup; 843 } 844 845 /* Is it on the exclude list ? */ 846 if (!tar_excl && clipn) { 847 char *exclaim; 848 849 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir()))); 850 851 exclaim = talloc_asprintf(ctx, 852 "%s\\%s", 853 client_get_cur_dir(), 854 finfo->name); 855 if (!exclaim) { 856 status = NT_STATUS_NO_MEMORY; 857 goto cleanup; 858 } 859 860 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search)); 861 862 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) || 863 (tar_re_search && mask_match_list(exclaim, cliplist, clipn, True))) { 864 DEBUG(3,("Skipping file %s\n", exclaim)); 865 TALLOC_FREE(exclaim); 866 status = NT_STATUS_OK; 867 goto cleanup; 868 } 869 TALLOC_FREE(exclaim); 870 } 871 872 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) { 873 char *saved_curdir = NULL; 874 char *new_cd = NULL; 875 char *mtar_mask = NULL; 876 877 saved_curdir = talloc_strdup(ctx, client_get_cur_dir()); 878 if (!saved_curdir) { 879 status = NT_STATUS_NO_MEMORY; 880 goto cleanup; 881 } 882 883 DEBUG(5, ("strlen(cur_dir)=%d, \ 884 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", 885 (int)strlen(saved_curdir), 886 (int)strlen(finfo->name), finfo->name, saved_curdir)); 887 888 new_cd = talloc_asprintf(ctx, 889 "%s%s\\", 890 client_get_cur_dir(), 891 finfo->name); 892 if (!new_cd) { 893 status = NT_STATUS_NO_MEMORY; 894 goto cleanup; 895 } 896 client_set_cur_dir(new_cd); 897 898 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir())); 899 900 /* write a tar directory, don't bother with mode - just 901 * set it to 40755 */ 902 writetarheader(tarhandle, client_get_cur_dir(), 0, 903 finfo->mtime_ts.tv_sec, "040755 \0", '5'); 904 if (tar_noisy) { 905 DEBUG(0,(" directory %s\n", 906 client_get_cur_dir())); 907 } 908 ntarf++; /* Make sure we have a file on there */ 909 mtar_mask = talloc_asprintf(ctx, 910 "%s*", 911 client_get_cur_dir()); 912 if (!mtar_mask) { 913 status = NT_STATUS_NO_MEMORY; 914 goto cleanup; 915 } 916 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask)); 917 do_list(mtar_mask, attribute, do_tar, False, True); 918 client_set_cur_dir(saved_curdir); 919 TALLOC_FREE(saved_curdir); 920 TALLOC_FREE(new_cd); 921 TALLOC_FREE(mtar_mask); 922 } else { 923 char *rname = talloc_asprintf(ctx, 924 "%s%s", 925 client_get_cur_dir(), 926 finfo->name); 927 if (!rname) { 928 status = NT_STATUS_NO_MEMORY; 929 goto cleanup; 930 } 931 status = do_atar(rname,finfo->name,finfo); 932 TALLOC_FREE(rname); 933 } 934 935 cleanup: 936 TALLOC_FREE(ctx); 1498 int len = 0; 1499 char *f, *s; 1500 TALLOC_CTX *tmp_ctx = talloc_new(NULL); 1501 if (tmp_ctx == NULL) { 1502 status = NT_STATUS_NO_MEMORY; 1503 goto out; 1504 } 1505 1506 f = strlower_talloc(tmp_ctx, full); 1507 if (f == NULL) { 1508 status = NT_STATUS_NO_MEMORY; 1509 goto out_ctx_free; 1510 } 1511 string_replace(f, '\\', '/'); 1512 s = strlower_talloc(tmp_ctx, sub); 1513 if (f == NULL) { 1514 status = NT_STATUS_NO_MEMORY; 1515 goto out_ctx_free; 1516 } 1517 string_replace(s, '\\', '/'); 1518 1519 /* find the point where sub and full diverge */ 1520 while ((*f != '\0') && (*s != '\0') && (*f == *s)) { 1521 f++; 1522 s++; 1523 len++; 1524 } 1525 1526 if ((*f == '\0') && (*s == '\0')) { 1527 *_subpath_match = true; /* sub and full match */ 1528 goto out_ctx_free; 1529 } 1530 1531 if ((*f == '\0') && (len > 0) && (*(f - 1) == '/')) { 1532 /* sub diverges from full at path separator */ 1533 *_subpath_match = true; 1534 goto out_ctx_free; 1535 } 1536 1537 if ((*s == '\0') && (strcmp(f, "/") == 0)) { 1538 /* full diverges from sub with trailing slash only */ 1539 *_subpath_match = true; 1540 goto out_ctx_free; 1541 } 1542 1543 if ((*s == '/') && (*f == '\0')) { 1544 /* sub diverges from full with extra path component */ 1545 *_subpath_match = true; 1546 goto out_ctx_free; 1547 } 1548 *_subpath_match = false; 1549 1550 out_ctx_free: 1551 talloc_free(tmp_ctx); 1552 out: 937 1553 return status; 938 1554 } 939 1555 940 /**************************************************************************** 941 Convert from UNIX to DOS file names 942 ***************************************************************************/ 943 944 static void unfixtarname(char *tptr, char *fp, int l, bool first) 945 { 946 /* remove '.' from start of file name, convert from unix /'s to 947 * dos \'s in path. Kill any absolute path names. But only if first! 1556 1557 /** 1558 * make_remote_path - recursively make remote dirs 1559 * @full_path: full hierarchy to create 1560 * 1561 * Create @full_path and each parent directories as needed. 1562 */ 1563 static int make_remote_path(const char *full_path) 1564 { 1565 extern struct cli_state *cli; 1566 char *path; 1567 char *subpath; 1568 char *state; 1569 char *last_backslash; 1570 char *p; 1571 int len; 1572 NTSTATUS status; 1573 int err = 0; 1574 TALLOC_CTX *ctx = talloc_new(NULL); 1575 if (ctx == NULL) { 1576 return 1; 1577 } 1578 1579 subpath = talloc_strdup(ctx, full_path); 1580 if (subpath == NULL) { 1581 err = 1; 1582 goto out; 1583 } 1584 path = talloc_strdup(ctx, full_path); 1585 if (path == NULL) { 1586 err = 1; 1587 goto out; 1588 } 1589 len = talloc_get_size(path) - 1; 1590 1591 last_backslash = strrchr_m(path, '\\'); 1592 if (last_backslash == NULL) { 1593 goto out; 1594 } 1595 1596 *last_backslash = 0; 1597 1598 subpath[0] = 0; 1599 p = strtok_r(path, "\\", &state); 1600 1601 while (p != NULL) { 1602 strlcat(subpath, p, len); 1603 status = cli_chkpath(cli, subpath); 1604 if (!NT_STATUS_IS_OK(status)) { 1605 status = cli_mkdir(cli, subpath); 1606 if (!NT_STATUS_IS_OK(status)) { 1607 DBG(0, ("Can't mkdir %s: %s\n", subpath, nt_errstr(status))); 1608 err = 1; 1609 goto out; 1610 } 1611 DBG(3, ("mkdir %s\n", subpath)); 1612 } 1613 1614 strlcat(subpath, "\\", len); 1615 p = strtok_r(NULL, "/\\", &state); 1616 1617 } 1618 1619 out: 1620 talloc_free(ctx); 1621 return err; 1622 } 1623 1624 /** 1625 * tar_reset_mem_context - reset talloc context associated with @t 1626 * 1627 * At the start of the program the context is NULL so a new one is 1628 * allocated. On the following runs (interactive session only), simply 1629 * free the children. 1630 */ 1631 static TALLOC_CTX *tar_reset_mem_context(struct tar *t) 1632 { 1633 tar_free_mem_context(t); 1634 t->talloc_ctx = talloc_new(NULL); 1635 return t->talloc_ctx; 1636 } 1637 1638 /** 1639 * tar_free_mem_context - free talloc context associated with @t 1640 */ 1641 static void tar_free_mem_context(struct tar *t) 1642 { 1643 if (t->talloc_ctx) { 1644 talloc_free(t->talloc_ctx); 1645 t->talloc_ctx = NULL; 1646 t->path_list_size = 0; 1647 t->path_list = NULL; 1648 t->tar_path = NULL; 1649 } 1650 } 1651 1652 #define XSET(v) [v] = #v 1653 #define XTABLE(v, t) DBG(2, ("DUMP:%-20.20s = %s\n", #v, t[v])) 1654 #define XBOOL(v) DBG(2, ("DUMP:%-20.20s = %d\n", #v, v ? 1 : 0)) 1655 #define XSTR(v) DBG(2, ("DUMP:%-20.20s = %s\n", #v, v ? v : "NULL")) 1656 #define XINT(v) DBG(2, ("DUMP:%-20.20s = %d\n", #v, v)) 1657 #define XUINT64(v) DBG(2, ("DUMP:%-20.20s = %" PRIu64 "\n", #v, v)) 1658 1659 /** 1660 * tar_dump - dump tar structure on stdout 1661 */ 1662 static void tar_dump(struct tar *t) 1663 { 1664 int i; 1665 const char* op[] = { 1666 XSET(TAR_NO_OPERATION), 1667 XSET(TAR_CREATE), 1668 XSET(TAR_EXTRACT), 1669 }; 1670 1671 const char* sel[] = { 1672 XSET(TAR_NO_SELECTION), 1673 XSET(TAR_INCLUDE), 1674 XSET(TAR_EXCLUDE), 1675 }; 1676 1677 XBOOL(t->to_process); 1678 XTABLE(t->mode.operation, op); 1679 XTABLE(t->mode.selection, sel); 1680 XINT(t->mode.blocksize); 1681 XBOOL(t->mode.hidden); 1682 XBOOL(t->mode.system); 1683 XBOOL(t->mode.incremental); 1684 XBOOL(t->mode.reset); 1685 XBOOL(t->mode.dry); 1686 XBOOL(t->mode.verbose); 1687 XUINT64(t->total_size); 1688 XSTR(t->tar_path); 1689 XINT(t->path_list_size); 1690 1691 for (i = 0; t->path_list && t->path_list[i]; i++) { 1692 DBG(2, ("DUMP: t->path_list[%2d] = %s\n", i, t->path_list[i])); 1693 } 1694 1695 DBG(2, ("DUMP:t->path_list @ %p (%d elem)\n", t->path_list, i)); 1696 } 1697 #undef XSET 1698 #undef XTABLE 1699 #undef XBOOL 1700 #undef XSTR 1701 #undef XINT 1702 1703 /** 1704 * max_token - return upper limit for the number of token in @str 1705 * 1706 * The result is not exact, the actual number of token might be less 1707 * than what is returned. 1708 */ 1709 static int max_token(const char *str) 1710 { 1711 const char *s; 1712 int nb = 0; 1713 1714 if (str == NULL) { 1715 return 0; 1716 } 1717 1718 s = str; 1719 while (s[0] != '\0') { 1720 if (isspace((int)s[0])) { 1721 nb++; 1722 } 1723 s++; 1724 } 1725 1726 nb++; 1727 1728 return nb; 1729 } 1730 1731 /** 1732 * fix_unix_path - convert @path to a DOS path 1733 * @path: path to convert 1734 * @removeprefix: if true, remove leading ./ or /. 1735 */ 1736 static char *fix_unix_path(char *path, bool do_remove_prefix) 1737 { 1738 char *from = path, *to = path; 1739 1740 if (path == NULL || path[0] == '\0') { 1741 return path; 1742 } 1743 1744 /* remove prefix: 1745 * ./path => path 1746 * /path => path 948 1747 */ 949 950 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l)); 951 952 if (first) { 953 if (*fp == '.') { 954 fp++; 955 l--; 956 } 957 if (*fp == '\\' || *fp == '/') { 958 fp++; 959 l--; 960 } 961 } 962 963 safe_strcpy(tptr, fp, l); 964 string_replace(tptr, '/', '\\'); 965 } 966 967 /**************************************************************************** 968 Move to the next block in the buffer, which may mean read in another set of 969 blocks. FIXME, we should allow more than one block to be skipped. 970 ****************************************************************************/ 971 972 static int next_block(char *ltarbuf, char **bufferp, int bufsiz) 973 { 974 int bufread, total = 0; 975 976 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp)); 977 *bufferp += TBLOCK; 978 total = TBLOCK; 979 980 if (*bufferp >= (ltarbuf + bufsiz)) { 981 982 DEBUG(5, ("Reading more data into ltarbuf ...\n")); 983 984 /* 985 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net> 986 * Fixes bug where read can return short if coming from 987 * a pipe. 988 */ 989 990 bufread = read(tarhandle, ltarbuf, bufsiz); 991 total = bufread; 992 993 while (total < bufsiz) { 994 if (bufread < 0) { /* An error, return false */ 995 return (total > 0 ? -2 : bufread); 996 } 997 if (bufread == 0) { 998 if (total <= 0) { 999 return -2; 1000 } 1001 break; 1002 } 1003 bufread = read(tarhandle, <arbuf[total], bufsiz - total); 1004 total += bufread; 1005 } 1006 1007 DEBUG(5, ("Total bytes read ... %i\n", total)); 1008 1009 *bufferp = ltarbuf; 1010 } 1011 1012 return(total); 1013 } 1014 1015 /* Skip a file, even if it includes a long file name? */ 1016 static int skip_file(int skipsize) 1017 { 1018 int dsize = skipsize; 1019 1020 DEBUG(5, ("Skiping file. Size = %i\n", skipsize)); 1021 1022 /* FIXME, we should skip more than one block at a time */ 1023 1024 while (dsize > 0) { 1025 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { 1026 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); 1027 return(False); 1028 } 1029 dsize -= TBLOCK; 1030 } 1031 1032 return(True); 1033 } 1034 1035 /************************************************************* 1036 Get a file from the tar file and store it. 1037 When this is called, tarbuf already contains the first 1038 file block. This is a bit broken & needs fixing. 1039 **************************************************************/ 1040 1041 static int get_file(file_info2 finfo) 1042 { 1043 uint16_t fnum = (uint16_t) -1; 1044 int dsize = 0, bpos = 0; 1045 uint64_t rsize = 0, pos = 0; 1046 NTSTATUS status; 1047 1048 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size)); 1049 1050 if (!ensurepath(finfo.name)) { 1051 DEBUG(0, ("abandoning restore\n")); 1052 return False; 1053 } 1054 1055 status = cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum); 1056 if (!NT_STATUS_IS_OK(status)) { 1057 DEBUG(0, ("abandoning restore\n")); 1058 return False; 1059 } 1060 1061 /* read the blocks from the tar file and write to the remote file */ 1062 1063 rsize = finfo.size; /* This is how much to write */ 1064 1065 while (rsize > 0) { 1066 1067 /* We can only write up to the end of the buffer */ 1068 dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, 65520); /* Calculate the size to write */ 1069 dsize = MIN(dsize, rsize); /* Should be only what is left */ 1070 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos)); 1071 1072 status = cli_writeall(cli, fnum, 0, 1073 (uint8_t *)(buffer_p + bpos), pos, 1074 dsize, NULL); 1075 if (!NT_STATUS_IS_OK(status)) { 1076 DEBUG(0, ("Error writing remote file: %s\n", 1077 nt_errstr(status))); 1078 return 0; 1079 } 1080 1081 rsize -= dsize; 1082 pos += dsize; 1083 1084 /* Now figure out how much to move in the buffer */ 1085 1086 /* FIXME, we should skip more than one block at a time */ 1087 1088 /* First, skip any initial part of the part written that is left over */ 1089 /* from the end of the first TBLOCK */ 1090 1091 if ((bpos) && ((bpos + dsize) >= TBLOCK)) { 1092 dsize -= (TBLOCK - bpos); /* Get rid of the end of the first block */ 1093 bpos = 0; 1094 1095 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { /* and skip the block */ 1096 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); 1097 return False; 1098 } 1099 } 1100 1101 /* 1102 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>. 1103 * If the file being extracted is an exact multiple of 1104 * TBLOCK bytes then we don't want to extract the next 1105 * block from the tarfile here, as it will be done in 1106 * the caller of get_file(). 1107 */ 1108 1109 while (((rsize != 0) && (dsize >= TBLOCK)) || 1110 ((rsize == 0) && (dsize > TBLOCK))) { 1111 1112 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { 1113 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); 1114 return False; 1115 } 1116 1117 dsize -= TBLOCK; 1118 } 1119 bpos = dsize; 1120 } 1121 1122 /* Now close the file ... */ 1123 1124 if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) { 1125 DEBUG(0, ("Error %s closing remote file\n", 1126 cli_errstr(cli))); 1127 return(False); 1128 } 1129 1130 /* Now we update the creation date ... */ 1131 DEBUG(5, ("Updating creation date on %s\n", finfo.name)); 1132 1133 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec))) { 1134 if (tar_real_noisy) { 1135 DEBUG(0, ("Could not set time on file: %s\n", finfo.name)); 1136 /*return(False); */ /* Ignore, as Win95 does not allow changes */ 1137 } 1138 } 1139 1140 ntarf++; 1141 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo.name, (double)finfo.size)); 1142 return(True); 1143 } 1144 1145 /* Create a directory. We just ensure that the path exists and return as there 1146 is no file associated with a directory 1147 */ 1148 static int get_dir(file_info2 finfo) 1149 { 1150 DEBUG(0, ("restore directory %s\n", finfo.name)); 1151 1152 if (!ensurepath(finfo.name)) { 1153 DEBUG(0, ("Problems creating directory\n")); 1154 return(False); 1155 } 1156 ntarf++; 1157 return(True); 1158 } 1159 1160 /* Get a file with a long file name ... first file has file name, next file 1161 has the data. We only want the long file name, as the loop in do_tarput 1162 will deal with the rest. 1163 */ 1164 static char *get_longfilename(file_info2 finfo) 1165 { 1166 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name 1167 * header call. */ 1168 int namesize = finfo.size + strlen(client_get_cur_dir()) + 2; 1169 char *longname = (char *)SMB_MALLOC(namesize); 1170 int offset = 0, left = finfo.size; 1171 bool first = True; 1172 1173 DEBUG(5, ("Restoring a long file name: %s\n", finfo.name)); 1174 DEBUG(5, ("Len = %.0f\n", (double)finfo.size)); 1175 1176 if (longname == NULL) { 1177 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize)); 1178 return(NULL); 1179 } 1180 1181 /* First, add cur_dir to the long file name */ 1182 1183 if (strlen(client_get_cur_dir()) > 0) { 1184 strncpy(longname, client_get_cur_dir(), namesize); 1185 offset = strlen(client_get_cur_dir()); 1186 } 1187 1188 /* Loop through the blocks picking up the name */ 1189 1190 while (left > 0) { 1191 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { 1192 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); 1193 SAFE_FREE(longname); 1194 return(NULL); 1195 } 1196 1197 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--); 1198 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p)); 1199 1200 offset += TBLOCK; 1201 left -= TBLOCK; 1202 } 1203 1204 return(longname); 1205 } 1206 1207 static void do_tarput(void) 1208 { 1209 file_info2 finfo; 1210 struct timespec tp_start; 1211 char *longfilename = NULL, linkflag; 1212 int skip = False; 1213 1214 ZERO_STRUCT(finfo); 1215 1216 clock_gettime_mono(&tp_start); 1217 DEBUG(5, ("RJS do_tarput called ...\n")); 1218 1219 buffer_p = tarbuf + tbufsiz; /* init this to force first read */ 1220 1221 /* Now read through those files ... */ 1222 while (True) { 1223 /* Get us to the next block, or the first block first time around */ 1224 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { 1225 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); 1226 SAFE_FREE(longfilename); 1227 return; 1228 } 1229 1230 DEBUG(5, ("Reading the next header ...\n")); 1231 1232 switch (readtarheader((union hblock *) buffer_p, 1233 &finfo, client_get_cur_dir())) { 1234 case -2: /* Hmm, not good, but not fatal */ 1235 DEBUG(0, ("Skipping %s...\n", finfo.name)); 1236 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && !skip_file(finfo.size)) { 1237 DEBUG(0, ("Short file, bailing out...\n")); 1238 SAFE_FREE(longfilename); 1239 return; 1240 } 1241 break; 1242 1243 case -1: 1244 DEBUG(0, ("abandoning restore, -1 from read tar header\n")); 1245 SAFE_FREE(longfilename); 1246 return; 1247 1248 case 0: /* chksum is zero - looks like an EOF */ 1249 DEBUG(0, ("tar: restored %d files and directories\n", ntarf)); 1250 SAFE_FREE(longfilename); 1251 return; /* Hmmm, bad here ... */ 1252 1253 default: 1254 /* No action */ 1255 break; 1256 } 1257 1258 /* Now, do we have a long file name? */ 1259 if (longfilename != NULL) { 1260 SAFE_FREE(finfo.name); /* Free the space already allocated */ 1261 finfo.name = longfilename; 1262 longfilename = NULL; 1263 } 1264 1265 /* Well, now we have a header, process the file ... */ 1266 /* Should we skip the file? We have the long name as well here */ 1267 skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) || 1268 (tar_re_search && mask_match_list(finfo.name, cliplist, clipn, True))); 1269 1270 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name)); 1271 if (skip) { 1272 skip_file(finfo.size); 1273 continue; 1274 } 1275 1276 /* We only get this far if we should process the file */ 1277 linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag; 1278 switch (linkflag) { 1279 case '0': /* Should use symbolic names--FIXME */ 1280 /* 1281 * Skip to the next block first, so we can get the file, FIXME, should 1282 * be in get_file ... 1283 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net> 1284 * Fixes bug where file size in tarfile is zero. 1285 */ 1286 if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) { 1287 DEBUG(0, ("Short file, bailing out...\n")); 1288 return; 1289 } 1290 if (!get_file(finfo)) { 1291 DEBUG(0, ("Abandoning restore\n")); 1292 return; 1293 } 1294 break; 1295 case '5': 1296 if (!get_dir(finfo)) { 1297 DEBUG(0, ("Abandoning restore \n")); 1298 return; 1299 } 1300 break; 1301 case 'L': 1302 SAFE_FREE(longfilename); 1303 longfilename = get_longfilename(finfo); 1304 if (!longfilename) { 1305 DEBUG(0, ("abandoning restore\n")); 1306 return; 1307 } 1308 DEBUG(5, ("Long file name: %s\n", longfilename)); 1309 break; 1310 1311 default: 1312 skip_file(finfo.size); /* Don't handle these yet */ 1313 break; 1314 } 1315 } 1316 } 1317 1318 /* 1319 * samba interactive commands 1320 */ 1321 1322 /**************************************************************************** 1323 Blocksize command 1324 ***************************************************************************/ 1748 if (do_remove_prefix) { 1749 /* /path */ 1750 if (path[0] == '/' || path[0] == '\\') { 1751 from += 1; 1752 } 1753 1754 /* ./path */ 1755 if (path[1] != '\0' && path[0] == '.' && (path[1] == '/' || path[1] == '\\')) { 1756 from += 2; 1757 } 1758 } 1759 1760 /* replace / with \ */ 1761 while (from[0] != '\0') { 1762 if (from[0] == '/') { 1763 to[0] = '\\'; 1764 } else { 1765 to[0] = from[0]; 1766 } 1767 1768 from++; 1769 to++; 1770 } 1771 to[0] = '\0'; 1772 1773 return path; 1774 } 1775 1776 /** 1777 * path_base_name - return @path basename 1778 * 1779 * If @path doesn't contain any directory separator return NULL. 1780 */ 1781 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base) 1782 { 1783 char *base = NULL; 1784 int last = -1; 1785 int i; 1786 1787 for (i = 0; path[i]; i++) { 1788 if (path[i] == '\\' || path[i] == '/') { 1789 last = i; 1790 } 1791 } 1792 1793 if (last >= 0) { 1794 base = talloc_strdup(ctx, path); 1795 if (base == NULL) { 1796 return NT_STATUS_NO_MEMORY; 1797 } 1798 1799 base[last] = 0; 1800 } 1801 1802 *_base = base; 1803 return NT_STATUS_OK; 1804 } 1805 1806 #else 1807 1808 #define NOT_IMPLEMENTED DEBUG(0, ("tar mode not compiled. build with --with-libarchive\n")) 1325 1809 1326 1810 int cmd_block(void) 1327 1811 { 1328 TALLOC_CTX *ctx = talloc_tos(); 1329 char *buf; 1330 int block; 1331 1332 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { 1333 DEBUG(0, ("blocksize <n>\n")); 1334 return 1; 1335 } 1336 1337 block=atoi(buf); 1338 if (block < 0 || block > 65535) { 1339 DEBUG(0, ("blocksize out of range")); 1340 return 1; 1341 } 1342 1343 blocksize=block; 1344 DEBUG(2,("blocksize is now %d\n", blocksize)); 1345 return 0; 1346 } 1347 1348 /**************************************************************************** 1349 command to set incremental / reset mode 1350 ***************************************************************************/ 1812 NOT_IMPLEMENTED; 1813 return 1; 1814 } 1351 1815 1352 1816 int cmd_tarmode(void) 1353 1817 { 1354 TALLOC_CTX *ctx = talloc_tos(); 1355 char *buf; 1356 1357 while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { 1358 if (strequal(buf, "full")) 1359 tar_inc=False; 1360 else if (strequal(buf, "inc")) 1361 tar_inc=True; 1362 else if (strequal(buf, "reset")) 1363 tar_reset=True; 1364 else if (strequal(buf, "noreset")) 1365 tar_reset=False; 1366 else if (strequal(buf, "system")) 1367 tar_system=True; 1368 else if (strequal(buf, "nosystem")) 1369 tar_system=False; 1370 else if (strequal(buf, "hidden")) 1371 tar_hidden=True; 1372 else if (strequal(buf, "nohidden")) 1373 tar_hidden=False; 1374 else if (strequal(buf, "verbose") || strequal(buf, "noquiet")) 1375 tar_noisy=True; 1376 else if (strequal(buf, "quiet") || strequal(buf, "noverbose")) 1377 tar_noisy=False; 1378 else 1379 DEBUG(0, ("tarmode: unrecognised option %s\n", buf)); 1380 TALLOC_FREE(buf); 1381 } 1382 1383 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n", 1384 tar_inc ? "incremental" : "full", 1385 tar_system ? "system" : "nosystem", 1386 tar_hidden ? "hidden" : "nohidden", 1387 tar_reset ? "reset" : "noreset", 1388 tar_noisy ? "verbose" : "quiet")); 1389 return 0; 1390 } 1391 1392 /**************************************************************************** 1393 Feeble attrib command 1394 ***************************************************************************/ 1395 1396 int cmd_setmode(void) 1397 { 1398 TALLOC_CTX *ctx = talloc_tos(); 1399 char *q; 1400 char *buf; 1401 char *fname = NULL; 1402 uint16 attra[2]; 1403 int direct=1; 1404 1405 attra[0] = attra[1] = 0; 1406 1407 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { 1408 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n")); 1409 return 1; 1410 } 1411 1412 fname = talloc_asprintf(ctx, 1413 "%s%s", 1414 client_get_cur_dir(), 1415 buf); 1416 if (!fname) { 1417 return 1; 1418 } 1419 1420 while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { 1421 q=buf; 1422 1423 while(*q) { 1424 switch (*q++) { 1425 case '+': 1426 direct=1; 1427 break; 1428 case '-': 1429 direct=0; 1430 break; 1431 case 'r': 1432 attra[direct]|=FILE_ATTRIBUTE_READONLY; 1433 break; 1434 case 'h': 1435 attra[direct]|=FILE_ATTRIBUTE_HIDDEN; 1436 break; 1437 case 's': 1438 attra[direct]|=FILE_ATTRIBUTE_SYSTEM; 1439 break; 1440 case 'a': 1441 attra[direct]|=FILE_ATTRIBUTE_ARCHIVE; 1442 break; 1443 default: 1444 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n")); 1445 return 1; 1446 } 1447 } 1448 } 1449 1450 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) { 1451 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n")); 1452 return 1; 1453 } 1454 1455 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET])); 1456 do_setrattr(fname, attra[ATTRSET], ATTRSET); 1457 do_setrattr(fname, attra[ATTRRESET], ATTRRESET); 1458 return 0; 1459 } 1460 1461 /** 1462 Convert list of tokens to array; dependent on above routine. 1463 Uses the global cmd_ptr from above - bit of a hack. 1464 **/ 1465 1466 static char **toktocliplist(int *ctok, const char *sep) 1467 { 1468 char *s=(char *)cmd_ptr; 1469 int ictok=0; 1470 char **ret, **iret; 1471 1472 if (!sep) 1473 sep = " \t\n\r"; 1474 1475 while(*s && strchr_m(sep,*s)) 1476 s++; 1477 1478 /* nothing left? */ 1479 if (!*s) 1480 return(NULL); 1481 1482 do { 1483 ictok++; 1484 while(*s && (!strchr_m(sep,*s))) 1485 s++; 1486 while(*s && strchr_m(sep,*s)) 1487 *s++=0; 1488 } while(*s); 1489 1490 *ctok=ictok; 1491 s=(char *)cmd_ptr; 1492 1493 if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1))) 1494 return NULL; 1495 1496 while(ictok--) { 1497 *iret++=s; 1498 if (ictok > 0) { 1499 while(*s++) 1500 ; 1501 while(!*s) 1502 s++; 1503 } 1504 } 1505 1506 ret[*ctok] = NULL; 1507 return ret; 1508 } 1509 1510 /**************************************************************************** 1511 Principal command for creating / extracting 1512 ***************************************************************************/ 1818 NOT_IMPLEMENTED; 1819 return 1; 1820 } 1513 1821 1514 1822 int cmd_tar(void) 1515 1823 { 1516 TALLOC_CTX *ctx = talloc_tos(); 1517 char *buf; 1518 char **argl = NULL; 1519 int argcl = 0; 1520 int ret; 1521 1522 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { 1523 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n")); 1524 return 1; 1525 } 1526 1527 argl=toktocliplist(&argcl, NULL); 1528 if (!tar_parseargs(argcl, argl, buf, 0)) { 1529 SAFE_FREE(argl); 1530 return 1; 1531 } 1532 1533 ret = process_tar(); 1534 SAFE_FREE(argl); 1535 return ret; 1536 } 1537 1538 /**************************************************************************** 1539 Command line (option) version 1540 ***************************************************************************/ 1541 1542 int process_tar(void) 1543 { 1544 TALLOC_CTX *ctx = talloc_tos(); 1545 int rc = 0; 1546 initarbuf(); 1547 switch(tar_type) { 1548 case 'x': 1549 1550 #if 0 1551 do_tarput2(); 1552 #else 1553 do_tarput(); 1824 NOT_IMPLEMENTED; 1825 return 1; 1826 } 1827 1828 int tar_process(struct tar* tar) 1829 { 1830 NOT_IMPLEMENTED; 1831 return 1; 1832 } 1833 1834 int tar_parse_args(struct tar *tar, const char *flag, const char **val, int valsize) 1835 { 1836 NOT_IMPLEMENTED; 1837 return 1; 1838 } 1839 1840 bool tar_to_process(struct tar *tar) 1841 { 1842 return false; 1843 } 1844 1845 struct tar *tar_get_ctx() 1846 { 1847 return NULL; 1848 } 1849 1554 1850 #endif 1555 SAFE_FREE(tarbuf);1556 close(tarhandle);1557 break;1558 case 'r':1559 case 'c':1560 if (clipn && tar_excl) {1561 int i;1562 char *tarmac = NULL;1563 1564 for (i=0; i<clipn; i++) {1565 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));1566 1567 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {1568 *(cliplist[i]+strlen(cliplist[i])-1)='\0';1569 }1570 1571 if (strrchr_m(cliplist[i], '\\')) {1572 char *p;1573 char saved_char;1574 char *saved_dir = talloc_strdup(ctx,1575 client_get_cur_dir());1576 if (!saved_dir) {1577 return 1;1578 }1579 1580 if (*cliplist[i]=='\\') {1581 tarmac = talloc_strdup(ctx,1582 cliplist[i]);1583 } else {1584 tarmac = talloc_asprintf(ctx,1585 "%s%s",1586 client_get_cur_dir(),1587 cliplist[i]);1588 }1589 if (!tarmac) {1590 return 1;1591 }1592 /*1593 * Strip off the last \\xxx1594 * xxx element of tarmac to set1595 * it as current directory.1596 */1597 p = strrchr_m(tarmac, '\\');1598 if (!p) {1599 return 1;1600 }1601 saved_char = p[1];1602 p[1] = '\0';1603 1604 client_set_cur_dir(tarmac);1605 1606 /*1607 * Restore the character we1608 * just replaced to1609 * put the pathname1610 * back as it was.1611 */1612 p[1] = saved_char;1613 1614 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));1615 do_list(tarmac,attribute,do_tar, False, True);1616 1617 client_set_cur_dir(saved_dir);1618 1619 TALLOC_FREE(saved_dir);1620 TALLOC_FREE(tarmac);1621 } else {1622 tarmac = talloc_asprintf(ctx,1623 "%s%s",1624 client_get_cur_dir(),1625 cliplist[i]);1626 if (!tarmac) {1627 return 1;1628 }1629 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));1630 do_list(tarmac,attribute,do_tar, False, True);1631 TALLOC_FREE(tarmac);1632 }1633 }1634 } else {1635 char *mask = talloc_asprintf(ctx,1636 "%s\\*",1637 client_get_cur_dir());1638 if (!mask) {1639 return 1;1640 }1641 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask));1642 do_list(mask,attribute,do_tar,False, True);1643 TALLOC_FREE(mask);1644 }1645 1646 if (ntarf) {1647 dotareof(tarhandle);1648 }1649 close(tarhandle);1650 SAFE_FREE(tarbuf);1651 1652 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf));1653 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf));1654 break;1655 }1656 1657 if (must_free_cliplist) {1658 int i;1659 for (i = 0; i < clipn; ++i) {1660 SAFE_FREE(cliplist[i]);1661 }1662 SAFE_FREE(cliplist);1663 cliplist = NULL;1664 clipn = 0;1665 must_free_cliplist = False;1666 }1667 return rc;1668 }1669 1670 /****************************************************************************1671 Find a token (filename) in a clip list1672 ***************************************************************************/1673 1674 static int clipfind(char **aret, int ret, char *tok)1675 {1676 if (aret==NULL)1677 return 0;1678 1679 /* ignore leading slashes or dots in token */1680 while(strchr_m("/\\.", *tok))1681 tok++;1682 1683 while(ret--) {1684 char *pkey=*aret++;1685 1686 /* ignore leading slashes or dots in list */1687 while(strchr_m("/\\.", *pkey))1688 pkey++;1689 1690 if (!strslashcmp(pkey, tok))1691 return 1;1692 }1693 return 0;1694 }1695 1696 /****************************************************************************1697 Read list of files to include from the file and initialize cliplist1698 accordingly.1699 ***************************************************************************/1700 1701 static int read_inclusion_file(char *filename)1702 {1703 XFILE *inclusion = NULL;1704 char buf[PATH_MAX + 1];1705 char *inclusion_buffer = NULL;1706 int inclusion_buffer_size = 0;1707 int inclusion_buffer_sofar = 0;1708 char *p;1709 char *tmpstr;1710 int i;1711 int error = 0;1712 1713 clipn = 0;1714 buf[PATH_MAX] = '\0'; /* guarantee null-termination */1715 if ((inclusion = x_fopen(filename, O_RDONLY, 0)) == NULL) {1716 /* XXX It would be better to include a reason for failure, but without1717 * autoconf, it's hard to use strerror, sys_errlist, etc.1718 */1719 DEBUG(0,("Unable to open inclusion file %s\n", filename));1720 return 0;1721 }1722 1723 while ((! error) && (x_fgets(buf, sizeof(buf)-1, inclusion))) {1724 if (inclusion_buffer == NULL) {1725 inclusion_buffer_size = 1024;1726 if ((inclusion_buffer = (char *)SMB_MALLOC(inclusion_buffer_size)) == NULL) {1727 DEBUG(0,("failure allocating buffer to read inclusion file\n"));1728 error = 1;1729 break;1730 }1731 }1732 1733 if (buf[strlen(buf)-1] == '\n') {1734 buf[strlen(buf)-1] = '\0';1735 }1736 1737 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {1738 inclusion_buffer_size *= 2;1739 inclusion_buffer = (char *)SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);1740 if (!inclusion_buffer) {1741 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",1742 inclusion_buffer_size));1743 error = 1;1744 break;1745 }1746 }1747 1748 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);1749 inclusion_buffer_sofar += strlen(buf) + 1;1750 clipn++;1751 }1752 x_fclose(inclusion);1753 1754 if (! error) {1755 /* Allocate an array of clipn + 1 char*'s for cliplist */1756 cliplist = SMB_MALLOC_ARRAY(char *, clipn + 1);1757 if (cliplist == NULL) {1758 DEBUG(0,("failure allocating memory for cliplist\n"));1759 error = 1;1760 } else {1761 cliplist[clipn] = NULL;1762 p = inclusion_buffer;1763 for (i = 0; (! error) && (i < clipn); i++) {1764 /* set current item to NULL so array will be null-terminated even if1765 * malloc fails below. */1766 cliplist[i] = NULL;1767 if ((tmpstr = (char *)SMB_MALLOC(strlen(p)+1)) == NULL) {1768 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));1769 error = 1;1770 } else {1771 unfixtarname(tmpstr, p, strlen(p) + 1, True);1772 cliplist[i] = tmpstr;1773 if ((p = strchr_m(p, '\000')) == NULL) {1774 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));1775 abort();1776 }1777 }1778 ++p;1779 }1780 must_free_cliplist = True;1781 }1782 }1783 1784 SAFE_FREE(inclusion_buffer);1785 if (error) {1786 if (cliplist) {1787 char **pp;1788 /* We know cliplist is always null-terminated */1789 for (pp = cliplist; *pp; ++pp) {1790 SAFE_FREE(*pp);1791 }1792 SAFE_FREE(cliplist);1793 cliplist = NULL;1794 must_free_cliplist = False;1795 }1796 return 0;1797 }1798 1799 /* cliplist and its elements are freed at the end of process_tar. */1800 return 1;1801 }1802 1803 /****************************************************************************1804 Parse tar arguments. Sets tar_type, tar_excl, etc.1805 ***************************************************************************/1806 1807 int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)1808 {1809 int newOptind = Optind;1810 char tar_clipfl='\0';1811 1812 /* Reset back to defaults - could be from interactive version1813 * reset mode and archive mode left as they are though1814 */1815 tar_type='\0';1816 tar_excl=True;1817 dry_run=False;1818 1819 while (*Optarg) {1820 switch(*Optarg++) {1821 case 'c':1822 tar_type='c';1823 break;1824 case 'x':1825 if (tar_type=='c') {1826 printf("Tar must be followed by only one of c or x.\n");1827 return 0;1828 }1829 tar_type='x';1830 break;1831 case 'b':1832 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {1833 DEBUG(0,("Option b must be followed by valid blocksize\n"));1834 return 0;1835 } else {1836 Optind++;1837 newOptind++;1838 }1839 break;1840 case 'g':1841 tar_inc=True;1842 break;1843 case 'N':1844 if (Optind>=argc) {1845 DEBUG(0,("Option N must be followed by valid file name\n"));1846 return 0;1847 } else {1848 SMB_STRUCT_STAT stbuf;1849 1850 if (sys_stat(argv[Optind], &stbuf,1851 false) == 0) {1852 newer_than = convert_timespec_to_time_t(1853 stbuf.st_ex_mtime);1854 DEBUG(1,("Getting files newer than %s",1855 time_to_asc(newer_than)));1856 newOptind++;1857 Optind++;1858 } else {1859 DEBUG(0,("Error setting newer-than time\n"));1860 return 0;1861 }1862 }1863 break;1864 case 'a':1865 tar_reset=True;1866 break;1867 case 'q':1868 tar_noisy=False;1869 break;1870 case 'I':1871 if (tar_clipfl) {1872 DEBUG(0,("Only one of I,X,F must be specified\n"));1873 return 0;1874 }1875 tar_clipfl='I';1876 break;1877 case 'X':1878 if (tar_clipfl) {1879 DEBUG(0,("Only one of I,X,F must be specified\n"));1880 return 0;1881 }1882 tar_clipfl='X';1883 break;1884 case 'F':1885 if (tar_clipfl) {1886 DEBUG(0,("Only one of I,X,F must be specified\n"));1887 return 0;1888 }1889 tar_clipfl='F';1890 break;1891 case 'r':1892 DEBUG(0, ("tar_re_search set\n"));1893 tar_re_search = True;1894 break;1895 case 'n':1896 if (tar_type == 'c') {1897 DEBUG(0, ("dry_run set\n"));1898 dry_run = True;1899 } else {1900 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));1901 return 0;1902 }1903 break;1904 default:1905 DEBUG(0,("Unknown tar option\n"));1906 return 0;1907 }1908 }1909 1910 if (!tar_type) {1911 printf("Option T must be followed by one of c or x.\n");1912 return 0;1913 }1914 1915 /* tar_excl is true if cliplist lists files to be included.1916 * Both 'I' and 'F' mean include. */1917 tar_excl=tar_clipfl!='X';1918 1919 if (tar_clipfl=='F') {1920 if (argc-Optind-1 != 1) {1921 DEBUG(0,("Option F must be followed by exactly one filename.\n"));1922 return 0;1923 }1924 newOptind++;1925 /* Optind points at the tar output file, Optind+1 at the inclusion file. */1926 if (! read_inclusion_file(argv[Optind+1])) {1927 return 0;1928 }1929 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */1930 char *tmpstr;1931 char **tmplist;1932 int clipcount;1933 1934 cliplist=argv+Optind+1;1935 clipn=argc-Optind-1;1936 clipcount = clipn;1937 1938 if ((tmplist=SMB_MALLOC_ARRAY(char *,clipn)) == NULL) {1939 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn));1940 return 0;1941 }1942 1943 for (clipcount = 0; clipcount < clipn; clipcount++) {1944 1945 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));1946 1947 if ((tmpstr = (char *)SMB_MALLOC(strlen(cliplist[clipcount])+1)) == NULL) {1948 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount));1949 SAFE_FREE(tmplist);1950 return 0;1951 }1952 1953 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);1954 tmplist[clipcount] = tmpstr;1955 DEBUG(5, ("Processed an item, %s\n", tmpstr));1956 1957 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));1958 }1959 1960 cliplist = tmplist;1961 must_free_cliplist = True;1962 1963 newOptind += clipn;1964 }1965 1966 if (Optind+1<argc && tar_re_search && tar_clipfl != 'F') {1967 /* Doing regular expression seaches not from an inclusion file. */1968 clipn=argc-Optind-1;1969 cliplist=argv+Optind+1;1970 newOptind += clipn;1971 }1972 1973 if (Optind>=argc || !strcmp(argv[Optind], "-")) {1974 /* Sets tar handle to either 0 or 1, as appropriate */1975 tarhandle=(tar_type=='c');1976 /*1977 * Make sure that dbf points to stderr if we are using stdout for1978 * tar output1979 */1980 if (tarhandle == 1) {1981 setup_logging("smbclient", DEBUG_STDERR);1982 }1983 if (!argv[Optind]) {1984 DEBUG(0,("Must specify tar filename\n"));1985 return 0;1986 }1987 if (!strcmp(argv[Optind], "-")) {1988 newOptind++;1989 }1990 1991 } else {1992 if (tar_type=='c' && dry_run) {1993 tarhandle=-1;1994 } else if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1)1995 || (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) {1996 DEBUG(0,("Error opening local file %s - %s\n", argv[Optind], strerror(errno)));1997 return(0);1998 }1999 newOptind++;2000 }2001 2002 return newOptind;2003 }
Note:
See TracChangeset
for help on using the changeset viewer.