summaryrefslogtreecommitdiff
path: root/include/iprt/dir.h
blob: 54e235949db813e5286f3974bd9a60e11c75d2d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
/** @file
 * IPRT - Directory Manipulation.
 */

/*
 * Copyright (C) 2006-2012 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef ___iprt_dir_h
#define ___iprt_dir_h

#include <iprt/cdefs.h>
#include <iprt/types.h>
#include <iprt/fs.h>


RT_C_DECLS_BEGIN

/** @defgroup grp_rt_dir    RTDir - Directory Manipulation
 * @ingroup grp_rt
 * @{
 */

/**
 * Check for the existence of a directory.
 *
 * All symbolic links will be attemped resolved.  If that is undesirable, please
 * use RTPathQueryInfo instead.
 *
 * @returns true if exist and is a directory.
 * @returns false if not exists or isn't a directory.
 * @param   pszPath     Path to the directory.
 */
RTDECL(bool) RTDirExists(const char *pszPath);

/** @name RTDirCreate  flags.
 * @{ */
/** Don't allow symbolic links as part of the path.
 * @remarks this flag is currently not implemented and will be ignored. */
#define RTDIRCREATE_FLAGS_NO_SYMLINKS  RT_BIT(0)
/** @} */

/**
 * Creates a directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Path to the directory to create.
 * @param   fMode       The mode of the new directory.
 * @param   fCreate     Create flags, RTDIRCREATE_FLAGS_*.
 */
RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate);

/**
 * Creates a directory including all parent directories in the path
 * if they don't exist.
 *
 * @returns iprt status code.
 * @param   pszPath     Path to the directory to create.
 * @param   fMode       The mode of the new directories.
 */
RTDECL(int) RTDirCreateFullPath(const char *pszPath, RTFMODE fMode);

/**
 * Creates a new directory with a unique name using the given template.
 *
 * One or more trailing X'es in the template will be replaced by random alpha
 * numeric characters until a RTDirCreate succeeds or we run out of patience.
 * For instance:
 *          "/tmp/myprog-XXXXXX"
 *
 * As an alternative to trailing X'es, it
 * is possible to put 3 or more X'es somewhere inside the directory name. In
 * the following string only the last bunch of X'es will be modified:
 *          "/tmp/myprog-XXX-XXX.tmp"
 *
 * @returns iprt status code.
 * @param   pszTemplate     The directory name template on input. The actual
 *                          directory name on success. Empty string on failure.
 * @param   fMode           The mode to create the directory with.  Use 0700
 *                          unless you have reason not to.
 */
RTDECL(int) RTDirCreateTemp(char *pszTemplate, RTFMODE fMode);

/**
 * Secure version of @a RTDirCreateTemp with a fixed mode of 0700.
 *
 * This function behaves in the same way as @a RTDirCreateTemp with two
 * additional points.  Firstly the mode is fixed to 0700.  Secondly it will
 * fail if it is not possible to perform the operation securely.  Possible
 * reasons include that the directory could be removed by another unprivileged
 * user before it is used (e.g. if is created in a non-sticky /tmp directory)
 * or that the path contains symbolic links which another unprivileged user
 * could manipulate; however the exact criteria will be specified on a
 * platform-by-platform basis as platform support is added.
 * @see RTPathIsSecure for the current list of criteria.
 * @returns iprt status code.
 * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the
 *                             current platform at this time.
 * @returns VERR_INSECURE      if the directory could not be created securely.
 * @param   pszTemplate        The directory name template on input. The
 *                             actual directory name on success. Empty string
 *                             on failure.
 */
RTDECL(int) RTDirCreateTempSecure(char *pszTemplate);

/**
 * Creates a new directory with a unique name by appending a number.
 *
 * First it is tried to create the directory without any numbers appended.
 * When this fails a number string is appended (starting with 1) separated by
 * the optional separator. The numbers are zero padded.
 *
 * On success @a pszPath contains the path created.
 *
 * @returns iprt status code.
 * @param   pszPath     Path to the directory to create.
 * @param   cbSize      The size of pszPath. Needs enough space for holding the
 *                      digits and the optional separator.
 * @param   fMode       The mode of the new directory.
 * @param   cchDigits   How many digits should the number maximal have.
 * @param   chSep       The separator used between the path and the number. Can
 *                      be zero. (optional)
 */
RTDECL(int) RTDirCreateUniqueNumbered(char *pszPath, size_t cbSize, RTFMODE fMode, signed int cchDigits, char chSep);

/**
 * Removes a directory if empty.
 *
 * @returns iprt status code.
 * @param   pszPath         Path to the directory to remove.
 */
RTDECL(int) RTDirRemove(const char *pszPath);

