Seiichi NAMBA
1999-Apr-08 16:27 UTC
Keep-timestamp-in-`get'-patch for smbclient in samba-2.0.3
-------- --Multipart_Thu_Apr__8_13:33:51_1999-1 Content-Type: text/plain; charset=US-ASCII Hello guys, I always wondered why smbclient keeps timestamp in `put'ting a file but does not keep it in `get'ting a file. Alternative to keep the time stamp in `get'ting file is to use -Tc option or smbtar script, but they are a bit hairy for interactive use, and it can only dump files with an absolute pathname from the top of relevant service. This patch adds a NEW command `timestamp' to toggle the `timestamp' flag between `keep' and `new' (I don't know if these mnemonics are quite right in English context or not). If the flag `timestamp' is `keep' (BOOL:True), Windows file's timestamp (a_time and m_time) will be kept in corresponding UNIX file copied by `get' and `mget' command (`m*get' work like as in ncftp). # The copied a_time (access time) make sense for NT4.0 and samba-2.0.3 # server, but may be a garbage if the server is Windows98. If the flag `timestamp' is `new', `m*get' work as they are in old smbclient. The code is ugly, because I don't know anything about samba source tree structure and SMB protocol. Surely there must be smarter implementations than this quick and ready hack, but the code is working fine at least on linux-2.0.36 <=[m]get= Windows98/NT4.0/samba-2.0.3 server (Windows95 is not tested at all). Some development codes are still left between "#if 0" -- "#else|#endif". Sorry for inconvenience. I wish the new command might be adopted (with better code, not my lousy one) in official release, for I have to deal with Windows98 server and it stores timestamp-sensitive files... With my biggest gratitude for the great works of the Samba team, Seiichi PS. static BOOL timestamp = True /* means `keep' */ is my default in the patch. This may go well with DOS/Windows convention, but might have to be False as default for others who are familiar with the original smbclient's behaviour. To set it False (`new'), change the preceeding "#if 0" to "#if 1". Major defect of this patch is that a file attribute is read two times. I am not subscribing the mailing list (so sorry for interruption.), so kindly send an direct Email to my address below if you have any comment on this. The patch goes as the next part (applies on source/client/client.c). Seiichi NAMBA <sn@asahi-net.email.ne.jp> http://www.asahi-net.or.jp/~pi9s-nnb/ http://www.asahi-net.or.jp/~pi9s-nnb/dired-dd-home.html --Multipart_Thu_Apr__8_13:33:51_1999-1 Content-Type: text/plain; type=gzip; charset=US-ASCII Content-Disposition: attachment; filename="samba-2.0.3-smbcilent.get-with-timestamp.patch" Content-Transfer-Encoding: 7bit --- client/client.c.Org Sun Feb 28 07:08:58 1999 +++ client/client.c Thu Apr 8 12:42:08 1999 @@ -79,6 +79,13 @@ BOOL prompt = True; +/* s.n. Thu Apr 8 03:52:51 1999 my default is True (keep) */ +#if 0 +static BOOL timestamp = False; +#else +static BOOL timestamp = True; +#endif + int printmode = 1; static BOOL recurse = False; @@ -466,6 +473,19 @@ DEBUG(0, ("Total number of bytes: %d\n", dir_total)); } +/**************************************************************************** + get one fileinfo, used in do_get() s.n. Wed Apr 7 19:17:50 1999 + Ugly. Should write other interface to interpret_long_filename() ? + ****************************************************************************/ +static file_info an_finfo; /* Guess right to copy entity (not pointer). */ + +static void do_get_an_finfo(file_info *f, const char *mask) +{ + memcpy(&an_finfo,f,sizeof(*f)); + /* Debugger. + printf("do_get_an_finfo, a:%ld, m:%ld, mask:%s\n", + an_finfo->atime, an_finfo->mtime, mask); */ +} /**************************************************************************** get a file from rname to lname @@ -480,6 +500,11 @@ uint16 attr; size_t size; off_t nread = 0; + /* s.n. Tue Apr 6 21:53:25 1999 */ +#if 0 + time_t c_time, a_time, m_time, w_time; +#endif + struct utimbuf utb; GetTimeOfDay(&tp_start); @@ -506,6 +531,18 @@ } + /* s.n. Tue Apr 6 21:54:47 1999, to `keep' atime and mtime */ + /* Win98 returns 0's for [cam]_time etc. */ +#if 0 + if (!cli_qfileinfo(cli, fnum, + &attr, &size, &c_time, &a_time, &m_time, &w_time, + NULL) && + !cli_getattrE(cli, fnum, + &attr, &size, &c_time, &a_time, &m_time)) { + DEBUG(0,("getattrib: %s\n",cli_errstr(cli))); + return; + } +#else /* Use samba-2.0.3 original code here. see below. */ if (!cli_qfileinfo(cli, fnum, &attr, &size, NULL, NULL, NULL, NULL, NULL) && !cli_getattrE(cli, fnum, @@ -513,6 +550,7 @@ DEBUG(0,("getattrib: %s\n",cli_errstr(cli))); return; } +#endif DEBUG(2,("getting file %s of size %.0f as %s ", lname, (double)size, lname)); @@ -538,6 +576,36 @@ if (newhandle) { close(handle); + + /* s.n. Tue Apr 6 22:18:17 1999 */ + if (timestamp) { +#if 0 /* Unused */ + /* Works fine for NT/and linux samba-2.0.3 server, but + Win98 returns garbage a_time, m_time (Win95 not tested). + ( Using gmtime() is correct here ? ) + printf("a:%ld m:%ld\n", a_time, m_time); + printf("a:%s m:%s\n", ctime(&a_time), ctime(&m_time)); */ + utb.actime = mktime(gmtime(&a_time)); + utb.modtime = mktime(gmtime(&m_time)); +#else + uint16 attribute = aDIR | aSYSTEM | aHIDDEN; + + /* Use cmd_dir() type of interface here. */ + cli_list(cli, rname, attribute, do_get_an_finfo); + + /* Now rname's finfo is copied in an_finfo */ + utb.actime = mktime(LocalTime(&(an_finfo.atime))); + utb.modtime = mktime(LocalTime(&(an_finfo.mtime))); +#endif + /* The same hack in dos_utime() in samba-2.0.3's doscalls.c */ + if (utb.modtime == (time_t)0 || utb.modtime == (time_t)-1) + ; + else { + if (utb.actime == (time_t)0 || utb.actime == (time_t)-1) + utb.actime = utb.modtime; + utime(lname, &utb); + } + } } if (archive_level >= 2 && (attr & aARCH)) { @@ -555,7 +623,7 @@ get_total_time_ms += this_time; get_total_size += nread; - DEBUG(2,("(%g kb/s) (average %g kb/s)\n", + DEBUG(0,("(%g kb/s) (average %g kb/s)\n", nread / (1.024*this_time + 1.0e-4), get_total_size / (1.024*get_total_time_ms))); } @@ -1230,6 +1298,16 @@ /**************************************************************************** +toggle the timestamp flag s.n. Thu Apr 8 03:55:08 1999 +****************************************************************************/ +static void cmd_timestamp(void) +{ + timestamp = !timestamp; + DEBUG(2,("timestamp is now %s\n",timestamp?"keep":"new")); +} + + +/**************************************************************************** set the newer than time ****************************************************************************/ static void cmd_newer(void) @@ -1442,6 +1520,8 @@ {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}}, + /* s.n. Thu Apr 8 03:56:26 1999 */ + {"timestamp",cmd_timestamp,"toggle timestamp between keep and new for get and mget",{COMPL_NONE,COMPL_NONE}}, {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}}, {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}}, --Multipart_Thu_Apr__8_13:33:51_1999-1--