SftpFile.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Security;
  5. using System.Globalization;
  6. using Renci.SshNet.Common;
  7. namespace Renci.SshNet.Sftp
  8. {
  9. /// <summary>
  10. /// Represents SFTP file information
  11. /// </summary>
  12. public class SftpFile
  13. {
  14. private SftpSession _sftpSession;
  15. /// <summary>
  16. /// Gets the file attributes.
  17. /// </summary>
  18. public SftpFileAttributes Attributes { get; private set; }
  19. /// <summary>
  20. /// Initializes a new instance of the <see cref="SftpFile"/> class.
  21. /// </summary>
  22. /// <param name="sftpSession">The SFTP session.</param>
  23. /// <param name="fullName">Full path of the directory or file.</param>
  24. /// <param name="attributes">Attributes of the directory or file.</param>
  25. /// <exception cref="ArgumentNullException"><paramref name="sftpSession"/> or <paramref name="fullName"/> is null.</exception>
  26. internal SftpFile(SftpSession sftpSession, string fullName, SftpFileAttributes attributes)
  27. {
  28. if (sftpSession == null)
  29. throw new SshConnectionException("Client not connected.");
  30. if (attributes == null)
  31. throw new ArgumentNullException("attributes");
  32. if (fullName == null)
  33. throw new ArgumentNullException("fullName");
  34. this._sftpSession = sftpSession;
  35. this.Attributes = attributes;
  36. this.Name = fullName.Substring(fullName.LastIndexOf('/') + 1);
  37. this.FullName = fullName;
  38. }
  39. /// <summary>
  40. /// Gets the full path of the directory or file.
  41. /// </summary>
  42. public string FullName { get; private set; }
  43. /// <summary>
  44. /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists.
  45. /// Otherwise, the Name property gets the name of the directory.
  46. /// </summary>
  47. public string Name { get; private set; }
  48. /// <summary>
  49. /// Gets or sets the time the current file or directory was last accessed.
  50. /// </summary>
  51. /// <value>
  52. /// The time that the current file or directory was last accessed.
  53. /// </value>
  54. public DateTime LastAccessTime
  55. {
  56. get
  57. {
  58. return this.Attributes.LastAccessTime;
  59. }
  60. set
  61. {
  62. this.Attributes.LastAccessTime = value;
  63. }
  64. }
  65. /// <summary>
  66. /// Gets or sets the time when the current file or directory was last written to.
  67. /// </summary>
  68. /// <value>
  69. /// The time the current file was last written.
  70. /// </value>
  71. public DateTime LastWriteTime
  72. {
  73. get
  74. {
  75. return this.Attributes.LastWriteTime;
  76. }
  77. set
  78. {
  79. this.Attributes.LastWriteTime = value;
  80. }
  81. }
  82. /// <summary>
  83. /// Gets or sets the time, in coordinated universal time (UTC), the current file or directory was last accessed.
  84. /// </summary>
  85. /// <value>
  86. /// The time that the current file or directory was last accessed.
  87. /// </value>
  88. public DateTime LastAccessTimeUtc
  89. {
  90. get
  91. {
  92. return this.Attributes.LastAccessTime.ToUniversalTime();
  93. }
  94. set
  95. {
  96. this.Attributes.LastAccessTime = value.ToLocalTime();
  97. }
  98. }
  99. /// <summary>
  100. /// Gets or sets the time, in coordinated universal time (UTC), when the current file or directory was last written to.
  101. /// </summary>
  102. /// <value>
  103. /// The time the current file was last written.
  104. /// </value>
  105. public DateTime LastWriteTimeUtc
  106. {
  107. get
  108. {
  109. return this.Attributes.LastWriteTime.ToUniversalTime();
  110. }
  111. set
  112. {
  113. this.Attributes.LastWriteTime = value.ToLocalTime();
  114. }
  115. }
  116. /// <summary>
  117. /// Gets or sets the size, in bytes, of the current file.
  118. /// </summary>
  119. /// <value>
  120. /// The size of the current file in bytes.
  121. /// </value>
  122. public long Length
  123. {
  124. get
  125. {
  126. return this.Attributes.Size;
  127. }
  128. }
  129. /// <summary>
  130. /// Gets or sets file user id.
  131. /// </summary>
  132. /// <value>
  133. /// File user id.
  134. /// </value>
  135. public int UserId
  136. {
  137. get
  138. {
  139. return this.Attributes.UserId;
  140. }
  141. set
  142. {
  143. this.Attributes.UserId = value;
  144. }
  145. }
  146. /// <summary>
  147. /// Gets or sets file group id.
  148. /// </summary>
  149. /// <value>
  150. /// File group id.
  151. /// </value>
  152. public int GroupId
  153. {
  154. get
  155. {
  156. return this.Attributes.GroupId;
  157. }
  158. set
  159. {
  160. this.Attributes.GroupId = value;
  161. }
  162. }
  163. /// <summary>
  164. /// Gets a value indicating whether file represents a socket.
  165. /// </summary>
  166. /// <value>
  167. /// <c>true</c> if file represents a socket; otherwise, <c>false</c>.
  168. /// </value>
  169. public bool IsSocket
  170. {
  171. get
  172. {
  173. return this.Attributes.IsSocket;
  174. }
  175. }
  176. /// <summary>
  177. /// Gets a value indicating whether file represents a symbolic link.
  178. /// </summary>
  179. /// <value>
  180. /// <c>true</c> if file represents a symbolic link; otherwise, <c>false</c>.
  181. /// </value>
  182. public bool IsSymbolicLink
  183. {
  184. get
  185. {
  186. return this.Attributes.IsSymbolicLink;
  187. }
  188. }
  189. /// <summary>
  190. /// Gets a value indicating whether file represents a regular file.
  191. /// </summary>
  192. /// <value>
  193. /// <c>true</c> if file represents a regular file; otherwise, <c>false</c>.
  194. /// </value>
  195. public bool IsRegularFile
  196. {
  197. get
  198. {
  199. return this.Attributes.IsRegularFile;
  200. }
  201. }
  202. /// <summary>
  203. /// Gets a value indicating whether file represents a block device.
  204. /// </summary>
  205. /// <value>
  206. /// <c>true</c> if file represents a block device; otherwise, <c>false</c>.
  207. /// </value>
  208. public bool IsBlockDevice
  209. {
  210. get
  211. {
  212. return this.Attributes.IsBlockDevice;
  213. }
  214. }
  215. /// <summary>
  216. /// Gets a value indicating whether file represents a directory.
  217. /// </summary>
  218. /// <value>
  219. /// <c>true</c> if file represents a directory; otherwise, <c>false</c>.
  220. /// </value>
  221. public bool IsDirectory
  222. {
  223. get
  224. {
  225. return this.Attributes.IsDirectory;
  226. }
  227. }
  228. /// <summary>
  229. /// Gets a value indicating whether file represents a character device.
  230. /// </summary>
  231. /// <value>
  232. /// <c>true</c> if file represents a character device; otherwise, <c>false</c>.
  233. /// </value>
  234. public bool IsCharacterDevice
  235. {
  236. get
  237. {
  238. return this.Attributes.IsCharacterDevice;
  239. }
  240. }
  241. /// <summary>
  242. /// Gets a value indicating whether file represents a named pipe.
  243. /// </summary>
  244. /// <value>
  245. /// <c>true</c> if file represents a named pipe; otherwise, <c>false</c>.
  246. /// </value>
  247. public bool IsNamedPipe
  248. {
  249. get
  250. {
  251. return this.Attributes.IsNamedPipe;
  252. }
  253. }
  254. /// <summary>
  255. /// Gets or sets a value indicating whether the owner can read from this file.
  256. /// </summary>
  257. /// <value>
  258. /// <c>true</c> if owner can read from this file; otherwise, <c>false</c>.
  259. /// </value>
  260. public bool OwnerCanRead
  261. {
  262. get
  263. {
  264. return this.Attributes.OwnerCanRead;
  265. }
  266. set
  267. {
  268. this.Attributes.OwnerCanRead = value;
  269. }
  270. }
  271. /// <summary>
  272. /// Gets or sets a value indicating whether the owner can write into this file.
  273. /// </summary>
  274. /// <value>
  275. /// <c>true</c> if owner can write into this file; otherwise, <c>false</c>.
  276. /// </value>
  277. public bool OwnerCanWrite
  278. {
  279. get
  280. {
  281. return this.Attributes.OwnerCanWrite;
  282. }
  283. set
  284. {
  285. this.Attributes.OwnerCanWrite = value;
  286. }
  287. }
  288. /// <summary>
  289. /// Gets or sets a value indicating whether the owner can execute this file.
  290. /// </summary>
  291. /// <value>
  292. /// <c>true</c> if owner can execute this file; otherwise, <c>false</c>.
  293. /// </value>
  294. public bool OwnerCanExecute
  295. {
  296. get
  297. {
  298. return this.Attributes.OwnerCanExecute;
  299. }
  300. set
  301. {
  302. this.Attributes.OwnerCanExecute = value;
  303. }
  304. }
  305. /// <summary>
  306. /// Gets or sets a value indicating whether the group members can read from this file.
  307. /// </summary>
  308. /// <value>
  309. /// <c>true</c> if group members can read from this file; otherwise, <c>false</c>.
  310. /// </value>
  311. public bool GroupCanRead
  312. {
  313. get
  314. {
  315. return this.Attributes.GroupCanRead;
  316. }
  317. set
  318. {
  319. this.Attributes.GroupCanRead = value;
  320. }
  321. }
  322. /// <summary>
  323. /// Gets or sets a value indicating whether the group members can write into this file.
  324. /// </summary>
  325. /// <value>
  326. /// <c>true</c> if group members can write into this file; otherwise, <c>false</c>.
  327. /// </value>
  328. public bool GroupCanWrite
  329. {
  330. get
  331. {
  332. return this.Attributes.GroupCanWrite;
  333. }
  334. set
  335. {
  336. this.Attributes.GroupCanWrite = value;
  337. }
  338. }
  339. /// <summary>
  340. /// Gets or sets a value indicating whether the group members can execute this file.
  341. /// </summary>
  342. /// <value>
  343. /// <c>true</c> if group members can execute this file; otherwise, <c>false</c>.
  344. /// </value>
  345. public bool GroupCanExecute
  346. {
  347. get
  348. {
  349. return this.Attributes.GroupCanExecute;
  350. }
  351. set
  352. {
  353. this.Attributes.GroupCanExecute = value;
  354. }
  355. }
  356. /// <summary>
  357. /// Gets or sets a value indicating whether the others can read from this file.
  358. /// </summary>
  359. /// <value>
  360. /// <c>true</c> if others can read from this file; otherwise, <c>false</c>.
  361. /// </value>
  362. public bool OthersCanRead
  363. {
  364. get
  365. {
  366. return this.Attributes.OthersCanRead;
  367. }
  368. set
  369. {
  370. this.Attributes.OthersCanRead = value;
  371. }
  372. }
  373. /// <summary>
  374. /// Gets or sets a value indicating whether the others can write into this file.
  375. /// </summary>
  376. /// <value>
  377. /// <c>true</c> if others can write into this file; otherwise, <c>false</c>.
  378. /// </value>
  379. public bool OthersCanWrite
  380. {
  381. get
  382. {
  383. return this.Attributes.OthersCanWrite;
  384. }
  385. set
  386. {
  387. this.Attributes.OthersCanWrite = value;
  388. }
  389. }
  390. /// <summary>
  391. /// Gets or sets a value indicating whether the others can execute this file.
  392. /// </summary>
  393. /// <value>
  394. /// <c>true</c> if others can execute this file; otherwise, <c>false</c>.
  395. /// </value>
  396. public bool OthersCanExecute
  397. {
  398. get
  399. {
  400. return this.Attributes.OthersCanExecute;
  401. }
  402. set
  403. {
  404. this.Attributes.OthersCanExecute = value;
  405. }
  406. }
  407. /// <summary>
  408. /// Gets the extension part of the file.
  409. /// </summary>
  410. /// <value>
  411. /// File extensions.
  412. /// </value>
  413. public IDictionary<string, string> Extensions { get; private set; }
  414. /// <summary>
  415. /// Sets file permissions.
  416. /// </summary>
  417. /// <param name="mode">The mode.</param>
  418. public void SetPermissions(short mode)
  419. {
  420. this.Attributes.SetPermissions(mode);
  421. this.UpdateStatus();
  422. }
  423. /// <summary>
  424. /// Permanently deletes a file on remote machine.
  425. /// </summary>
  426. public void Delete()
  427. {
  428. if (this.IsDirectory)
  429. {
  430. this._sftpSession.RequestRmDir(this.FullName);
  431. }
  432. else
  433. {
  434. this._sftpSession.RequestRemove(this.FullName);
  435. }
  436. }
  437. /// <summary>
  438. /// Moves a specified file to a new location on remote machine, providing the option to specify a new file name.
  439. /// </summary>
  440. /// <param name="destFileName">The path to move the file to, which can specify a different file name.</param>
  441. /// <exception cref="ArgumentNullException"><paramref name="destFileName"/> is null.</exception>
  442. public void MoveTo(string destFileName)
  443. {
  444. if (destFileName == null)
  445. throw new ArgumentNullException("destFileName");
  446. this._sftpSession.RequestRename(this.FullName, destFileName);
  447. var fullPath = this._sftpSession.GetCanonicalPath(destFileName);
  448. this.Name = fullPath.Substring(fullPath.LastIndexOf('/') + 1);
  449. this.FullName = fullPath;
  450. }
  451. /// <summary>
  452. /// Updates file status on the server.
  453. /// </summary>
  454. public void UpdateStatus()
  455. {
  456. this._sftpSession.RequestSetStat(this.FullName, this.Attributes);
  457. }
  458. /// <summary>
  459. /// Returns a <see cref="System.String"/> that represents this instance.
  460. /// </summary>
  461. /// <returns>
  462. /// A <see cref="System.String"/> that represents this instance.
  463. /// </returns>
  464. public override string ToString()
  465. {
  466. return string.Format(CultureInfo.CurrentCulture, "Name {0}, Length {1}, User ID {2}, Group ID {3}, Accessed {4}, Modified {5}", this.Name, this.Length, this.UserId, this.GroupId, this.LastAccessTime, this.LastWriteTime);
  467. }
  468. }
  469. }