/**
 * Removes a directory tree recursively.
 *
 * @returns iprt status code.
 * @param   pszPath         Path to the directory to remove recursively.
 * @param   fFlags          Flags, see RTDIRRMREC_F_XXX.
 *
 * @remarks This will not work on a root directory.
 */
RTDECL(int) RTDirRemoveRecursive(const char *pszPath, uint32_t fFlags);

/** @name   RTDirRemoveRecursive flags.
 * @{ */
/** Delete the content of the directory and the directory itself. */
#define RTDIRRMREC_F_CONTENT_AND_DIR    UINT32_C(0)
/** Only delete the content of the directory, omit the directory it self. */
#define RTDIRRMREC_F_CONTENT_ONLY       RT_BIT_32(0)
/** Mask of valid flags. */
#define RTDIRRMREC_F_VALID_MASK         UINT32_C(0x00000001)
/** @} */

/**
 * Flushes the specified directory.
 *
 * This API is not implemented on all systems.  On some systems it may be
 * unnecessary if you've already flushed the file.  If you really care for your
 * data and is entering dangerous territories, it doesn't hurt calling it after
 * flushing and closing the file.
 *
 * @returns IPRT status code.
 * @retval  VERR_NOT_IMPLEMENTED must be expected.
 * @retval  VERR_NOT_SUPPORTED must be expected.
 * @param   pszPath     Path to the directory.
 */
RTDECL(int) RTDirFlush(const char *pszPath);

/**
 * Flushes the parent directory of the specified file.
 *
 * This is just a wrapper around RTDirFlush.
 *
 * @returns IPRT status code, see RTDirFlush for details.
 * @param   pszChild    Path to the file which parent should be flushed.
 */
RTDECL(int) RTDirFlushParent(const char *pszChild);


/** Pointer to an open directory (sort of handle). */
typedef struct RTDIR *PRTDIR;


/**
 * Filter option for RTDirOpenFiltered().
 */
typedef enum RTDIRFILTER
{
    /** The usual invalid 0 entry. */
    RTDIRFILTER_INVALID = 0,
    /** No filter should be applied (and none was specified). */
    RTDIRFILTER_NONE,
    /** The Windows NT filter.
     * The following wildcard chars: *, ?, <, > and "
     * The matching is done on the uppercased strings.  */
    RTDIRFILTER_WINNT,
    /** The UNIX filter.
     * The following wildcard chars: *, ?, [..]
     * The matching is done on exact case. */
    RTDIRFILTER_UNIX,
    /** The UNIX filter, uppercased matching.
     * Same as RTDIRFILTER_UNIX except that the strings are uppercased before comparing. */
    RTDIRFILTER_UNIX_UPCASED,

    /** The usual full 32-bit value. */
    RTDIRFILTER_32BIT_HACK = 0x7fffffff
} RTDIRFILTER;


/**
 * Directory entry type.
 *
 * This is the RTFS_TYPE_MASK stuff shifted down 12 bits and
 * identical to the BSD/LINUX ABI.
 */
typedef enum RTDIRENTRYTYPE
{
    /** Unknown type (DT_UNKNOWN). */
    RTDIRENTRYTYPE_UNKNOWN          = 0,
    /** Named pipe (fifo) (DT_FIFO). */
    RTDIRENTRYTYPE_FIFO             = 001,
    /** Character device (DT_CHR). */
    RTDIRENTRYTYPE_DEV_CHAR         = 002,
    /** Directory (DT_DIR). */
    RTDIRENTRYTYPE_DIRECTORY        = 004,
    /** Block device (DT_BLK). */
    RTDIRENTRYTYPE_DEV_BLOCK        = 006,
    /** Regular file (DT_REG). */
    RTDIRENTRYTYPE_FILE             = 010,
    /** Symbolic link (DT_LNK). */
    RTDIRENTRYTYPE_SYMLINK          = 012,
    /** Socket (DT_SOCK). */
    RTDIRENTRYTYPE_SOCKET           = 014,
    /** Whiteout (DT_WHT). */
    RTDIRENTRYTYPE_WHITEOUT         = 016
} RTDIRENTRYTYPE;


/**
 * Directory entry.
 *
 * This is inspired by the POSIX interfaces.
 */
#pragma pack(1)
typedef struct RTDIRENTRY
{
    /** The unique identifier (within the file system) of this file system object (d_ino).
     *
     * Together with INodeIdDevice, this field can be used as a OS wide unique id
     * when both their values are not 0.  This field is 0 if the information is not
     * available. */
    RTINODE         INodeId;
    /** The entry type. (d_type)
     * RTDIRENTRYTYPE_UNKNOWN is a common return value here since not all file
     * systems (or Unixes) stores the type of a directory entry and instead
     * expects the user to use stat() to get it.  So, when you see this you
     * should use RTDirQueryUnknownType or RTDirQueryUnknownTypeEx to get the type,
     * or if if you're lazy, use RTDirReadEx. */
    RTDIRENTRYTYPE  enmType;
    /** The length of the filename, excluding the terminating nul character. */
    uint16_t        cbName;
    /** The filename. (no path)
     * Using the pcbDirEntry parameter of RTDirRead makes this field variable in size. */
    char            szName[260];
} RTDIRENTRY;
#pragma pack()
/** Pointer to a directory entry. */
typedef RTDIRENTRY *PRTDIRENTRY;
/** Pointer to a const directory entry. */
typedef RTDIRENTRY const *PCRTDIRENTRY;


