libndr: Avoid assigning duplicate versions to symbols
[amitay/samba.git] / source3 / lib / file_id.c
index 026d2f8d27d1fa01ccda3585aa57cebe9d8ec7c5..0cc5a56bc27a131e11c732061c3da902fc734cf9 100644 (file)
@@ -1,20 +1,20 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    file_id structure handling
 
    Copyright (C) Andrew Tridgell 2007
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -31,17 +31,15 @@ bool file_id_equal(const struct file_id *id1, const struct file_id *id2)
            id1->extid == id2->extid;
 }
 
-/*
-  a static string for a file_id structure
- */
-const char *file_id_string_tos(const struct file_id *id)
+char *file_id_str_buf(struct file_id fid, struct file_id_buf *dst)
 {
-       char *result = talloc_asprintf(talloc_tos(), "%llx:%llx:%llx",
-                                      (unsigned long long)id->devid, 
-                                      (unsigned long long)id->inode,
-                                      (unsigned long long)id->extid);
-       SMB_ASSERT(result != NULL);
-       return result;
+       snprintf(dst->buf,
+                sizeof(dst->buf),
+                "%"PRIu64":%"PRIu64":%"PRIu64,
+                fid.devid,
+                fid.inode,
+                fid.extid);
+       return dst->buf;
 }
 
 /*
@@ -72,7 +70,7 @@ void push_file_id_24(char *buf, const struct file_id *id)
 /*
   pull a 24 byte version of a file id from a buffer
  */
-void pull_file_id_24(char *buf, struct file_id *id)
+void pull_file_id_24(const char *buf, struct file_id *id)
 {
        ZERO_STRUCTP(id);
        id->devid  = IVAL(buf,  0);
@@ -82,3 +80,39 @@ void pull_file_id_24(char *buf, struct file_id *id)
        id->extid  = IVAL(buf,  16);
        id->extid |= ((uint64_t)IVAL(buf,20))<<32;
 }
+
+uint64_t make_file_id_from_itime(SMB_STRUCT_STAT *st)
+{
+       struct timespec itime = st->st_ex_itime;
+       ino_t ino = st->st_ex_ino;
+       uint64_t file_id_low;
+       uint64_t file_id;
+
+       if (st->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME) {
+               return ino;
+       }
+
+       round_timespec_to_nttime(&itime);
+
+       file_id_low = itime.tv_nsec;
+       if (file_id_low == 0) {
+               /*
+                * This could be by coincidence, but more likely the filesystem
+                * is only giving us seconds granularity. We need more fine
+                * grained granularity for the File-ID, so combine with the
+                * inode number.
+                */
+               file_id_low = ino & ((1 << 30) - 1);
+       }
+
+       /*
+        * Set the high bit so ideally File-IDs based on inode numbers and
+        * File-IDs based on Birth Time use disjoint ranges, given inodes never
+        * have the high bit set.
+        */
+       file_id = ((uint64_t)1) << 63;
+       file_id |= (uint64_t)itime.tv_sec << 30;
+       file_id |= file_id_low;
+
+       return file_id;
+}