/**
 * Directory entry with extended information.
 *
 * This is inspired by the PC interfaces.
 */
#pragma pack(1)
typedef struct RTDIRENTRYEX
{
    /** Full information about the object. */
    RTFSOBJINFO     Info;
    /** The length of the short field (number of RTUTF16 entries (not chars)).
     * It is 16-bit for reasons of alignment. */
    uint16_t        cwcShortName;
    /** The short name for 8.3 compatibility.
     * Empty string if not available.
     * Since the length is a bit tricky for a UTF-8 encoded name, and since this
     * is practically speaking only a windows thing, it is encoded as UCS-2. */
    RTUTF16         wszShortName[14];
    /** The length of the filename. */
    uint16_t        cbName;
    /** The filename. (no path)
     * Using the pcbDirEntry parameter of RTDirReadEx makes this field variable in size. */
    char            szName[260];
} RTDIRENTRYEX;
#pragma pack()
/** Pointer to a directory entry. */
typedef RTDIRENTRYEX *PRTDIRENTRYEX;
/** Pointer to a const directory entry. */
typedef RTDIRENTRYEX const *PCRTDIRENTRYEX;


/**
 * Opens a directory.
 *
 * @returns iprt status code.
 * @param   ppDir       Where to store the open directory pointer.
 * @param   pszPath     Path to the directory to open.
 */
RTDECL(int) RTDirOpen(PRTDIR *ppDir, const char *pszPath);

/** @name RTDirOpenFiltered  flags.
 * @{ */
/** Don't allow symbolic links as part of the path.
 * @remarks this flag is currently not implemented and will be ignored. */
#define RTDIROPEN_FLAGS_NO_SYMLINKS  RT_BIT(0)
/** @} */

/**
 * Opens a directory filtering the entries using dos style wildcards.
 *
 * @returns iprt status code.
 * @param   ppDir       Where to store the open directory pointer.
 * @param   pszPath     Path to the directory to search, this must include wildcards.
 * @param   enmFilter   The kind of filter to apply. Setting this to RTDIRFILTER_NONE makes
 *                      this function behave like RTDirOpen.
 * @param   fOpen       Open flags, RTDIROPENFILTERED_FLAGS_*.
 */
RTDECL(int) RTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fOpen);

/**
 * Closes a directory.
 *
 * @returns iprt status code.
 * @param   pDir        Pointer to open directory returned by RTDirOpen() or RTDirOpenFiltered().
 */
RTDECL(int) RTDirClose(PRTDIR pDir);

/**
 * Reads the next entry in the directory.
 *
 * @returns VINF_SUCCESS and data in pDirEntry on success.
 * @returns VERR_NO_MORE_FILES when the end of the directory has been reached.
 * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If
 *          pcbDirEntry is specified it will be updated with the required buffer size.
 * @returns suitable iprt status code on other errors.
 *
 * @param   pDir        Pointer to the open directory.
 * @param   pDirEntry   Where to store the information about the next
 *                      directory entry on success.
 * @param   pcbDirEntry Optional parameter used for variable buffer size.
 *
 *                      On input the variable pointed to contains the size of the pDirEntry
 *                      structure. This must be at least OFFSET(RTDIRENTRY, szName[2]) bytes.
 *
 *                      On successful output the field is updated to
 *                      OFFSET(RTDIRENTRY, szName[pDirEntry->cbName + 1]).
 *
 *                      When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is
 *                      returned, this field contains the required buffer size.
 *
 *                      The value is unchanged in all other cases.
 */
RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry);

/**
 * Reads the next entry in the directory returning extended information.
 *
 * @returns VINF_SUCCESS and data in pDirEntry on success.
 * @returns VERR_NO_MORE_FILES when the end of the directory has been reached.
 * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If
 *          pcbDirEntry is specified it will be updated with the required buffer size.
 * @returns suitable iprt status code on other errors.
 *
 * @param   pDir        Pointer to the open directory.
 * @param   pDirEntry   Where to store the information about the next
 *                      directory entry on success.
 * @param   pcbDirEntry Optional parameter used for variable buffer size.
 *
 *                      On input the variable pointed to contains the size of the pDirEntry
 *                      structure. This must be at least OFFSET(RTDIRENTRYEX, szName[2]) bytes.
 *
 *                      On successful output the field is updated to
 *                      OFFSET(RTDIRENTRYEX, szName[pDirEntry->cbName + 1]).
 *
 *                      When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is
 *                      returned, this field contains the required buffer size.
 *
 *                      The value is unchanged in all other cases.
 * @param   enmAdditionalAttribs
 *                      Which set of additional attributes to request.
 *                      Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
 * @param   fFlags      RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
 */
RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags);

/**
 * Resolves RTDIRENTRYTYPE_UNKNOWN values returned by RTDirRead.
 *
 * @returns IPRT status code (see RTPathQueryInfo).
 * @param   pszComposedName The path to the directory entry. The caller must
 *                          compose this, it's NOT sufficient to pass
 *                          RTDIRENTRY::szName!
 * @param   fFollowSymlinks Whether to follow symbolic links or not.
 * @param   penmType        Pointer to the RTDIRENTRY::enmType member.  If this
 *                          is not RTDIRENTRYTYPE_UNKNOWN and, if
 *                          @a fFollowSymlinks is false, not
 *                          RTDIRENTRYTYPE_SYMLINK, the function will return
 *                          immediately without doing anything.  Otherwise it
 *                          will use RTPathQueryInfo to try figure out the
 *                          correct value.  On failure, this will be unchanged.
 */
RTDECL(int) RTDirQueryUnknownType(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType);

/**
 * Resolves RTDIRENTRYTYPE_UNKNOWN values returned by RTDirRead, extended
 * version.
 *
 * @returns IPRT status code (see RTPathQueryInfo).
 * @param   pszComposedName The path to the directory entry. The caller must
 *                          compose this, it's NOT sufficient to pass
 *                          RTDIRENTRY::szName!
 * @param   fFollowSymlinks Whether to follow symbolic links or not.
 * @param   penmType        Pointer to the RTDIRENTRY::enmType member or
 *                          similar.  Will NOT be checked on input.
 * @param   pObjInfo        The object info buffer to use with RTPathQueryInfo.
 */
RTDECL(int) RTDirQueryUnknownTypeEx(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType, PRTFSOBJINFO pObjInfo);

/**
 * Checks if the directory entry returned by RTDirRead is '.', '..' or similar.
 *
 * @returns true / false.
 * @param   pDirEntry       The directory entry to check.
 */
RTDECL(bool) RTDirEntryIsStdDotLink(PRTDIRENTRY pDirEntry);

/**
 * Checks if the directory entry returned by RTDirReadEx is '.', '..' or
 * similar.
 *
 * @returns true / false.
 * @param   pDirEntryEx     The extended directory entry to check.
 */
RTDECL(bool) RTDirEntryExIsStdDotLink(PCRTDIRENTRYEX pDirEntryEx);

/**
 * Renames a file.
 *
 * Identical to RTPathRename except that it will ensure that the source is a directory.
 *
 * @returns IPRT status code.
 * @returns VERR_ALREADY_EXISTS if the destination file exists.
 *
 * @param   pszSrc      The path to the source file.
 * @param   pszDst      The path to the destination file.
 *                      This file will be created.
 * @param   fRename     See RTPathRename.
 */
RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename);


/**
 * Query information about an open directory.
 *
 * @returns iprt status code.
 *
 * @param   pDir        Pointer to the open directory.
 * @param   pObjInfo                Object information structure to be filled on successful return.
 * @param   enmAdditionalAttribs    Which set of additional attributes to request.
 *                                  Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
 */
RTR3DECL(int) RTDirQueryInfo(PRTDIR pDir, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs);


/**
 * Changes one or more of the timestamps associated of file system object.
 *
 * @returns iprt status code.
 * @returns VERR_NOT_SUPPORTED is returned if the operation isn't supported by the OS.
 *
 * @param   pDir        Pointer to the open directory.
 * @param   pAccessTime         Pointer to the new access time. NULL if not to be changed.
 * @param   pModificationTime   Pointer to the new modifcation time. NULL if not to be changed.
 * @param   pChangeTime         Pointer to the new change time. NULL if not to be changed.
 * @param   pBirthTime          Pointer to the new time of birth. NULL if not to be changed.
 *
 * @remark  The file system might not implement all these time attributes,
 *          the API will ignore the ones which aren't supported.
 *
 * @remark  The file system might not implement the time resolution
 *          employed by this interface, the time will be chopped to fit.
 *
 * @remark  The file system may update the change time even if it's
 *          not specified.
 *
 * @remark  POSIX can only set Access & Modification and will always set both.
 */
RTR3DECL(int) RTDirSetTimes(PRTDIR pDir, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
                            PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);

/** @} */

RT_C_DECLS_END

#endif